From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/CMD/NLSFUNC/DOESMAC.INC | 40 + v4.0/src/CMD/NLSFUNC/FUNCDBCS.INC | 18 + v4.0/src/CMD/NLSFUNC/FUNCPARM.INC | 33 + v4.0/src/CMD/NLSFUNC/MAKEFILE | 45 + v4.0/src/CMD/NLSFUNC/MSG2NLS.INC | 93 ++ v4.0/src/CMD/NLSFUNC/NLSFUNC.ASM | 1811 +++++++++++++++++++++++++++++++++++++ v4.0/src/CMD/NLSFUNC/NLSFUNC.SKL | 15 + v4.0/src/CMD/NLSFUNC/NLSPARM.ASM | 148 +++ 8 files changed, 2203 insertions(+) create mode 100644 v4.0/src/CMD/NLSFUNC/DOESMAC.INC create mode 100644 v4.0/src/CMD/NLSFUNC/FUNCDBCS.INC create mode 100644 v4.0/src/CMD/NLSFUNC/FUNCPARM.INC create mode 100644 v4.0/src/CMD/NLSFUNC/MAKEFILE create mode 100644 v4.0/src/CMD/NLSFUNC/MSG2NLS.INC create mode 100644 v4.0/src/CMD/NLSFUNC/NLSFUNC.ASM create mode 100644 v4.0/src/CMD/NLSFUNC/NLSFUNC.SKL create mode 100644 v4.0/src/CMD/NLSFUNC/NLSPARM.ASM (limited to 'v4.0/src/CMD/NLSFUNC') diff --git a/v4.0/src/CMD/NLSFUNC/DOESMAC.INC b/v4.0/src/CMD/NLSFUNC/DOESMAC.INC new file mode 100644 index 0000000..0d98ade --- /dev/null +++ b/v4.0/src/CMD/NLSFUNC/DOESMAC.INC @@ -0,0 +1,40 @@ +CallInstall MACRO name,mpx,fn,save,restore +BREAK MACRO subtitle + SUBTTL subtitle + PAGE +ENDM +.xcref break +IF Installed + IFNB + SaveReg + ENDIF + MOV AX,(mpx SHL 8) + fn + INT 2Fh + IFNB + RestoreReg + ENDIF +ELSE + Invoke name +ENDIF +ENDM + +BREAK + +SaveReg MACRO reglist ;; push those registers +IRP reg, + ?stackdepth = ?stackdepth + 1 + PUSH reg +ENDM +ENDM +.xcref SaveReg + +BREAK + +RestoreReg MACRO reglist ;; pop those registers +IRP reg, + ?stackdepth = ?stackdepth - 1 + POP reg +ENDM +ENDM +.xcref RestoreReg + \ No newline at end of file diff --git a/v4.0/src/CMD/NLSFUNC/FUNCDBCS.INC b/v4.0/src/CMD/NLSFUNC/FUNCDBCS.INC new file mode 100644 index 0000000..b119765 --- /dev/null +++ b/v4.0/src/CMD/NLSFUNC/FUNCDBCS.INC @@ -0,0 +1,18 @@ +;; generic ioctl call data "packet" pointed to by DS:DX =E +PACKET STRUC ;USED BY MINOR CODES: 6AH,4AH,4DH (SELECT, QUERY SELECTED, PREPARE END) =E +PACKLEN DW 0 ;LENGTH OF PACKET IN BYTES =E 2/16/KK +PACKCPID DW 0 ;CODE PAGE ID =E +DBCS_EV DB 0,0 ; 2/16/KK + DB 0,0 ; 2/16/KK + DB 0,0 ; 2/16/KK + DB 0,0 ; 2/16/KK + DB 0,0 ; 2/16/KK + DB 0,0 ; 2/16/KK + DB 0,0 ; 2/16/KK + DB 0,0 ; 2/16/KK +PACKET ENDS + + +STD_CPLENGTH equ 2 +PK PACKET <> ;CNS + \ No newline at end of file diff --git a/v4.0/src/CMD/NLSFUNC/FUNCPARM.INC b/v4.0/src/CMD/NLSFUNC/FUNCPARM.INC new file mode 100644 index 0000000..3e6d18c --- /dev/null +++ b/v4.0/src/CMD/NLSFUNC/FUNCPARM.INC @@ -0,0 +1,33 @@ +;Parser INPUT PARM LIST Structure + + + NLS_PARMS label word + dw NLS_PARMSX + db 0 ;no extra delimiters + + NLS_PARMSX label word + db 0,1 ;Min 0 - no path + ;Max 1 - path + dw NLS_POS1 + + NLS_POS1 label word + dw 0201h ;File spec (optional) + dw 0001h ;Cap result by file + dw Res_Valptr ;tbl + dw NoVal ;no value list + db 0 ;no switch or + ;keyword synonyms + + +NOVAL label word + db 0 + + RES_VALPTR label word + + RES_TYPE db ? ;Result_type + RES_ITAG db 0 ;Matched item tag + RES_SYN dw 0 ;synonym returned + RES_POFF dw 0 ;drive type or beginning of string + RES_PSEG dw 0 ;may be string + + \ No newline at end of file diff --git a/v4.0/src/CMD/NLSFUNC/MAKEFILE b/v4.0/src/CMD/NLSFUNC/MAKEFILE new file mode 100644 index 0000000..912c42c --- /dev/null +++ b/v4.0/src/CMD/NLSFUNC/MAKEFILE @@ -0,0 +1,45 @@ +#************************** makefile for cmd\... *************************** + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: nlsfunc.exe + +nlsfunc.ctl: nlsfunc.skl \ + $(msg)\$(COUNTRY).msg \ + makefile + + +nlsfunc.obj: nlsfunc.asm \ + funcdbcs.inc \ + msg2nls.inc \ + funcparm.inc \ + nlsfunc.ctl \ + nlsfunc.cla \ + nlsfunc.cl1 \ + nlsfunc.cl2 \ + doesmac.inc \ + $(inc)\mult.inc \ + $(inc)\msgserv.asm \ + $(inc)\doscntry.inc \ + $(inc)\devsym.inc \ + $(inc)\struc.inc \ + $(inc)\copyrigh.inc \ + makefile + +nlsparm.obj: nlsparm.asm \ + $(inc)\parse.asm \ + $(inc)\psdata.inc \ + makefile + + + +nlsfunc.exe: nlsfunc.obj nlsparm.obj + link nlsfunc+nlsparm; + diff --git a/v4.0/src/CMD/NLSFUNC/MSG2NLS.INC b/v4.0/src/CMD/NLSFUNC/MSG2NLS.INC new file mode 100644 index 0000000..f52be80 --- /dev/null +++ b/v4.0/src/CMD/NLSFUNC/MSG2NLS.INC @@ -0,0 +1,93 @@ +BADDOS equ 1 +ALLINS equ 2 +FNF equ 3 +FLAG1 equ LEFT_ALIGN+CHAR_FIELD_ASCIIZ + +;***************************************************************************** +;****************************************************************************** +; VALUES FOR THE MSG_DESC CONTROL BLOCK +ONE_SUBS EQU 1 ;ONE VARIABLE FIELD IN MESSAGE +TWO_SUBS EQU 2 ;TWO VARIABLE FIELDS IN MESSAGE +THREE_SUBS EQU 3 ;THREE VARIABLE FIELDS IN MESSAGE +CLASS_1 EQU EXT_ERR_CLASS ;CLASS 1 (DOS EXTENDED ERRORS) +CLASS_2 EQU PARSE_ERR_CLASS ;CLASS 2 (PARSE ERRORS) +CLASS_A EQU UTILITY_MSG_CLASS ;CLASS A TYPE MESSAGE + +;THIS MESSAGE DESCRIPTOR CONTROL BLOCK IS GENERATED, ONE PER MESSAGE, +;TO DEFINE THE SEVERAL PARAMETERS THAT ARE EXPECTED TO BE PASSED IN +;CERTAIN REGISTERS WHEN THE SYSDISPMSG FUNCTION IS TO BE INVOKED. + +;MSG_DESC STRUC +;MSG_NUM DW 0 ;MESSAGE NUMBER (TO AX) +;MSG_HAND DW 0 ;HANDLE OF OUTPUT DEVICE (TO BX) +;MSG_SUBLIST Dd 0 ;POINTER TO SUBLIST (TO SI) +;MSG_COUNT DW 0 ;SUBSTITUTION COUNT (TO CX) +;MSG_CLASS DB 0 ;MESSAGE CLASS (IN HIGH BYTE, TO DH) +; ; LOW BYTE HAS 0 (FUNCTION "NO INPUT", TO DL) +;MSG_DESC ENDS +; VALUES FOR THE SUBLIST CONTROL BLOCK +PC_ID_0 EQU 0 ;ID OF " - " TRAILER TO MESSAGE +PC_ID_1 EQU 1 ;ID OF PERCENT VARIABLE FIELD +PC_ID_2 EQU 2 ;ID OF PERCENT VARIABLE FIELD +PC_ID_3 EQU 3 ;ID OF PERCENT VARIABLE FIELD +MAX_0 EQU 0 ;MAXIMUM WIDTH OF STRING FIELD (0=NO LIMIT) +MIN_1 EQU 1 ;MINIMUM WIDTH OF STRING FIELD +ID_0 EQU 0 + +;Message PARM LIST Structure + PARMLIST1 LABEL BYTE ;PARM LIST + ;(File not found - 'PATH_SPEC') + DB 11 ;PARMLIST size + DB 0 ;reserved + DD PATH_SPEC + DB id_0 ;; n of %n + DB FLAG1 ;; data type + DB max_0 ;;max width + DB min_1 ;;min width + DB PAD_CHAR ;;char defined to be space + + + PARMLIST2 LABEL BYTE ;PARM LIST + ;(NLSFUNC already installed) + DB 11 ;PARMLIST size + DB 0 ;reserved + DD UTILITY ;; ptr to data + DB 1 ;; n of %n + DB FLAG1 ;; data type + DB 0 ;;max width + DB 1 ;;min width + DB PAD_CHAR ;;char defined + + PARMLIST3 LABEL BYTE ;PARM LIST + ;(Invalid parameter 'PATH_SPEC') + DB 11 ;PARMLIST size + DB 0 ;reserved + DD PATH_SPEC ;; ptr to data + DB id_0 ;; n of %n + DB FLAG1 ;; data type + DB 0 ;;max width + DB 1 ;;min width + DB PAD_CHAR ;;char defined + +; THE NEXT GROUP ARE ALL CLASS "1" MESSAGES + +; PUBLIC MSGNUM_EXTERR +;MSGNUeM_EXTERR MSG_DESC ;ALL EXTENDED DOS ERRORS + ;File not found - %0 + +; THE NEXT GROUP ARE ALL CLASS "2" MESSAGES + +; PUBLIC MSGNUM_PARSE ;SO PARSE DRIVER CAN FIND IT +;MSGNUM_PARSE MSG_DESC <,STDERR,,,CLASS_2> ;ALL PARSING ERRORS BUT INVALID + ;SYNTAX + ;ERROR NUMBER WILL NEED TO BE FILLED IN + +; THE NEXT GROUP ARE ALL CLASS "A" MESSAGES +; THESE ARE THE "CANNED" MESSAGES ALWAYS PRESENT + +; PUBLIC MSGNUM_VER +;MSGNUM_VER MSG_DESC <1,STDERR> ;"Incorrect DOS Version" + +; PUBLIC MSGNUM_INST +;MSGNUM_INST MSG_DESC ;"%1 - already installed" +;end of MSGHAN.INC diff --git a/v4.0/src/CMD/NLSFUNC/NLSFUNC.ASM b/v4.0/src/CMD/NLSFUNC/NLSFUNC.ASM new file mode 100644 index 0000000..a855e3f --- /dev/null +++ b/v4.0/src/CMD/NLSFUNC/NLSFUNC.ASM @@ -0,0 +1,1811 @@ + + PAGE ,132 ; + TITLE NLSFUNC - GET/SET CP & COUNTRY INFO CHCP SUPPORT +;************************************************************************** +;This is the NLSFUNC int2f command that supports the INT21h functions +;Get_Extended Country Information and the Set_codepage... +;NLSFUNC will read the COUNTRY.SYS information from disk , store the +;data in a buffer , then move the information into a buffer +;area specified by DOS. +;d:NLSFUNC {path} +; * +;CHECKINSTALL: * +;CheckRequest proc * +; If installed previously * +; report back error already installed and exit * +; otherwise goto install * +;Checkrequest endp * +;************************************************************************* +; NEW CODE * +;************************************************************************* +subttl get extended country data +page +; +;*************************************** +;* Process_Path Procedure * +;*************************************** +;* CALL SYSLOADMSG * +;* Do DOS Version check * +;* If ne X.X then (carry set) * +;* CALL SYSDISPLAY_MSG * +;* DISPLAY_MSG(Message number 001) * +;* (001 - Incorrect DOS Version) * +;* (Class 3 - Utility Msg) * +;* exit * +;* else * +;* Establish addressability * +;* to command line parms (DS:SI) * +;* Establish addressability to PARM * +;* control block (ES:DI) * +;* * +;* Call SYSPARSE for filename * +;* GET Parse Block results * +;* IF PARSE_ERROR * +;* CALL SYSDISPLAY_MSG (Class 2)* +;* DISPLAY_MSG = PARSE_NUM * +;* ELSE * +;* SUCCESSFUL_PARSE (0 or -1) * +;* ENDIFELSE * +;* GET_PARSE_RESULTS Path_Spec * +;* IF No path exist then * +;* assume current directory * +;* assume default filename * +;* ENDIF * +;* IF No Drive exist then * +;* Use Current Drive * +;* ENDIF * +;* IF No filename exist then * +;* assume default filename * +;* and concatenate with drive * +;* ENDIF * +;* CHECK_PATH * +;* IF PATH EXIST THAN * +;* INSTALL_NLS (NLS_RESCODE) * +;* ENDIF * +;* ELSE NOT PATH_EXIST THAN * +;* GET_PARSE_RESULTS (Class 3) * +;* PASS_TO_MSGTXT (Message 003) * +;* (File not found %1) * +;* ERR_CODE SET TO 2 * +;* EXIT * +;* ENDIFELSE * +;* * +;* INSTALL_NLS * +;* CHECK INSTALL FLAG * +;* IF INSTALLED * +;* (Class 3) * +;* PASS_TO_MGSTXT (Msg 002) * +;* %1 already installed * +;* ELSE * +;* HOOK IN CODE * +;* TERMINATE & STAY RESIDENT * +;* ENDIFELSE * +;* * +;* * +;* EXIT * +;* CHECK FOR ERRORCODE * +;* exit to DOS * +;*************************************** +; +;INSTALL: +; Get the current 2f handler in the chain +; make it the next install my handler in the +; beginning of the the chain using get interrupt (25) +; and set interrupt (35); Once in the chain +; terminate and stay resident. +; +;DOS NEEDS ME....... +; +;Install Dos Interface Logic +; Dos issues Call Install +; Establish residency +; If Mult Id is mine (* NLSFUNC*) +; CheckInstall Status to see if installed or not +; otherwise +; jump to the next 2f handler +;CheckInstall +; If not installed returns +; If installed program is executed (*NLSFUNC resident portion *) +;******************************************************************************* +; +;Program Logic +; +; Check to make sure not reserved DOS number in the al +; +; Go establish which function is to be performed +; +;Sel_Func proc +; mov FUNC_CODE,al +; case +; function code = 0 +; function code = 1 +; function code = 2 +; function code = 3 +; function code = 4 +; otherwise error_routine +; return +;Sel_Func endp + + +;funcode0 proc +;INSTALL NLSFUNC must be installed in mem +; return 0FFh that I am installed +;funcode0 endp + +;funcode1 proc +; (* Means Set codepage and "select" device drivers*) +; same at funcode 3 plus device drivers are invoked with the +; specified code page. +;funcode1 endp + +;funcode2 proc +; (* Get_extended_country info issued by DOS not in buffer*) +; BP = info_type +; call trans_Cty_Data Proc +; return +;funcode2 endp + +;funcode3 proc +; (* Means Set codepage *) +; On entry DOS gives me the CODEP in BX & the CC in DX,SIZE in CX +; Search for Country.sys file on disk +; if file is found }BUFFER will exist in code 320 (can be altered) +; the control buffer = 64 bytes of the buffer +; the data buffer = 256 bytes of the buffer +; call Trans_Cty_Data Proc +; otherwise return an error flag +; return +;funcode3 endp + + +;funcode4 proc +; (* Get_extended_country info - old 38 call*) +; set flag and same as funcode 2 +; data returned slightly Revised +;funcode4 endp + +; **************************** +; if selected is FUNCTION 1, 3 +; PassDOS_Data(*ES:DI*) +; otherwise FUNCTION 2, 4 +; Get the INFO ID +; Flag that it is function 2 +; PassUserData(*ES:DI*) +; mov NO_ERRORS to ERROR_FLAG +; **************************** +;Trans_Cty_Data Proc +; Open file(Dos call back 38) +; Do an LSEEK to move CTY_INFO into NLSFUNC control buffer 39 +; Do an LSEEK to move tables into NLSFUNC data buffer 39 +; if R/W pointer ok on Disk +; Read the file(Dos call back 38) +; Check to see if it is FUNCTION 1 or FUNCTION 2 +; Flag if FUNCTION 2 +; if FUNCTION 2 +; Search for user specified INFO ID +; until found or report back error to DOS & exit +; if INFO ID is found +; godo move the data and set the counter to zero (entry value) +; +; +; +; +;MOVE_DATA: Manage transfer from disk to buffer +; Check to see if entire entry can fit in to the data +; buffer if not read the maximum allowed into buffer +; Check to see what is left to read; read until no more +; Search for appropriate field in the DOS INFO +; if found move in info until complete +; get the next entry until number of entries is 0 +; otherwise +; report to DOS error and exit +; loop back to read file until (all entries are Obtained) or (EOF) +; Close file handle (Dos call back 40) +; otherwise mov 05h to error_flag & jump to error_routine +; +; return +;Trans ENDP +; +; +;Error_routine proc +; mov al,error_flag +; return +;error_routine endp +;******************************************************************************* +;**********************************INTRO**************************************** +subttl Revision History +page +;****************************** Revision History *************************** ; +; +; =A 7/29/86 RG PTM P64 +; Prevent overwrite of DOS monocase routine entry point during +; transfer of SetCountryInfo. +; For Get Ext Cty Info, put DOS monocase routine entry point into +; user buffer. +; +; =B 7/29/86 RG PTM P67 +; Correct jump condition in ERROR_ROUTINE of NLSRES_CODE. +; This prevents exit without COUNTRY.SYS file close. +; +; =C 7/30/86 RG PTM P85 +; Preserve ES register in NLSFUNC for IBMDOS. +; +; =D 7/31/86 RG PTM P86 +; Corrects information put into user buffer for Get Extended +; Country Information. +; +; =E 7/31/85 RG DCR 18 +; CHCP support. +; +; =F 8/4/86 RG +; Get Country Info - Revised info from Get Extended Country Info +; +; =G 8/5/86 RG +; Correct carry set for good exit. +; +; =H 8/5/86 RG +; Start extended info at length instead of signature. +; +; =FC 8/14/86 FChen +; Insert code for control buff management and actual length retunred +; +; =I 8/20/86 RG +; Improve path parameter parsing. +; +; =J 8/22/86 RG +; Change error codes +; +; =K 8/28/86 RG +; 65 call-get ext cty info put final csize (# bytes returned) +; in cx on iret ; +; +; =L 11/7/86 RG +; Set error to INVALID DATA (13) on no cp/cty match. +; +; =M 05/20/87 CNS +; Additional re-design for structured code using STRUC +; PARSER implementation +; Message Retriever implementation +; DBCS Support for Environmental Vector recognition (Walk Devices& IOCTL call) +; Enable the Interrupt when NLSFUNC is loaded PTM ??? +; +;AN001; P2685 NLSFUNC should not visit the same device repeatedly. 01/15/88 J.K. +;AN002; P3934 Bad write on sacred DOS area - segmentation incorrect 03/22/88 CNS +;******************************************************************************* +subttl macros +page +PUSHALL macro reg1,reg2,reg3 ;used to save all + push reg1 ;registers needed + push reg2 ;for DOS interactions + push reg3 + endm + +POPALL macro reg1,reg2,reg3 ;used to restore all + pop reg3 ;for DOS interactions + pop reg2 + pop reg1 + endm + +;SHOWERR macro msg,len_msg +; mov ah,40h +; mov bx,2 +; lea dx,msg ;displays error msgs +; mov cx,len_msg +; int 21h +; endm + + +EXTRN SYSPARSE:NEAR + +subttl NLSFUNC data +page +NLS_DATA SEGMENT byte PUBLIC 'DATA' + +;Copyright 1988 Microsoft +;***************************** MSG DATA ************************************ +UTILITY db "NLSFUNC",0 ;AC000; +;***************************** MSG DATA ************************************ + +.xlist +include copyrigh.inc ;AN000; +include struc.inc +include DOESMAC.INC +include MULT.INC +include sf.inc ;AN001; +include DOSCNTRY.INC +include DEVSYM.INC +include SYSMSG.INC ;AN000; +include FUNCDBCS.INC ;AN000; +include MSG2NLS.INC +include FUNCPARM.INC ;AN000; + +MSG_UTILNAME ;AN000; + +.list +MULT_NLSFUNC equ 14h +INSTALLED equ 0ffh +; nlsfunc function codes +CHG_CODEPAGE equ 1 +GET_EXT_CTY_INFO equ 2 +SET_CODEPAGE equ 3 +GET_CTY_INFO equ 4 + +INVALID_FUNCTION equ 1 ;=J +INVALID_DATA equ 13 ;=L +;FILE_NOT_FOUND equ 2 ;=J(=L no longer explicitly used) +;TAB equ 9 +;CR equ 13 +PAD_CHAR equ ' ' ;AN000; +BAD_INVOKE equ 65 ;=E +UPCASE_A equ 'A' +BUFFSIZE equ 512 ; ;AC000;REDUCTION OF ORIGINAL (128 BYTES) TO STORE +LOCATE_INFOTYPE equ 18 ;THE DEVICE LIST & THE OLD COUNTRY INFO +CTL_BUFF equ 256 ; ;AC000; +ID_TAG equ 8 +DATA_BUFF_LENG equ (BUFFSIZE - CTL_BUFF) +MAXBUFF_FIT equ (BUFFSIZE - (CTL_BUFF + ID_TAG)) +DATA_N_ID equ (CTL_BUFF + ID_TAG) +SETCTY_LENG equ 38 +;SPACE equ ' ' +BACKSLASH equ '\' +PERIOD equ '.' +;COLON equ ':' +; +;**************** NEW VARIABLE **************** +subttl NLSFUNC data +page +IN_DEX equ bp ;AN000; +FILESPEC_PTR equ byte ptr ds:[in_dex] ;AN000; +FILEVAL equ 0100h ;convert data block after checking for the + ;AN000; + ;drive only to look for the filespec +CL_NUM equ 81h ;command line at the PSP + ;AN000; +;**************** NEW VARIABLE **************** +;interrupts +SET_INT equ 25h +GET_INT equ 35h +; +;dos call backs +;dosopen equ 38 +;dosclose equ 39 +;lseek equ 40 +;dosread equ 41 +; +;NO_ERRORS equ 0FFh + +;variable definition area +;initialization area + +MSG_SERVICES + +ID_CHECK db 1 ;resident variable re-initialize +ALL_DONE db 0 ;resident variable re-initialize +GET_EXT db 0 ;resident variable re-initialize +INFO_ID db 0 ;resident variable re-initialize +DONT_CLOSE db 0 ;if open or close error,this is set + +RES_PARASIZE dw 0 ;adjusted size for terminate & stay func. +ERROR_CODE db 0 ;contains extended error code val +FUNC_CODE db 0 ;save function number +GOOD_PAR db 0 +PARSE_ERR db 0 + +SI_DOSLOCATE dw 0 +DS_DOSLOCATE dw 0 +SAVEDX dw 0 ;=FC file offset +SAVECX dw 0 ;=FC +NOFFSET dw 2 ;=FC +CSIZE dw 0 +CCODE dw 0 +CPAGE dw 0 +VALID_FUNC db 0 ;Flag to check for valid function # +EXIT_STAY db 0 +FILENAME db "COUNTRY.SYS",0 +PATH_SPEC db 64 dup(0) ;used to build path parameter +USER_PATH db 0 ;=I +PAR_RETC dw 0 +NO_PARMS db 0 +GOOD_PATH db 0 +PATHSEG DW 0 +SW_SPEC dW 0 +LENGTH_HOLD db 0 +;***CNS +CUR_PTR DW 0 ;AN003;; keeps track of parameter position ;AN000 +OLD_PTR DW 0 ;AN003;; keeps track of parameter position ;AN000 +;***CNS +;******************************************************************************** +NLS_BUFFER db BUFFSIZE dup (?) ;NLS BUFFER to transfer data + + +DATASIZE equ $-NLS_DATA + +NLS_DATA ENDS + +NLS_INIT_CODE SEGMENT BYTE PUBLIC 'CODE' + + ASSUME CS:NLS_INIT_CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING + + + +INT_2f_NEXT DD ? ;Chain location. +TEMPHOLD DW 0 +subttl resident code +page +;**************************** resident portion ******************************** + +NLSRES_CODE PROC NEAR + cmp ah,MULT_NLSFUNC ;Check the mutliplex value + je IS_NLSFUNC ;the # is mine + jmp dword ptr INT_2F_NEXT ;Chain to* the next handler + +IS_NLSFUNC: + + + cmp al,0f8h ;Make sure AL does not have reserved + ;DOS value 0F8 - 0FFH + jb SEL_FUNC ;Select the function code between 0, + ;1,2,3,4 + + iret ;return on reserved functions + +SEL_FUNC: + + + push es ;=C + push ds ;save the user's data segment + push si + push ds + push ax ;save the function value + mov TEMPHOLD,ax + + + mov ax,NLS_DATA ;so it won't be hosed + mov ds,ax ;set the data segment to mine + + ASSUME DS:NLS_DATA + + pop ax + pop DS_DOSLOCATE + pop SI_DOSLOCATE + + mov ID_CHECK,1 ;re-intialize flags + mov ALL_DONE,0 ;from resident portion + mov GET_EXT ,0 + mov INFO_ID ,0 + mov VALID_FUNC,0 ;Flag to check for valid function # + mov DONT_CLOSE,0 ;no open or close error yet + + pushall bx,cx,dx ;save all DOS registers + pushall bp,si,di ;save all DOS registers +; *************************** CNS ********************************************** + sti ;;AN000;the interrupt for external devices + ;AN000; +; *************************** CNS ********************************************** + mov FUNC_CODE,al ;save function # + cmp al,0 + jne FUNCODE_DOSTATE ;state is not 0 + mov al,INSTALLED ;Tell DOS I am installed + ;state is 0 + jmp RES_EXIT ;exit + + +FUNCODE_DOSTATE: + cmp al,CHG_CODEPAGE + je FUNCODE3_1 + cmp al,GET_EXT_CTY_INFO + je FUNCODE2 + cmp al,SET_CODEPAGE + je FUNCODE3_1 + jmp FUNCODE4 + + +FUNCODE4: ;Get Country Data - old 38 call =F + mov bp,1 ;set info_id to 1 =F + jmp short FUNCODE2 ; =F + + +FUNCODE3_1: ;Set Codepage/Get Country Information =E + les di,dword ptr SI_DOSLOCATE +; cmp es:[di].ccDosCodePage,bx ;=E +; jne fc3_1_10 ;=E +; cmp es:[di].ccDosCountry,dx ;=E +; jne fc3_1_10 ;=E +; mov CPAGE,bx ;get the codepage value =E +; jmp short fc3_1_20 ;=E +; +;fc3_1_10: + call RES_MAIN + jc ERROR_ROUTINE + CallInstall Dosclose,multdos,39,, ;close the file + jc NO_CLOSE + +fc3_1_20: + cmp FUNC_CODE,1 ;=E + je FUNCODE1 ;=E + mov al,ALL_DONE ;=E + jmp short RES_EXIT ;=E + + +FUNCODE2: ;Get Extended Country Information + mov ax,bp ;information requested by the user + mov INFO_ID,al + mov GET_EXT,1 ;get extended cty into user buffer + call RES_MAIN + jc ERROR_ROUTINE + + jmp short CLOSE_FILE ;=E + + +FUNCODE1: ;CHCP - Change Code Page =E + call WALK_DEVICES ;=E + mov al,ALL_DONE ;=E + jmp short RES_EXIT ;=E + + + +CLOSE_FILE: ;DOS 3eh function close COUNTRY.SYS + mov al,ALL_DONE + + CallInstall Dosclose,multdos,39,, ;close the file + jc NO_CLOSE + ;clear to let DOS know ok + + +RES_EXIT: + popall bp,si,di ;restore all DOS registers + popall bx,cx,dx ;restore all DOS registers + + cmp FUNC_CODE,GET_EXT_CTY_INFO ; =K + jne NC_IRET ; =K + cmp al,0 ;if successful 65 call, put size =K + jne NC_IRET ;of info returned in CX =K + mov cx,CSIZE ; =K + +NC_IRET: ; =K + pop ds ;restore user's data segment =K moved + pop es ;=C =K moved + iret ;Return to DOS + +NO_CLOSE: + mov ALL_DONE,al ;=J + inc DONT_CLOSE + +;if an error was detected + +ERROR_ROUTINE: + mov al,ALL_DONE + cmp DONT_CLOSE,1 + je RES_EXIT + jmp CLOSE_FILE + + +NLSRES_CODE ENDP +;*******************************END OF NLSRES_CODE****************************** +subttl resident main routine +page +;*******************************RES_MAIN**************************************** +RES_MAIN PROC NEAR + + mov VALID_FUNC,1 ;function exist + mov CPAGE,bx ;get the codepage value + mov CCODE,dx ;get the country code + mov CSIZE,cx ;size of the buffer + call CHK_OPEN ;go open file if possible + jc END_RES ;scan and read country info + + mov ax,CCODE + mov dx,CPAGE + mov si,offset NLS_BUFFER + call Trans_Cty_Data + ;into my buffer & the dos buffer + END_RES: + ret + +RES_MAIN ENDP +;*******************************END RES_MAIN************************************ +subttl check open procedure +page +;******************************CHECK OPEN PROCEDURE**************************** +CHK_OPEN PROC NEAR + + + xor cx,cx ;zero cx for open + cmp USER_PATH,1 ;either user supplied=I + je co_user ;or default DOS + +co_dos: push ds ;save current ds value + push si ;save current si value + lds si,dword ptr SI_DOSLOCATE ;old dos ds si value + lea dx,ds:[si].ccPATH_COUNTRYSYS + CallInstall Dosopen,Multdos,38,, + pop si ;restore current si + pop ds ;restore current ds + jmp short co_10 + +co_user: lea dx,PATH_SPEC + CallInstall Dosopen,Multdos,38,, + +co_10: jc BADREP_FILE ;bx contains the + mov bx,ax ;file handle + jmp short END_OPEN + +BADREP_FILE: + mov ALL_DONE,al ;=J + inc DONT_CLOSE + +END_OPEN: + ret + + CHK_OPEN ENDP +;******************************END OF CHKOPEN********************************** +subttl transfer country data +page +;******************************TRANS_CTY__DATA ******************************** +TRANS_CTY_DATA PROC NEAR + +TRANSTART: + push di ;save start of CTY/CP INFO + ;get the size of the file + xor cx,cx ;clear cx to start at + xor dx,dx ;at the beginning of the + ;file + call READ_CTLBUFF ;Read in the file header + jnc CHK_INFOTYPE + jmp END_TRANS ;=G + +CHK_INFOTYPE: + add si,LOCATE_INFOTYPE ;si > Country info type + cmp byte ptr ds:[si],1 ;only 1 type exist currently + je GET_INFOIDS + jmp BAD_FILE +GET_INFOIDS: + inc si ;si > set to file offset + mov dx,word ptr ds:[si] ;Get the Info file offset + mov cx,word ptr ds:[si+2] ;Doubleword + + mov SAVEDX,dx ;=FC save offset + mov SAVECX,cx ;=FC for more than 1 buffer + mov NOFFSET,2 ;=FC start from beginning + + call READ_CTLBUFF ;Read Info + jnc COUNT_ENTRIES + jmp END_TRANS ;=G + +COUNT_ENTRIES: + + mov cx,word ptr ds:[si] ;Get count of entries + ;in info + inc si ;next word + inc si ;si > Entry info packet + +FIND_CTY: ;Search for CTY/CP combo + + mov ax,word ptr ds:[si] ;=FC get size of entry + add ax,2 ;=FC include length filed + add NOFFSET,ax ;=FC look ahead + cmp NOFFSET,CTL_BUFF-4 ;=FC < (256 - 4) + jb IN_BUFF ;=FC + sub NOFFSET,ax ;=FC restore to old offset + push cx ;=FC save number of cntries + mov cx,SAVECX ;=FC get file offset + mov dx,SAVEDX ;=FC + add dx,NOFFSET ;=FC update to the entry + adc cx,0 ;=FC beginning + mov SAVECX,cx ;=FC save them for next use + mov SAVEDX,dx ;=FC + call READ_CTLBUFF ;=FC read next buffer in + jc READERROR ;=FC read error occurs + pop cx ;=FC restore number of cntries + mov NOFFSET,0 ;=FC a new beginning +IN_BUFF: + + mov dx,CPAGE + mov ax,CCODE + cmp ax,word ptr ds:[si+2] ;compare country id + jne NEXT_CTY + cmp dx, word ptr ds:[si+4] ;compare code page id + je FOUND_CTY + cmp dx,0 ;=FC if default pick the + jz FOUND_CTY2 ;=FC 1st country + +NEXT_CTY: + add si, word ptr ds:[si] ;next entry + inc si + inc si ;take a word for size of entry itself + loop FIND_CTY + + mov ALL_DONE,INVALID_DATA ;if it exits the loop =J =L + jmp FINDCTY_FAIL ;then no cp/cty match + +READERROR: pop cx ;=FC + jmp END_TRANS ;=FC + +FOUND_CTY2: mov dx,word ptr ds:[si+4] ;=FC from now on,this is + mov CPAGE,dx ;=FC the code page + +FOUND_CTY: ;found the matching entry + mov dx, word ptr ds:[si+10] ;get the file offset of country data + mov cx, word ptr ds:[si+12] + call READ_CTLBUFF + jnc NUM_ENTRY + jmp END_TRANS ;=G +NUM_ENTRY: + mov cx, word ptr ds:[si] ;get the number of entries to handle. + inc si + inc si ;SI -> first entry + +SETDOSCTY_DATA: +.REPEAT + push di ;ES:DI -> DOS_COUNTRY_CDPG_INFO + push si ;si -> current entry in Control buffer + push cx ;save # of entry left + + mov al, byte ptr ds:[si+2] ;get data entry id + xor ah,ah ;clear out for comparison with + ;info-id in case id is > 256 + + + + cmp GET_EXT,1 ;check to see if function 2 + ;get_extended info was needed + jne TRANSALL ;if not assume function code 1 + ;set codepage + + cmp INFO_ID,-1 ;Minus 1 means return all of the + jne CHK_ID ;country info to the user + ;otherwise get the specific + ;info id and return only that info + + + pop cx ;error can not return all + pop si ;info accept for currently + pop di ;loaded control info in DOS + jmp BAD_SETID ;area + +CHK_ID: cmp al,INFO_ID ;check to see if the selected + ;id is the same as the id in the + ;ctrl buffer area + + jne SETDOSCTY_NEXT ;if not equal go search for the + ;next information id + + pop cx ;Bingo!! Found it set counter + mov cx,1 ;to zero to exit loop + push cx + mov ID_CHECK,0 ;found a valid id + cmp GET_EXT,1 ;after transferring data to USER + je GET_ADDR ;area + + ;set cx image in stack to force + ;exit loop +TRANSALL: + + + + call GetDOSCTY_Dest ;get the address of destination in ES:DI + jc SetDOSCTY_NEXT ;No matching data entry id in DOS + +GET_ADDR: + + mov dx, word ptr ds:[si+4] ;get offset of data + mov cx, word ptr ds:[si+6] + + + +SEEK_READ: + + push ax ;=A save data id. + xor bp,bp ;DOS 4200h function + CallInstall Lseek,multdos,40,, ;move ptr + pop ax ;=A + jc DATASEEKNREAD + ;when ptr moved + mov dx,offset NLS_BUFFER +CTL_BUFF ;set the buffer to the beginning of the + ;data buffer area + + mov cx,DATA_BUFF_LENG ;set to number of bytes in the + ;data buffer area + push ax ;=A + ;DOS 3fh + CallInstall Dosread,Multdos,41,, ;Read cx many bytes into the buffer + pop ax ;=A + jc DATASEEKNREAD + +IS_EXTENDED: + cmp GET_EXT,1 + jne CHK_OVERWRITE + call GETEXT_CTY + jmp short SETDOSCTY_NEXT + + +CHK_OVERWRITE: ;=A + ; If SetCountryInfo, then + ; put DOS monocase routine + ; entry point into + ; NLS_BUFFER so don't + ; write over. =A + cmp al,SetCountryInfo ;=A + jne DOS_MOVE ;=A + mov ax,word ptr es:[di+24] ;=A + mov word ptr ds:[NLS_BUFFER+CTL_BUFF + 32],ax ;=A + mov ax,word ptr es:[di+26] ;=A + mov word ptr ds:[NLS_BUFFER+CTL_BUFF + 34],ax ;=A + + mov ax,CPAGE ;=FC, CPAGE is right + mov word ptr ds:[NLS_BUFFER+CTL_BUFF + 12],ax ;=FC + +DOS_MOVE: + call CHK_ADJUST ;now check to see if the entire + ;table fits + +SETDOSCTY_NEXT: + + pop cx + pop si + pop di + add si, word ptr ds:[si] + inc si + inc si + dec cx + .UNTIL NEAR ;loop SETDOSCTY_DATA + + ;Check for an invalid id + cmp GET_EXT,1 ;Check to see if a get_ext func 2 was issued + jne CTLSEEKnREAD ;if not move on + cmp ID_CHECK,1 ;if so check to see if an id was found + je BAD_SETID ;if none was found report an error + ;otherwise continue + + +CTLSEEKnREAD: + clc ;=G + jmp short END_TRANS ;exit + + + +DATASEEKnREAD: + mov ALL_DONE,al ;=J + pop cx + pop si + pop di + jmp short END_TRANS + +BAD_SETID: + mov ALL_DONE,INVALID_FUNCTION ;=J + jmp short FINDCTY_FAIL ;=J + +BAD_FILE: + mov ALL_DONE,INVALID_FUNCTION ;=J + +FINDCTY_FAIL: + stc + +END_TRANS: + pop di ;Restore header start + ret + + + +TRANS_CTY_DATA ENDP + +;******************************END TRANS_CTY_DATA ****************************** +subttl get DOS country destination +page +;****************************GETCTY_DEST*********************************************** +GetDOSCty_Dest proc near +;Get the destination address in the DOS country info table. +;Input: AL - Data ID +; ES:DI -> DOS_COUNTRY_CDPG_INFO +;On return: +; ES:DI -> Destination address of the matching data id +; carry set if no matching data id found in DOS. + + push cx + add di, ccNumber_of_entries ;skip the reserved area, syscodepage etc. + mov cx, word ptr es:[di] ;get the number of entries + inc di + inc di ;SI -> the first start entry id +GetCntryDest: + cmp byte ptr es:[di], al + je GetCntryDest_OK + cmp byte ptr es:[di], SetCountryInfo ;was it SetCountryInfo entry? + je GetCntryDest_1 + add di, 5 ;next data id + jmp short GetCntryDest_loop + +GetCntryDest_1: + add di, NEW_COUNTRY_SIZE + 1 ;next data id + +GetCntryDest_loop: + loop GetCntryDest + stc + jmp short GetCntryDest_exit + +GetCntryDest_OK: + + cmp al, SetCountryInfo ;select country info? + jne GetCntryDest_OK1 + inc di ;now DI -> ccCountryInfoLen + clc ;clear the carry + jmp short GetCntryDest_exit + +GetCntryDest_OK1: + + les di, dword ptr es:[di+1] ;get the destination in ES:DI + clc + +GetCntryDest_Exit: + pop cx + ret + +GetDOSCty_Dest endp +;****************************GETDOSCTY_DEST************************************* +subttl get extended country data +page +;****************************GETEXT_CTY***************************************** +GETEXT_CTY proc + +JUSTONE_ID: + mov ah,func_code ;=F + cmp ah,GET_CTY_INFO ;=F + je id_ctyinfo1 ;=F + + mov al,INFO_ID + mov byte ptr es:[di],al + + cmp INFO_ID,SetCountryInfo ;SETCTY_INFO =D moved. + je ID_CTYINFO ;=D don't want ptr if 1. + + mov word ptr es:[di+1],offset nls_buffer + ctl_buff+8 ;=H + mov word ptr es:[di+3],ds ;my current ds value + mov CSIZE,5 ;=K + + jmp GET_EXT_END + +ID_CTYINFO: + inc di ;=D (old code - add di,5) =F(moved). +id_ctyinfo1: ;=F + mov cx,CSIZE + ;next line used to be "add si,5" + ;si needs to point to cty info. =D + mov si,offset nls_buffer + ctl_buff + 8 ;=D + + push es ;=A put DOS Monocase Routine + push di ;=A entry point in user buffer. + push ax ;=A + les di,dword ptr si_doslocate ;=A + mov ax,word ptr es:[di].ccMono_Ptr ;=A + mov word ptr ds:[si+24],ax ;=A + mov ax,word ptr es:[di].ccMono_Ptr+2 ;=A + mov word ptr ds:[si+26],ax ;=A + + mov ax,CPAGE ;=FC trust CPAGE + mov word ptr ds:[si+4],ax ;=FC + + pop ax ;=A + pop di ;=A + pop es ;=A + + push bx ;=F + cmp ah,GET_CTY_INFO ;=F if get cty info(38) slide info + jne id_ctyinfo2 ;=F ptr up to date. + add si,6 ;=F + mov cx,old_country_size ;=FC + jmp MOVE_CTY ;=FC + +id_ctyinfo2: mov bx,word ptr ds:[si] ;=FC get table size + + + sub CSIZE,3 ;=FC size begins after length field + mov cx,CSIZE ;=FC + + cmp cx,bx ;=D was cmped to SETCTR_LENG + ja TRUNC_SIZE ;=FC used to be jg + jmp short MOV_SIZE +TRUNC_SIZE: + mov cx,bx ;=F +MOV_SIZE: + mov es:[di],cx ;=FC move actual length to user's buff + add di,2 ;=FC update index + add si,2 ;=FC skip length field + +MOVE_CTY: pop bx ;=F + mov CSIZE,cx ;=K + add CSIZE,3 ;=K + rep movsb + +GET_EXT_END: + ret + +GETEXT_CTY endp +;*****************************END GETEXT_CTY************************************* +subttl read into control buffer +page +;**************************READ_CTLBUFF***************************************** +; +READ_CTLBUFF proc near +;Move file pointer to CX:DX +;Read 64 bytes into the control buffer. Assume that the necessary data +;is within that limit. +;SI will be set to beginning of the offset my NLS_BUFFER hence DS:SI points to the control buffer. +;Entry: CX,DX offset from the start of the file where the read/write pointer +; be moved. +; BX - file handle +; DS - buffer seg. +;Return: The control data information is read into DS:0 - DS:0200. +; CX,DX value destroyed. +; Carry set if error in Reading file. +; + ;Function 4200h + xor bp,bp + CallInstall Lseek,multdos,40,, ;move pointer + jc NO_SEEK1 + + mov dx,offset NLS_BUFFER ;ds:dx -> control buffer + mov si,dx ;index for the entire buffer + ;read into the buffer function 3fh + mov cx, CTL_BUFF ;XXX bytes. Size of the information + CallInstall Dosread,multdos,41,, ;should be less than XXX bytes. + jc NO_READ1 + jmp short RICB_exit + + +NO_SEEK1: + mov ALL_DONE,al ;=J + jmp short RICB_exit + +NO_READ1: + mov ALL_DONE,al ;=J + +RICB_exit: ;In this case 64 bytes + ret + +READ_CTLBUFF endp +;****************************END READ_CTLBUFF*********************************** +subttl check / adjust / move data into DOS buffer +page +;****************************CHK_ADJUST***************************************** +CHK_ADJUST PROC NEAR + + push ax ;save info id + mov si,offset NLS_BUFFER+DATA_N_ID ;start of buffer + tag id + mov cx, word ptr ds:[si] ;get the length of the structure + + inc cx + inc cx + + cmp cx,MAXBUFF_FIT + jbe MOVE_DATA + push cx + mov cx,MAXBUFF_FIT + rep movsb + pop cx + sub cx,MAXBUFF_FIT + +NEED_ADJUST: + mov dx,offset NLS_BUFFER+CTL_BUFF ;reset to the beginning of the data buffer + mov si,dx ;reset to the beginning of the data buffer + cmp cx,DATA_BUFF_LENG ;check to see if it fits for the nth read + jbe LAST_READ ;last portion fits + push cx ;save how much is left to read + mov cx,DATA_BUFF_LENG ;set to how much you read at one time + + ;read again ;function 3fh + ;read into the data buffer + CallInstall Dosread,multdos,41,, ;save the file handle + jc ADJUST_END + + rep movsb ;move data into DOS area + pop cx ;restore size remaining to + sub cx,DATA_BUFF_LENG ;be read get new size + jmp NEED_ADJUST ;must read agian + +LAST_READ: + ;one more read 3f + CallInstall Dosread,multdos,41,, + jc ADJUST_END + +MOVE_DATA: + rep movsb ;move data into DOS area + +ADJUST_END: + pop ax + ret +CHK_ADJUST ENDP +;*******************************END CHK_ADJUST ********************************* +subttl walk through device drivers and invoke +page +;************************ WALK DEVICE DRIVERS ********************************** +;=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E=E= + +WALK_DEVICES PROC NEAR + + mov si,offset NLS_BUFFER ;Prepare to hold device name + push es ;AN001; Clear out NLS_BUFFER to 0 + push ds ;AN001; + pop es ;AN001; + mov di, si ;AN001; ES:DI-> NLS_BUFFER + xor ax, ax ;AN001; AX=0 + mov cx, BUFFSIZE ;AN001; + shr cx, 1 ;AN001; /2 to make a # of words + rep stosw ;AN001; + pop es ;AN001; Restore es + ;Get ptr to hdr of 1st device. + push si ;AN001; + CallInstall GetDevLst,Multdos,44,, + pop si ;AN001; + mov es,bx ;bx:ax -> hdr. + mov di,ax +char_test: + test es:[di].sdevatt,devtyp ;check attribute word for + jne open_device + jmp GET_NEXT_DEVICE ;character device. + +OPEN_DEVICE: + push si + push di ;set up asciiz filename + add di,10 ;for DOS file open + mov cx,8 + +set_asciiz: mov al,es:[di] + cmp al,20h + je done_set_asciiz + mov ds:[si],al + inc di + inc si + loop set_asciiz + +done_set_asciiz:xor al,al + mov ds:[si],al + + pop di + pop si + + mov cx,1 ;open for write + mov dx,si + CallInstall Dosopen,Multdos,38,, + jnc end_open_device + jmp GET_NEXT_DEVICE ; ignore this =FC + +end_open_device: + mov bx,ax ;put handle in bx + call Chk_Revisit ;AN001; Have been here already? + jnc INVOKE_DEVICE ;AN001; No, a new one. + jmp CLOSE_DEVICE ;AN001; Yes. Close and ignore this. + +INVOKE_DEVICE: + push ds ;Check print queue first. + push si ;Set up for 2f print call. + clc + mov ax,0106h ;2f call to command.com. + int 2fh ;If print active: carry set, + jnc invoke_it ;DS:SI -> hdr of printing device. + cmp si,di ;Check if printing device is this + jne invoke_it ;device. Match on ptr to device. + mov ax,ds + mov cx,es + cmp ax,cx + jne invoke_it + + pop si + pop ds + mov ALL_DONE,BAD_INVOKE ;Match. Set invoke error. + jmp CLOSE_DEVICE + +invoke_it: pop si ;save the current + pop ds ;environment + +;*************** CNS *********** Start of DBCS Support +; PUSH DS ;ICE +; push bx ;ICE +; push ax ;ICE +; mov bx,0140H ;ICE +; xor ax,ax ;ICE +; mov ds,ax ;ICE +; mov ax,word ptr ds:[bx] ;ICE +; mov word ptr ds:[bx],ax ;ICE +; POP ax ;ICE +; pop bx ;ICE +; pop ds ;ICE + push di + push bx + push cx + push es + les di,dword ptr SI_DOSLOCATE ;get the environmental +;*************** CNS ****************** +; mov bx,es:[di].ccDBCS_ptr ;values to allow +; mov es,es:[di].ccDBCS_ptr+2 ;recognition and +;*************** CNS ****************** + les bx,es:[di].ccDBCS_ptr + mov cx,es:[bx] ;invocation of data + add cx,2 + add bx,2 ;and ID for start + mov di,offset pk.DBCS_EV ;and stop values for + ;otherwise it is a DBCS +;****CHANGE ;or custom designed codepage + + mov PK.PACKLEN,cx ;if packet length is zero + +NODBCS_CP: + add cx,-2 ;AN002; reset counter before CP addition + +;****CHANGE + +DB_EVECS: + cmp cx,0 ;AN002;no need to alter packet + je NO_LOAD ;An002;initialized to zero + + + .REPEAT ;;AN000;DBCS transmission + ;AN000; + mov al,es:[bx] ;;AN000;get the the contents +;***CNS ;AN000; + mov ds:[di],al ;;AN002;of where the DBCS Points +;***CNS ;AN000; + inc di ;;AN000;data packet for ioctl + ;AN000; + inc bx ;AN000;;call--- get the start + ;stop values to load + ;AN000; + dec cx ;AN000; + + .UNTIL ;AN000; + ;invocation of 1 codepage + ;standard codepage selection + + +NO_LOAD: + + pop es ;AN000;;accordingly & restore + ;AN000; + pop cx ;AN000;;values + ;AN000; + pop bx ;AN000; + ;AN000; + pop di ;AN000; + ;AN000;;invoke codepage +;************************ CNS*** End of DBCS + + ;Set up data packet for generic + mov ax,cpage ;ioctl call. + mov pk.packcpid,ax + lea dx,pk + + mov cx,004ah + mov bp,0ch ;generic ioctl + CallInstall IOCTL,multdos,43,, + jc device_error + + +CLOSE_DEVICE: + CallInstall Dosclose,multdos,39,, + jc dev_open_close_error ; ignore this =FC + +GET_NEXT_DEVICE: + cmp word ptr es:[di],0FFFFH + je END_WALK_DEVICES + les di,dword ptr es:[di] + jmp char_test + +DEVICE_ERROR: + cmp ax,1 + je CLOSE_DEVICE + CallInstall GetExtErr,multdos,45,, + cmp ax,22 + je CLOSE_DEVICE + mov ALL_DONE,BAD_INVOKE + jmp CLOSE_DEVICE + +dev_open_close_error: + mov ALL_DONE,BAD_INVOKE + jmp GET_NEXT_DEVICE + +END_WALK_DEVICES: + + + ret + +WALK_DEVICES endp +;*********************** END WALK DEVICE DRIVERS ******************************* +;************************ Chk_Revisit****************************************** +;This routine will check if we are opening the same device driver again. +;If it is, then carry bit will set. +;This routine will use the NLS_BUFFER to keep the history of already +;visited device driver address (OFFSET,SEGMENT). NLS_BUFFER will be +;used from the end of the buffer towards to the front of the buffer. +;For 512 byte length and considering the front part used for OPEN device +;driver name string, this will handle appr. 126 devices maximum. which is +;sufficient enough. - J.K. 1/15/88 +;IN: BX = file handle +; DS = NLS_BUFFER segment +;OUT: carry set = visited +; carry not set = new one. +; Other registers saved. + +Chk_Revisit proc near + push ax ;AN001; + push bx ;AN001; + push es ;AN001; + push di ;AN001; + mov ax, 1220h ;AN001; Get the spot of SFT + int 2fh ;AN001; + jc Chk_Rvst_Ret ;AN001; This won't happen + xor bx, bx ;AN001; + mov bl, byte ptr es:[di] ;AN001; + mov ax, 1216h ;AN001; Get the SFT pointer + int 2fh ;AN001; es:di-> SFT table + jc Chk_Rvst_Ret ;AN001; This won't happen + mov ax, word ptr es:[di].SF_DEVPTR ;AN001; offset of device + mov bx, word ptr es:[di].SF_DEVPTR+2;AN001; Segment of device + mov di, offset NLS_BUFFER ;AN001; + add di, BUFFSIZE-2 ;AN001; ds:di-> last word of the buffer +Chk_Rvst_While: ;AN001; + cmp word ptr ds:[di], 0 ;AN001; di-> segment value + jne Chk_Rvst_Cont ;AN001; + cmp word ptr ds:[di-2], 0 ;AN001; offset + jne Chk_Rvst_Cont ;AN001; + jmp Chk_Rvst_New ;AN001; Encountered a blank entry in the buffer +Chk_Rvst_Cont: ;AN001; + cmp word ptr ds:[di], bx ;AN001; + jne Chk_Rvst_Next ;AN001; + cmp word ptr ds:[di-2], ax ;AN001; + jne Chk_Rvst_Next ;AN001; + stc ;AN001; found a match + jmp Chk_Rvst_Ret ;AN001; +Chk_Rvst_Next: ;AN001; + sub di, 4 ;AN001; move the pointer to the next entry + jmp Chk_Rvst_While ;AN001; +Chk_Rvst_New: ;AN001; + mov word ptr ds:[di],bx ;AN001; Keep the current open device segment + mov word ptr ds:[di-2], ax ;AN001; and offset + clc ;AN001; New device +Chk_Rvst_Ret: ;AN001; + pop di ;AN001; + pop es ;AN001; + pop bx ;AN001; + pop ax ;AN001; + ret ;AN001; +Chk_Revisit endp + +subttl end nlsfunc resident code +page + NLSRES_LENG equ $-NLSRES_CODE+DATASIZE +subttl initialization +page +;***************************** NLSFUNC Initialization ************************** + + ASSUME CS:NLS_INIT_CODE,SS:STACK + + + +MAIN PROC FAR + + mov ax,NLS_DATA ;set up data segment + mov ds,ax + assume ds:NLS_DATA + + mov PATHSEG,ax + + call SYSLOADMSG ;does DOS version check + + .IF + mov dx,NLSRES_LENG ;calculate paragraph + add dx,15 ;add 15 + shr dx,1 ;divide by 16 to get conversion from + shr dx,1 ;bytes to paragraphs + shr dx,1 + shr dx,1 + add dx,11h ;size based on the byte size of + mov RES_PARASIZE,dx ;the resident procedure + call PROCESS_PATH + + .ELSE + + call SYSDISPMSG + + .ENDIF + + .IF or + .IF + call INSTALL_NLS ;let's install NLSFUNC + .IF + mov EXIT_STAY,1 ;if nothing wrong occured + .ENDIF + .ENDIF + ;determine path of exit + ;error or residency +;****************************** EXIT PROG ********************************************* + push ax ;AN004;save existing values + push es ; + xor ax,ax + mov ax,es:[2ch] + cmp ax,0 + je NO_FREEDOM + mov es,ax + mov ax,4900H ;AN004;make the free allocate mem func + int 21h ; + +NO_FREEDOM: + pop es ;AN004;restore existing values + pop ax ; + + .IF ;Terminate and stay resident + mov bx,4 ;1st close file handles + .REPEAT + mov ah,3eh + int 21h + dec bx + .UNTIL + + mov ah,031h ; + mov dx,RES_PARASIZE ;paragraphs allocated + .ELSE + clc + mov ah,04ch ;value passed to ERRORLEVEL + .ENDIF + + mov al,ERROR_CODE ;check for an error + int 21H + + + + + + + MAIN ENDP + +;****************************** EXIT PROG ********************************************* +subttl parse +page +; On entry: ES points at the PSP +; DS points at NLS_DATA +; DX was used to calculate paragraph size +; +; PARSER EFFECTS ES & DS wil be swapped +; +; Changes : ES:DI seg:off containing PARM Input Block +; to DS:SI seg:off containing command line +; segments +; +; +; +; +; +; +;****************************** PROCESS PATH *********************************** +;=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I=I= + +PROCESS_PATH PROC NEAR + + ;to command line parms + + + push es ;;AC000;e original es (nothing) + ;AC000; + push ds ;AC000;he original ds (Nls_data) + ;AC002; + push ds ;save for both es & ds to point at data + + push es ;AC000;hat's in my es the PSP value + ;AN000; + push ds ;AN000;he segment id that points to my + ;es now points to data + pop es ;AC000; + ;input parameter control block (NLS_DATA) + ;AN000; + + pop ds ;AN000; points to the segment for + ;the command line string + ;AN000; + + ASSUME DS:NOTHING,ES:NLS_DATA + + xor dx,dx + xor cx,cx + +;***CNS +RE_START: + mov si,80h ;get the command line length + + mov cl,byte ptr ds:[si] ;get the length for the counter +; + mov LENGTH_HOLD,cl ;save the length of the command line +; + + + +; .IF + + mov di,OFFSET NLS_BUFFER ; + ; mov dx,1 + ; .ELSE + ; mov di,OFFSET PATH_SPEC ; + ; mov dx,-1 + ; .ENDIF + + mov si,CL_NUM ;AN000; points to the offset command + ;line input string at value 81h + ;AN000; + + rep movsb ;transfer command line to NLS_BUFFER + +; .IF +; jmp RE_START +; .ENDIF + +;***CNS + + + + + mov di,OFFSET NLS_PARMS ;AN000; into ES of the PARMS INPUT + ;BLOCK + ;AN000; + pop ds ; ds also point at NLS_DATA + + + ASSUME DS:NLS_DATA + + + mov si,OFFSET NLS_BUFFER ;si now points to the offset command +;***CNS + + PUSH AX ;AN003;Save environment + MOV AX,CUR_PTR ;AN003;Set advancing ptr to end of argument + MOV OLD_PTR,AX ;AN003;after saving the beginning the string + MOV CUR_PTR,SI ;AN003; + POP AX ;AN003;Restore the environment + +;***CNS + + + + xor cx,cx ;AN000;l value should be atleast 1 + xor dx,dx ;AN000;ut dx for input into the PARSER + ;AN000; + + .WHILE ;AN000; + call SYSPARSE ;AN000;empt to parse +;***CNS + + PUSH AX ;AN003;Save environment + MOV AX,CUR_PTR ;AN003;Set advancing ptr to end of argument + MOV OLD_PTR,AX ;AN003;after saving the beginning the string + MOV CUR_PTR,SI ;AN003; + POP AX ;AN003;Restore the environment + +;***CNS + ;AN000; + .IF ;AN000;ound + ;AN000; + mov USER_PATH,1 ;AN000;;path specified + ;AC000; + .ENDIF ;AN000; + + mov PAR_RETC,AX ;AN000;;keep parsing until eoln + ;AN000; + .ENDWHILE ;AN000; + + + .IF ;AN000;;parse error +;***CNS +; .IF ;AN003;IF invalid switch return command line +; +; mov ax,10 + + + LEA DI,PATH_SPEC ;AN003;Set PTR to look at the STRING + PUSH SI ;AN003;Save current SI index + PUSH AX + MOV AX,OLD_PTR ;AN003;Last locale of the end of a PARAM + SUB CUR_PTR,AX ;AN003;Get the length via the PSP + MOV SI,CUR_PTR + MOV CX,SI ;AN003;Save it in CX to move in the chars + POP AX ;AN003;Restore the PTR to the command line position + + MOV SI,OLD_PTR ;AN003;Last locale of the end of a PARAM + REP MOVSB ;AN003;Move in the chars until no more + + LEA DI,PATH_SPEC ;AN003;Set PTR to look at the STRING + + POP SI ;AN003;Restore the PTR to the command line position + + + + + mov cx,1 ;AN003;; + mov bx,STDERR ;AN003; + mov dl,no_input ;AN003; + mov dh,PARSE_ERR_CLASS ;AN003; + mov ds,PATHSEG ;AN003; + mov si,OFFSET PARMLIST3 ;AN003; + call SYSDISPMSG ;AN003; + mov PARSE_ERR,1 ;AN003;;PARSE ERROR OCCURED +;***CNS +; .ELSE + +; xor cx,cx ;AN000;; +; mov bx,STDERR ;AN000; +; mov dl,no_input ;AN000; +; mov dh,PARSE_ERR_CLASS ;AN000; +; mov ds,PATHSEG ;AN000; +; mov si,0 ;AN000; +; call SYSDISPMSG ;AN000; +; mov PARSE_ERR,1 ;AN000;;PARSE ERROR OCCURED +;***CNS + ; .ENDIF +;***CNS + .ELSEIF ;AN000;ordinal check + ;AN000; + mov GOOD_PAR,1 ;AN000;you are at the end of the line + ;AN000; + .ELSE + mov NO_PARMS,1 ;AN000;there is no argument go install + .ENDIF ;AN000;NLSFUNC + + .IF NEAR ;AN000;if not true you encountered a parse error + .IF NEAR ;AN000;there is a parameter line available + ;to parse + ;AN000; + ;Check the flags to see what + ;was returned in the return block + + lea di,path_spec ;AC000;es:di > final path_spec + ;that will be used after fixup + + .IF ;AC000;drive has been solved need + ;to check the filespec + ;now + xor in_dex,in_dex ;AN000;clear ctr + mov bx,Res_POFF ;AN000;get file spec ptr to text + push ds ;AN000;prepare for entry + mov ds,Res_PSEG ;AN000; + mov in_dex,bx ;AN000;string seg value if filename + .ENDIF ;user path ;AN000; + + + .WHILE ;load chars until no more + ;AN000; + ;AN000; + mov al,FILESPEC_PTR ;AN000; + mov byte ptr es:[di],al ;move value into pathspec and + inc in_dex ;increment to next char position + inc di ;AN000; + .ENDWHILE + +;************************** CNS ********************************************** +;The new method of checking for a "bogus" file will be to attempt an +;open on the path_spec if pathspec exist close path and continue if +;carry set stuff error code with 02 and exit..... +;***************************************************************************** +; push es ;AN000; + pop ds ;into find first + mov si,di ;AN000; + xor cx,cx ;AN000; +; + ASSUME DS:NLS_DATA +; + mov byte ptr ds:[si],NULL ;add asciiz value + ;AN000; + lea dx,PATH_SPEC ;check full pathname + mov ah,4eh + int 21h + ;set up addressability + .IF + clc ;ok-clear carry/exit + mov GOOD_PATH,1 + .ELSE + mov ax,FNF ;AN000; + mov cx,1 ; ;AN000; + mov bx,STDERR ;AN000; + mov dl,no_input ;AN000; + mov dh,UTILITY_MSG_CLASS ;AN000; + mov ds,PATHSEG ;AN000; + mov si,OFFSET PARMLIST1 ;AN000; + call SYSDISPMSG ;AN000; + mov ERROR_CODE,02 ; + stc + .ENDIF + + + + + + + + .ENDIF ;EXIT on bad parse + .ENDIF ;END OF PROCESS PATH + + + pop ds ;AN000;;restore original ds (NLS_DATA) + ;AN000; + pop es ;AN000;;restore original es (nothing) + ;AN000; + ;AN000;;after munging around with the PARSER + + ASSUME DS:NLS_DATA,ES:NOTHING + + ret + + + +PROCESS_PATH ENDP + +; + +;****************************** CNS ******************************************* +subttl install NLSFUNC +page +;******************************** INSTALL NLSFUNC ***************************** + +INSTALL_NLS PROC NEAR + + xor ax,ax ;clear the ax + mov ah,MULT_NLSFUNC ;load in my multiplex + INT 2fh ;id value 14 + or al,al ;check to see if +; jz DO_INSTALL ;hooked in the chain +; *********************** CNS ************************************************* + + .IF ;AN000 + + ;Install NLSFUNC + mov al,2fh ;Get interrupt + mov ah,GET_INT ;2f in the chain + int 21h + mov word ptr INT_2f_NEXT+2,ES ;store the address + mov word ptr INT_2f_NEXT,BX ;to make the current + push ds ;2f handler next in + push cs ;the chain + pop ds ;set Dataseg to the Code + mov dx,offset NLSRES_CODE ;give start address + mov al,2fh ;of resident logic + mov ah,SET_INT ;set the 2f in the + int 21h ;chain + pop ds ;restore original ds + ;terminate & + ;stay +;FREE THE ENVIRONMENT ;no then install + +; push ax ;AN004;save existing values +; push es ; +; mov ah,49H ;AN004;make the free allocate mem func +; mov es,es:[2ch] ;AN004;get the segment address +; int 21h ; +; pop es ;AN004;restore existing values +; pop ax ; + + .ELSE ;AN000; +;TBR Message retriever ;otherwise + mov ax,ALLINS ; + mov cx,1 ; + mov bx,STDERR ;AN000; + mov dl,no_input ;AN000; + mov dh,UTILITY_MSG_CLASS ;AN000; + mov ds,PATHSEG + mov si,OFFSET PARMLIST2 + call SYSDISPMSG ;AN000; + mov ERROR_CODE,80 ;UTILITY ERROR CODE + stc + +.ENDIF + + ret + +INSTALL_NLS ENDP + +msg_services ;AN000; +msg_services ;AN000; +msg_services ;AN000; + +;******************************** END OF NLS_INIT_CODE ************************** +NLS_INIT_CODE ENDS +subttl stack +page + +STACK SEGMENT PARA STACK 'STACK' + DB 512 DUP (?) +STACK ENDS + + END MAIN diff --git a/v4.0/src/CMD/NLSFUNC/NLSFUNC.SKL b/v4.0/src/CMD/NLSFUNC/NLSFUNC.SKL new file mode 100644 index 0000000..e33ba64 --- /dev/null +++ b/v4.0/src/CMD/NLSFUNC/NLSFUNC.SKL @@ -0,0 +1,15 @@ +:util NLSFUNC ;AN000; +:class 2 ;AN000; +:use PARSE1 ;AN000; +:use PARSE2 ;AN000; +:use PARSE3 ;AN000; +:use PARSE4 ;AN000; +:use PARSE6 ;AN000; +:use PARSE7 ;AN000; +:use PARSE8 ;AN000; +:use PARSE10 ;AN003; +:class A ;AN000; +:use 1 COMMON1 ;AN000;;MSG 1 is always "Incorrect DOS version" +:use 2 COMMON2 ;AN000;;MSG 2 is always "%1 already installed" +:use 3 EXTEND2 ;AN000;;MSG 3 is always "File not found - %1" +:end ;AN000; diff --git a/v4.0/src/CMD/NLSFUNC/NLSPARM.ASM b/v4.0/src/CMD/NLSFUNC/NLSPARM.ASM new file mode 100644 index 0000000..8b84bb5 --- /dev/null +++ b/v4.0/src/CMD/NLSFUNC/NLSPARM.ASM @@ -0,0 +1,148 @@ + PAGE ,132 ; + TITLE NLSPARM.SAL - NLSFUNC SYSTEM COMMAND LINE PARSER +;****************** START OF SPECIFICATIONS ***************************** +; MODULE NAME: NLSPARM.SAL +; +; DESCRIPTIVE NAME: Include the DOS system PARSER in the SEGMENT +; configuration expected by the modules of NLSFUNC. +; +;FUNCTION: The common code of the DOS command line PARSER is optimized by +; the setting of certain switches that cause the conditional +; assembly of only the required portions of the common PARSER. +; The segment registers are ASSUMED according to the type .EXE. +; +; ENTRY POINT: SYSPARSE, near +; +; INPUT: +; ES - has seg id of the SEGMENT +; that contains the input control blocks, +; defined below. +; +; DI - offset into ES of the PARMS INPUT BLOCK +; +; DS - has seg id of the SEGMENT +; that contains the DOS input COMMAND +; string, which is originally presented at 81h +; in the PSP. +; +; SI - offset into DS of the text of the DOS input COMMAND string +; as originally presented at 81H in the PSP. +; +; DX - zero +; +; CX - ordinal value, intially zero, updated on each subsequent call +; to the value returned in CX on the previous call. +; +; CS - points to the segment containing the +; INCLUDE PARSE.SAL statement +; +; DS - also points to the segment containing the INCLUDE +; PARSE.SAL statement. +; +; EXIT-NORMAL: Output registers: +; AX - return code: +; RC_No_Error equ 0 ; No error +; RC_EOL equ -1 ; End of command line +; +; DX - Offset into ES of the selected RESULT BLOCK. +; BL - terminated delimiter code +; CX - new operand ordinal +; SI - set past scanned operand +; +; EXIT-ERROR: Output registers: +; AX - return code: +; RC_Too_Many equ 1 ; Too many operands +; RC_Op_Missing equ 2 ; Required operand missing +; RC_Not_In_SW equ 3 ; Not in switch list provided +; RC_Not_In_Key equ 4 ; Not in keyword list provided +; RC_Out_Of_Range equ 6 ; Out of range specified +; RC_Not_In_Val equ 7 ; Not in value list provided +; RC_Not_In_Str equ 8 ; Not in string list provided +; RC_Syntax equ 9 ; Syntax error +; +; INTERNAL REFERENCES: +; ROUTINES: SYSPARSE:near (INCLUDEd in PARSE.SAL) +; +; DATA AREAS: none +; +; EXTERNAL REFERENCES: +; ROUTINES: none +; +; DATA AREAS: control blocks pointed to by input registers. +; +; NOTES: +; This module should be processed with the ASMUT preprocessor +; with the re-alignment not requested, as: +; +; SALUT NLSPARM,NUL; +; +; To assemble these modules, the sequential +; ordering of segments may be used. +; +; For LINK instructions, refer to the PROLOG of the main module, +; NLSFUNC.SAL +; +; REVISION HISTORY: A000 Version 4.00: add PARSER, System Message Handler, +; +; COPYRIGHT: "The DOS NLSFUNC Utility" +; "Version 4.00 (C)Copyright 1988 Microsoft +; "Licensed Material - Program Property of Microsoft " +; +;****************** END OF SPECIFICATIONS ***************************** + IF1 + %OUT COMPONENT=NLSFUNC, MODULE=NLSPARM.SAL... + ENDIF +; = = = = = = = = = = = = + HEADER +; = = = = = = = = = = = = + +HEADER MACRO TEXT +.XLIST + SUBTTL TEXT +.LIST + PAGE + ENDM + +; = = = = = = = = = = = = + HEADER +NLS_DATA SEGMENT BYTE PUBLIC 'DATA' + + CAPSW EQU 1 ;SUPPORT FILENAME TBL CAPS + FARSW EQU 0 ;PARSER CALL FAR + FILESW EQU 1 ;CHECK FOR FILESPEC +SWSW EQU 0 ;SUPPRESS SUPPORT FOR SWITCHES +DATESW EQU 0 ;SUPPRESS DATE CHECKING +TIMESW EQU 0 ;SUPPRESS TIME CHECKING +CMPXSW EQU 0 ;SUPPRESS CHECKING COMPLEX LIST +NUMSW EQU 0 ;SUPPRESS CHECKING NUMERIC VALUE +KEYSW EQU 0 ;SUPPRESS KEYWORD SUPPORT +VAL1SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 1 +VAL2SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 2 +VAL3SW EQU 0 ;SUPPRESS SUPPORT OF VALUE DEFINITION 3 +DRVSW EQU 0 ;SUPPORT OF DRIVE ONLY FORMAT +QUSSW EQU 0 ;SUPPRESS SUPPORT OF QUOTED STRING FORMAT + +; INCLUDE PSDATA.INC ;PARSE WORK AREA & EQUATES + +NLS_DATA ENDS + +NLS_INIT_CODE SEGMENT BYTE PUBLIC 'CODE' + +; ASSUME CS:NLS_INIT_CODE,DS:NLS_DATA + ASSUME CS:NLS_INIT_CODE,DS:nothing ; tsuneo + +; mov ax,NLS_DATA +; mov ds,ax + +;INCSW equ 0 + + + + + INCLUDE PARSE.ASM + PUBLIC SYSPARSE + +NLS_INIT_CODE ENDS +;NLS_DATA ENDS + END + \ No newline at end of file -- cgit v1.2.3