3 TITLE NLSFUNC
- GET
/SET CP
& COUNTRY INFO CHCP SUPPORT
4 ;**************************************************************************
5 ;This is the NLSFUNC int2f command that supports the INT21h functions
6 ;Get_Extended Country Information and the Set_codepage...
7 ;NLSFUNC will read the COUNTRY.SYS information from disk , store the
8 ;data in a buffer , then move the information into a buffer
9 ;area specified by DOS.
14 ; If installed previously *
15 ; report back error already installed and exit *
16 ; otherwise goto install *
18 ;*************************************************************************
20 ;*************************************************************************
21 subttl get extended country
data
24 ;***************************************
25 ;* Process_Path Procedure *
26 ;***************************************
28 ;* Do DOS Version check *
29 ;* If ne X.X then (carry set) *
30 ;* CALL SYSDISPLAY_MSG *
31 ;* DISPLAY_MSG(Message number 001) *
32 ;* (001 - Incorrect DOS Version) *
33 ;* (Class 3 - Utility Msg) *
36 ;* Establish addressability *
37 ;* to command line parms (DS:SI) *
38 ;* Establish addressability to PARM *
39 ;* control block (ES:DI) *
41 ;* Call SYSPARSE for filename *
42 ;* GET Parse Block results *
44 ;* CALL SYSDISPLAY_MSG (Class 2)*
45 ;* DISPLAY_MSG = PARSE_NUM *
47 ;* SUCCESSFUL_PARSE (0 or -1) *
49 ;* GET_PARSE_RESULTS Path_Spec *
50 ;* IF No path exist then *
51 ;* assume current directory *
52 ;* assume default filename *
54 ;* IF No Drive exist then *
55 ;* Use Current Drive *
57 ;* IF No filename exist then *
58 ;* assume default filename *
59 ;* and concatenate with drive *
62 ;* IF PATH EXIST THAN *
63 ;* INSTALL_NLS (NLS_RESCODE) *
65 ;* ELSE NOT PATH_EXIST THAN *
66 ;* GET_PARSE_RESULTS (Class 3) *
67 ;* PASS_TO_MSGTXT (Message 003) *
68 ;* (File not found %1) *
69 ;* ERR_CODE SET TO 2 *
74 ;* CHECK INSTALL FLAG *
77 ;* PASS_TO_MGSTXT (Msg 002) *
78 ;* %1 already installed *
81 ;* TERMINATE & STAY RESIDENT *
86 ;* CHECK FOR ERRORCODE *
88 ;***************************************
91 ; Get the current 2f handler in the chain
92 ; make it the next install my handler in the
93 ; beginning of the the chain using get interrupt (25)
94 ; and set interrupt (35); Once in the chain
95 ; terminate and stay resident.
99 ;Install Dos Interface Logic
100 ; Dos issues Call Install
101 ; Establish residency
102 ; If Mult Id is mine (* NLSFUNC*)
103 ; CheckInstall Status to see if installed or not
105 ; jump to the next 2f handler
107 ; If not installed returns
108 ; If installed program is executed (*NLSFUNC resident portion *)
109 ;*******************************************************************************
113 ; Check to make sure not reserved DOS number in the al
115 ; Go establish which function is to be performed
125 ; otherwise error_routine
131 ;INSTALL NLSFUNC must be installed in mem
132 ; return 0FFh that I am installed
136 ; (* Means Set codepage and "select" device drivers*)
137 ; same at funcode 3 plus device drivers are invoked with the
138 ; specified code page.
142 ; (* Get_extended_country info issued by DOS not in buffer*)
144 ; call trans_Cty_Data Proc
149 ; (* Means Set codepage *)
150 ; On entry DOS gives me the CODEP in BX & the CC in DX,SIZE in CX
151 ; Search for Country.sys file on disk
152 ; if file is found }BUFFER will exist in code 320 (can be altered)
153 ; the control buffer = 64 bytes of the buffer
154 ; the data buffer = 256 bytes of the buffer
155 ; call Trans_Cty_Data Proc
156 ; otherwise return an error flag
162 ; (* Get_extended_country info - old 38 call*)
163 ; set flag and same as funcode 2
164 ; data returned slightly Revised
167 ; ****************************
168 ; if selected is FUNCTION 1, 3
169 ; PassDOS_Data(*ES:DI*)
170 ; otherwise FUNCTION 2, 4
172 ; Flag that it is function 2
173 ; PassUserData(*ES:DI*)
174 ; mov NO_ERRORS to ERROR_FLAG
175 ; ****************************
177 ; Open file(Dos call back 38)
178 ; Do an LSEEK to move CTY_INFO into NLSFUNC control buffer 39
179 ; Do an LSEEK to move tables into NLSFUNC data buffer 39
180 ; if R/W pointer ok on Disk
181 ; Read the file(Dos call back 38)
182 ; Check to see if it is FUNCTION 1 or FUNCTION 2
185 ; Search for user specified INFO ID
186 ; until found or report back error to DOS & exit
187 ; if INFO ID is found
188 ; godo move the data and set the counter to zero (entry value)
193 ;MOVE_DATA: Manage transfer from disk to buffer
194 ; Check to see if entire entry can fit in to the data
195 ; buffer if not read the maximum allowed into buffer
196 ; Check to see what is left to read; read until no more
197 ; Search for appropriate field in the DOS INFO
198 ; if found move in info until complete
199 ; get the next entry until number of entries is 0
201 ; report to DOS error and exit
202 ; loop back to read file until (all entries are Obtained) or (EOF)
203 ; Close file handle (Dos call back 40)
204 ; otherwise mov 05h to error_flag & jump to error_routine
214 ;*******************************************************************************
215 ;**********************************INTRO****************************************
216 subttl Revision History
218 ;****************************** Revision History *************************** ;
220 ; =A 7/29/86 RG PTM P64
221 ; Prevent overwrite of DOS monocase routine entry point during
222 ; transfer of SetCountryInfo.
223 ; For Get Ext Cty Info, put DOS monocase routine entry point into
226 ; =B 7/29/86 RG PTM P67
227 ; Correct jump condition in ERROR_ROUTINE of NLSRES_CODE.
228 ; This prevents exit without COUNTRY.SYS file close.
230 ; =C 7/30/86 RG PTM P85
231 ; Preserve ES register in NLSFUNC for IBMDOS.
233 ; =D 7/31/86 RG PTM P86
234 ; Corrects information put into user buffer for Get Extended
235 ; Country Information.
237 ; =E 7/31/85 RG DCR 18
241 ; Get Country Info - Revised info from Get Extended Country Info
244 ; Correct carry set for good exit.
247 ; Start extended info at length instead of signature.
250 ; Insert code for control buff management and actual length retunred
253 ; Improve path parameter parsing.
259 ; 65 call-get ext cty info put final csize (# bytes returned)
263 ; Set error to INVALID DATA (13) on no cp/cty match.
266 ; Additional re-design for structured code using STRUC
267 ; PARSER implementation
268 ; Message Retriever implementation
269 ; DBCS Support for Environmental Vector recognition (Walk Devices& IOCTL call)
270 ; Enable the Interrupt when NLSFUNC is loaded PTM ???
272 ;AN001; P2685 NLSFUNC should not visit the same device repeatedly. 01/15/88 J.K.
273 ;AN002; P3934 Bad write on sacred DOS area - segmentation incorrect 03/22/88 CNS
274 ;*******************************************************************************
277 PUSHALL
macro reg1
,reg2
,reg3
;used to save all
278 push reg1
;registers needed
279 push reg2
;for DOS interactions
283 POPALL
macro reg1
,reg2
,reg3
;used to restore all
284 pop reg3
;for DOS interactions
289 ;SHOWERR macro msg,len_msg
292 ; lea dx,msg ;displays error msgs
302 NLS_DATA
SEGMENT byte PUBLIC 'DATA'
304 ;Copyright 1988 Microsoft
305 ;***************************** MSG DATA ************************************
306 UTILITY db "NLSFUNC",0 ;AC000;
307 ;***************************** MSG DATA ************************************
310 include copyrigh
.inc ;AN000;
314 include sf
.inc ;AN001;
317 include SYSMSG
.INC ;AN000;
318 include FUNCDBCS
.INC ;AN000;
320 include FUNCPARM
.INC ;AN000;
322 MSG_UTILNAME
<NLSFUNC
> ;AN000;
327 ; nlsfunc function codes
329 GET_EXT_CTY_INFO equ
2
333 INVALID_FUNCTION equ
1 ;=J
334 INVALID_DATA equ
13 ;=L
335 ;FILE_NOT_FOUND equ 2 ;=J(=L no longer explicitly used)
338 PAD_CHAR equ
' ' ;AN000;
339 BAD_INVOKE equ
65 ;=E
341 BUFFSIZE equ
512 ; ;AC000;REDUCTION OF ORIGINAL (128 BYTES) TO STORE
342 LOCATE_INFOTYPE equ
18 ;THE DEVICE LIST & THE OLD COUNTRY INFO
343 CTL_BUFF equ
256 ; ;AC000;
345 DATA_BUFF_LENG equ
(BUFFSIZE
- CTL_BUFF
)
346 MAXBUFF_FIT equ
(BUFFSIZE
- (CTL_BUFF
+ ID_TAG
))
347 DATA_N_ID equ
(CTL_BUFF
+ ID_TAG
)
354 ;**************** NEW VARIABLE ****************
357 IN_DEX equ bp ;AN000;
358 FILESPEC_PTR equ byte ptr ds:[in_dex] ;AN000;
359 FILEVAL equ 0100h ;convert data block after checking for the
361 ;drive only to look for the filespec
362 CL_NUM equ 81h ;command line at the PSP
364 ;**************** NEW VARIABLE ****************
377 ;variable definition area
380 MSG_SERVICES <MSGDATA>
382 ID_CHECK db 1 ;resident variable re-initialize
383 ALL_DONE db 0 ;resident variable re-initialize
384 GET_EXT db 0 ;resident variable re-initialize
385 INFO_ID db 0 ;resident variable re-initialize
386 DONT_CLOSE db 0 ;if open or close error,this is set
388 RES_PARASIZE dw 0 ;adjusted size for terminate & stay func.
389 ERROR_CODE db 0 ;contains extended error code val
390 FUNC_CODE db 0 ;save function number
396 SAVEDX dw 0 ;=FC file offset
402 VALID_FUNC db 0 ;Flag to check for valid function #
404 FILENAME db "COUNTRY.SYS",0
405 PATH_SPEC db 64 dup(0) ;used to build path parameter
414 CUR_PTR DW 0 ;AN003;; keeps track of parameter position ;AN000
415 OLD_PTR DW 0 ;AN003;; keeps track of parameter position ;AN000
417 ;********************************************************************************
418 NLS_BUFFER db BUFFSIZE dup (?) ;NLS BUFFER to transfer data
421 DATASIZE equ $-NLS_DATA
425 NLS_INIT_CODE SEGMENT BYTE PUBLIC 'CODE'
427 ASSUME CS:NLS_INIT_CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING
431 INT_2f_NEXT DD ? ;Chain location.
435 ;**************************** resident portion ********************************
437 NLSRES_CODE PROC NEAR
438 cmp ah,MULT_NLSFUNC ;Check the mutliplex value
439 je IS_NLSFUNC ;the # is mine
440 jmp dword ptr INT_2F_NEXT ;Chain to* the next handler
445 cmp al,0f8h ;Make sure AL does not have reserved
446 ;DOS value 0F8 - 0FFH
447 jb SEL_FUNC ;Select the function code between 0,
450 iret ;return on reserved functions
456 push ds ;save the user's data segment
459 push ax ;save the function value
463 mov ax,NLS_DATA ;so it won't be hosed
464 mov ds,ax ;set the data segment to mine
472 mov ID_CHECK,1 ;re-intialize flags
473 mov ALL_DONE,0 ;from resident portion
476 mov VALID_FUNC,0 ;Flag to check for valid function #
477 mov DONT_CLOSE,0 ;no open or close error yet
479 pushall bx,cx,dx ;save all DOS registers
480 pushall bp,si,di ;save all DOS registers
481 ; *************************** CNS **********************************************
482 sti ;;AN000;the interrupt for external devices
484 ; *************************** CNS **********************************************
485 mov FUNC_CODE,al ;save function #
487 jne FUNCODE_DOSTATE ;state is not 0
488 mov al,INSTALLED ;Tell DOS I am installed
496 cmp al,GET_EXT_CTY_INFO
503 FUNCODE4: ;Get Country Data - old 38 call =F
504 mov bp,1 ;set info_id to 1 =F
505 jmp short FUNCODE2 ; =F
508 FUNCODE3_1: ;Set Codepage/Get Country Information =E
509 les di,dword ptr SI_DOSLOCATE
510 ; cmp es:[di].ccDosCodePage,bx ;=E
512 ; cmp es:[di].ccDosCountry,dx ;=E
514 ; mov CPAGE,bx ;get the codepage value =E
515 ; jmp short fc3_1_20 ;=E
520 CallInstall Dosclose,multdos,39,<ax,bx,cx,dx,ds,es>,<es,ds,dx,cx,bx,ax> ;close the file
527 jmp short RES_EXIT ;=E
530 FUNCODE2: ;Get Extended Country Information
531 mov ax,bp ;information requested by the user
533 mov GET_EXT,1 ;get extended cty into user buffer
537 jmp short CLOSE_FILE ;=E
540 FUNCODE1: ;CHCP - Change Code Page =E
541 call WALK_DEVICES ;=E
543 jmp short RES_EXIT ;=E
547 CLOSE_FILE: ;DOS 3eh function close COUNTRY.SYS
550 CallInstall Dosclose,multdos,39,<ax,bx,cx,dx,ds,es>,<es,ds,dx,cx,bx,ax> ;close the file
552 ;clear to let DOS know ok
556 popall bp,si,di ;restore all DOS registers
557 popall bx,cx,dx ;restore all DOS registers
559 cmp FUNC_CODE,GET_EXT_CTY_INFO ; =K
561 cmp al,0 ;if successful 65 call, put size =K
562 jne NC_IRET ;of info returned in CX =K
566 pop ds ;restore user's data segment =K moved
574 ;if an error was detected
584 ;*******************************END OF NLSRES_CODE******************************
585 subttl resident main routine
587 ;*******************************RES_MAIN****************************************
590 mov VALID_FUNC,1 ;function exist
591 mov CPAGE,bx ;get the codepage value
592 mov CCODE,dx ;get the country code
593 mov CSIZE,cx ;size of the buffer
594 call CHK_OPEN ;go open file if possible
595 jc END_RES ;scan and read country info
599 mov si,offset NLS_BUFFER
601 ;into my buffer & the dos buffer
606 ;*******************************END RES_MAIN************************************
607 subttl check open procedure
609 ;******************************CHECK OPEN PROCEDURE****************************
613 xor cx,cx ;zero cx for open
614 cmp USER_PATH,1 ;either user supplied=I
615 je co_user ;or default DOS
617 co_dos: push ds ;save current ds value
618 push si ;save current si value
619 lds si,dword ptr SI_DOSLOCATE ;old dos ds si value
620 lea dx,ds:[si].ccPATH_COUNTRYSYS
621 CallInstall Dosopen,Multdos,38,<BX,DS,ES,SI,DI>,<DI,SI,ES,DS,BX>
622 pop si ;restore current si
623 pop ds ;restore current ds
626 co_user: lea dx,PATH_SPEC
627 CallInstall Dosopen,Multdos,38,<BX,DS,ES,SI,DI>,<DI,SI,ES,DS,BX>
629 co_10: jc BADREP_FILE ;bx contains the
630 mov bx,ax ;file handle
641 ;******************************END OF CHKOPEN**********************************
642 subttl transfer country data
644 ;******************************TRANS_CTY__DATA ********************************
645 TRANS_CTY_DATA PROC NEAR
648 push di ;save start of CTY/CP INFO
649 ;get the size of the file
650 xor cx,cx ;clear cx to start at
651 xor dx,dx ;at the beginning of the
653 call READ_CTLBUFF ;Read in the file header
658 add si,LOCATE_INFOTYPE ;si > Country info type
659 cmp byte ptr ds:[si],1 ;only 1 type exist currently
663 inc si ;si > set to file offset
664 mov dx,word ptr ds:[si] ;Get the Info file offset
665 mov cx,word ptr ds:[si+2] ;Doubleword
667 mov SAVEDX,dx ;=FC save offset
668 mov SAVECX,cx ;=FC for more than 1 buffer
669 mov NOFFSET,2 ;=FC start from beginning
671 call READ_CTLBUFF ;Read Info
677 mov cx,word ptr ds:[si] ;Get count of entries
680 inc si ;si > Entry info packet
682 FIND_CTY: ;Search for CTY/CP combo
684 mov ax,word ptr ds:[si] ;=FC get size of entry
685 add ax,2 ;=FC include length filed
686 add NOFFSET,ax ;=FC look ahead
687 cmp NOFFSET,CTL_BUFF-4 ;=FC < (256 - 4)
689 sub NOFFSET,ax ;=FC restore to old offset
690 push cx ;=FC save number of cntries
691 mov cx,SAVECX ;=FC get file offset
693 add dx,NOFFSET ;=FC update to the entry
694 adc cx,0 ;=FC beginning
695 mov SAVECX,cx ;=FC save them for next use
697 call READ_CTLBUFF ;=FC read next buffer in
698 jc READERROR ;=FC read error occurs
699 pop cx ;=FC restore number of cntries
700 mov NOFFSET,0 ;=FC a new beginning
705 cmp ax,word ptr ds:[si+2] ;compare country id
707 cmp dx, word ptr ds:[si+4] ;compare code page id
709 cmp dx,0 ;=FC if default pick the
710 jz FOUND_CTY2 ;=FC 1st country
713 add si, word ptr ds:[si] ;next entry
715 inc si ;take a word for size of entry itself
718 mov ALL_DONE,INVALID_DATA ;if it exits the loop =J =L
719 jmp FINDCTY_FAIL ;then no cp/cty match
721 READERROR: pop cx ;=FC
724 FOUND_CTY2: mov dx,word ptr ds:[si+4] ;=FC from now on,this is
725 mov CPAGE,dx ;=FC the code page
727 FOUND_CTY: ;found the matching entry
728 mov dx, word ptr ds:[si+10] ;get the file offset of country data
729 mov cx, word ptr ds:[si+12]
734 mov cx, word ptr ds:[si] ;get the number of entries to handle.
736 inc si ;SI -> first entry
740 push di ;ES:DI -> DOS_COUNTRY_CDPG_INFO
741 push si ;si -> current entry in Control buffer
742 push cx ;save # of entry left
744 mov al, byte ptr ds:[si+2] ;get data entry id
745 xor ah,ah ;clear out for comparison with
746 ;info-id in case id is > 256
750 cmp GET_EXT,1 ;check to see if function 2
751 ;get_extended info was needed
752 jne TRANSALL ;if not assume function code 1
755 cmp INFO_ID,-1 ;Minus 1 means return all of the
756 jne CHK_ID ;country info to the user
757 ;otherwise get the specific
758 ;info id and return only that info
761 pop cx ;error can not return all
762 pop si ;info accept for currently
763 pop di ;loaded control info in DOS
766 CHK_ID: cmp al,INFO_ID ;check to see if the selected
767 ;id is the same as the id in the
770 jne SETDOSCTY_NEXT ;if not equal go search for the
773 pop cx ;Bingo!! Found it set counter
774 mov cx,1 ;to zero to exit loop
776 mov ID_CHECK,0 ;found a valid id
777 cmp GET_EXT,1 ;after transferring data to USER
780 ;set cx image in stack to force
786 call GetDOSCTY_Dest ;get the address of destination in ES:DI
787 jc SetDOSCTY_NEXT ;No matching data entry id in DOS
791 mov dx, word ptr ds:[si+4] ;get offset of data
792 mov cx, word ptr ds:[si+6]
798 push ax ;=A save data id.
799 xor bp,bp ;DOS 4200h function
800 CallInstall Lseek,multdos,40,<bx,cx,ds,es,di,si>,<si,di,es,ds,cx,bx> ;move ptr
804 mov dx,offset NLS_BUFFER +CTL_BUFF ;set the buffer to the beginning of the
807 mov cx,DATA_BUFF_LENG ;set to number of bytes in the
811 CallInstall Dosread,Multdos,41,<bx,cx,ds,es,di,si>,<si,di,es,ds,cx,bx> ;Read cx many bytes into the buffer
819 jmp short SETDOSCTY_NEXT
823 ; If SetCountryInfo, then
824 ; put DOS monocase routine
826 ; NLS_BUFFER so don't
828 cmp al,SetCountryInfo ;=A
830 mov ax,word ptr es:[di+24] ;=A
831 mov word ptr ds:[NLS_BUFFER+CTL_BUFF + 32],ax ;=A
832 mov ax,word ptr es:[di+26] ;=A
833 mov word ptr ds:[NLS_BUFFER+CTL_BUFF + 34],ax ;=A
835 mov ax,CPAGE ;=FC, CPAGE is right
836 mov word ptr ds:[NLS_BUFFER+CTL_BUFF + 12],ax ;=FC
839 call CHK_ADJUST ;now check to see if the entire
847 add si, word ptr ds:[si]
851 .UNTIL <cx eq 0> NEAR ;loop SETDOSCTY_DATA
853 ;Check for an invalid id
854 cmp GET_EXT,1 ;Check to see if a get_ext func 2 was issued
855 jne CTLSEEKnREAD ;if not move on
856 cmp ID_CHECK,1 ;if so check to see if an id was found
857 je BAD_SETID ;if none was found report an error
863 jmp short END_TRANS ;exit
875 mov ALL_DONE,INVALID_FUNCTION ;=J
876 jmp short FINDCTY_FAIL ;=J
879 mov ALL_DONE,INVALID_FUNCTION ;=J
885 pop di ;Restore header start
892 ;******************************END TRANS_CTY_DATA ******************************
893 subttl get DOS country destination
895 ;****************************GETCTY_DEST***********************************************
896 GetDOSCty_Dest proc near
897 ;Get the destination address in the DOS country info table.
899 ; ES:DI -> DOS_COUNTRY_CDPG_INFO
901 ; ES:DI -> Destination address of the matching data id
902 ; carry set if no matching data id found in DOS.
905 add di, ccNumber_of_entries ;skip the reserved area, syscodepage etc.
906 mov cx, word ptr es:[di] ;get the number of entries
908 inc di ;SI -> the first start entry id
910 cmp byte ptr es:[di], al
912 cmp byte ptr es:[di], SetCountryInfo ;was it SetCountryInfo entry?
914 add di, 5 ;next data id
915 jmp short GetCntryDest_loop
918 add di, NEW_COUNTRY_SIZE + 1 ;next data id
923 jmp short GetCntryDest_exit
927 cmp al, SetCountryInfo ;select country info?
929 inc di ;now DI -> ccCountryInfoLen
931 jmp short GetCntryDest_exit
935 les di, dword ptr es:[di+1] ;get the destination in ES:DI
943 ;****************************GETDOSCTY_DEST*************************************
944 subttl get extended country data
946 ;****************************GETEXT_CTY*****************************************
951 cmp ah,GET_CTY_INFO ;=F
955 mov byte ptr es:[di],al
957 cmp INFO_ID,SetCountryInfo ;SETCTY_INFO =D moved.
958 je ID_CTYINFO ;=D don't want ptr if 1.
960 mov word ptr es:[di+1],offset nls_buffer + ctl_buff+8 ;=H
961 mov word ptr es:[di+3],ds ;my current ds value
967 inc di ;=D (old code - add di,5) =F(moved).
970 ;next line used to be "add si,5"
971 ;si needs to point to cty info. =D
972 mov si,offset nls_buffer + ctl_buff + 8 ;=D
974 push es ;=A put DOS Monocase Routine
975 push di ;=A entry point in user buffer.
977 les di,dword ptr si_doslocate ;=A
978 mov ax,word ptr es:[di].ccMono_Ptr ;=A
979 mov word ptr ds:[si+24],ax ;=A
980 mov ax,word ptr es:[di].ccMono_Ptr+2 ;=A
981 mov word ptr ds:[si+26],ax ;=A
983 mov ax,CPAGE ;=FC trust CPAGE
984 mov word ptr ds:[si+4],ax ;=FC
991 cmp ah,GET_CTY_INFO ;=F if get cty info(38) slide info
992 jne id_ctyinfo2 ;=F ptr up to date.
994 mov cx,old_country_size ;=FC
997 id_ctyinfo2: mov bx,word ptr ds:[si] ;=FC get table size
1000 sub CSIZE,3 ;=FC size begins after length field
1003 cmp cx,bx ;=D was cmped to SETCTR_LENG
1004 ja TRUNC_SIZE ;=FC used to be jg
1009 mov es:[di],cx ;=FC move actual length to user's buff
1010 add di,2 ;=FC update index
1011 add si,2 ;=FC skip length field
1013 MOVE_CTY: pop bx ;=F
1022 ;*****************************END GETEXT_CTY*************************************
1023 subttl read into control buffer
1025 ;**************************READ_CTLBUFF*****************************************
1027 READ_CTLBUFF proc near
1028 ;Move file pointer to CX:DX
1029 ;Read 64 bytes into the control buffer. Assume that the necessary data
1030 ;is within that limit.
1031 ;SI will be set to beginning of the offset my NLS_BUFFER hence DS:SI points to the control buffer.
1032 ;Entry: CX,DX offset from the start of the file where the read/write pointer
1036 ;Return: The control data information is read into DS:0 - DS:0200.
1037 ; CX,DX value destroyed.
1038 ; Carry set if error in Reading file.
1042 CallInstall Lseek,multdos,40,<bx,cx,ds,es,di,si>,<si,di,es,ds,cx,bx> ;move pointer
1045 mov dx,offset NLS_BUFFER ;ds:dx -> control buffer
1046 mov si,dx ;index for the entire buffer
1047 ;read into the buffer function 3fh
1048 mov cx, CTL_BUFF ;XXX bytes. Size of the information
1049 CallInstall Dosread,multdos,41,<bx,cx,dx,ds,es,di,si>,<si,di,es,ds,dx,cx,bx> ;should be less than XXX bytes.
1061 RICB_exit: ;In this case 64 bytes
1065 ;****************************END READ_CTLBUFF***********************************
1066 subttl check / adjust / move data into DOS buffer
1068 ;****************************CHK_ADJUST*****************************************
1069 CHK_ADJUST PROC NEAR
1071 push ax ;save info id
1072 mov si,offset NLS_BUFFER+DATA_N_ID ;start of buffer + tag id
1073 mov cx, word ptr ds:[si] ;get the length of the structure
1087 mov dx,offset NLS_BUFFER+CTL_BUFF ;reset to the beginning of the data buffer
1088 mov si,dx ;reset to the beginning of the data buffer
1089 cmp cx,DATA_BUFF_LENG ;check to see if it fits for the nth read
1090 jbe LAST_READ ;last portion fits
1091 push cx ;save how much is left to read
1092 mov cx,DATA_BUFF_LENG ;set to how much you read at one time
1094 ;read again ;function 3fh
1095 ;read into the data buffer
1096 CallInstall Dosread,multdos,41,<bx,cx,dx,ds,es,di,si>,<si,di,es,ds,dx,cx,bx> ;save the file handle
1099 rep movsb ;move data into DOS area
1100 pop cx ;restore size remaining to
1101 sub cx,DATA_BUFF_LENG ;be read get new size
1102 jmp NEED_ADJUST ;must read agian
1106 CallInstall Dosread,multdos,41,<bx,cx,dx,ds,es,di,si>,<si,di,es,ds,dx,cx,bx>
1110 rep movsb ;move data into DOS area
1116 ;*******************************END CHK_ADJUST *********************************
1117 subttl walk through device drivers and invoke
1119 ;************************ WALK DEVICE DRIVERS **********************************
1120 ;=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=
1122 WALK_DEVICES PROC NEAR
1124 mov si,offset NLS_BUFFER ;Prepare to hold device name
1125 push es ;AN001; Clear out NLS_BUFFER to 0
1128 mov di, si ;AN001; ES:DI-> NLS_BUFFER
1129 xor ax, ax ;AN001; AX=0
1130 mov cx, BUFFSIZE ;AN001;
1131 shr cx, 1 ;AN001; /2 to make a # of words
1133 pop es ;AN001; Restore es
1134 ;Get ptr to hdr of 1st device.
1136 CallInstall GetDevLst,Multdos,44,<DS>,<DS>
1138 mov es,bx ;bx:ax -> hdr.
1141 test es:[di].sdevatt,devtyp ;check attribute word for
1143 jmp GET_NEXT_DEVICE ;character device.
1147 push di ;set up asciiz filename
1148 add di,10 ;for DOS file open
1151 set_asciiz: mov al,es:[di]
1159 done_set_asciiz:xor al,al
1165 mov cx,1 ;open for write
1167 CallInstall Dosopen,Multdos,38,<DS,SI,ES,DI>,<DI,ES,SI,DS>
1169 jmp GET_NEXT_DEVICE ; ignore this =FC
1172 mov bx,ax ;put handle in bx
1173 call Chk_Revisit ;AN001; Have been here already?
1174 jnc INVOKE_DEVICE ;AN001; No, a new one.
1175 jmp CLOSE_DEVICE ;AN001; Yes. Close and ignore this.
1178 push ds ;Check print queue first.
1179 push si ;Set up for 2f print call.
1181 mov ax,0106h ;2f call to command.com.
1182 int 2fh ;If print active: carry set,
1183 jnc invoke_it ;DS:SI -> hdr of printing device.
1184 cmp si,di ;Check if printing device is this
1185 jne invoke_it ;device. Match on ptr to device.
1193 mov ALL_DONE,BAD_INVOKE ;Match. Set invoke error.
1196 invoke_it: pop si ;save the current
1199 ;*************** CNS *********** Start of DBCS Support
1206 ; mov ax,word ptr ds:[bx] ;ICE
1207 ; mov word ptr ds:[bx],ax ;ICE
1215 les di,dword ptr SI_DOSLOCATE ;get the environmental
1216 ;*************** CNS ******************
1217 ; mov bx,es:[di].ccDBCS_ptr ;values to allow
1218 ; mov es,es:[di].ccDBCS_ptr+2 ;recognition and
1219 ;*************** CNS ******************
1220 les bx,es:[di].ccDBCS_ptr
1221 mov cx,es:[bx] ;invocation of data
1223 add bx,2 ;and ID for start
1224 mov di,offset pk.DBCS_EV ;and stop values for
1225 ;otherwise it is a DBCS
1226 ;****CHANGE ;or custom designed codepage
1228 mov PK.PACKLEN,cx ;if packet length is zero
1231 add cx,-2 ;AN002; reset counter before CP addition
1236 cmp cx,0 ;AN002;no need to alter packet
1237 je NO_LOAD ;An002;initialized to zero
1240 .REPEAT ;;AN000;DBCS transmission
1242 mov al,es:[bx] ;;AN000;get the the contents
1244 mov ds:[di],al ;;AN002;of where the DBCS Points
1246 inc di ;;AN000;data packet for ioctl
1248 inc bx ;AN000;;call--- get the start
1249 ;stop values to load
1253 .UNTIL <CX EQ 0 > ;AN000;
1254 ;invocation of 1 codepage
1255 ;standard codepage selection
1260 pop es ;AN000;;accordingly & restore
1262 pop cx ;AN000;;values
1267 ;AN000;;invoke codepage
1268 ;************************ CNS*** End of DBCS
1270 ;Set up data packet for generic
1271 mov ax,cpage ;ioctl call.
1276 mov bp,0ch ;generic ioctl
1277 CallInstall IOCTL,multdos,43,<DS,SI,ES,DI,BX>,<BX,DI,ES,SI,DS>
1282 CallInstall Dosclose,multdos,39,<DS,SI,ES,DI>,<DI,ES,SI,DS>
1283 jc dev_open_close_error ; ignore this =FC
1286 cmp word ptr es:[di],0FFFFH
1288 les di,dword ptr es:[di]
1294 CallInstall GetExtErr,multdos,45,<DS,SI,ES,DI,BX>,<BX,DI,ES,SI,DS>
1297 mov ALL_DONE,BAD_INVOKE
1300 dev_open_close_error:
1301 mov ALL_DONE,BAD_INVOKE
1310 ;*********************** END WALK DEVICE DRIVERS *******************************
1311 ;************************ Chk_Revisit******************************************
1312 ;This routine will check if we are opening the same device driver again.
1313 ;If it is, then carry bit will set.
1314 ;This routine will use the NLS_BUFFER to keep the history of already
1315 ;visited device driver address (OFFSET,SEGMENT). NLS_BUFFER will be
1316 ;used from the end of the buffer towards to the front of the buffer.
1317 ;For 512 byte length and considering the front part used for OPEN device
1318 ;driver name string, this will handle appr. 126 devices maximum. which is
1319 ;sufficient enough. - J.K. 1/15/88
1320 ;IN: BX = file handle
1321 ; DS = NLS_BUFFER segment
1322 ;OUT: carry set = visited
1323 ; carry not set = new one.
1324 ; Other registers saved.
1326 Chk_Revisit proc near
1331 mov ax, 1220h ;AN001; Get the spot of SFT
1333 jc Chk_Rvst_Ret ;AN001; This won't happen
1335 mov bl, byte ptr es:[di] ;AN001;
1336 mov ax, 1216h ;AN001; Get the SFT pointer
1337 int 2fh ;AN001; es:di-> SFT table
1338 jc Chk_Rvst_Ret ;AN001; This won't happen
1339 mov ax, word ptr es:[di].SF_DEVPTR ;AN001; offset of device
1340 mov bx, word ptr es:[di].SF_DEVPTR+2;AN001; Segment of device
1341 mov di, offset NLS_BUFFER ;AN001;
1342 add di, BUFFSIZE-2 ;AN001; ds:di-> last word of the buffer
1343 Chk_Rvst_While: ;AN001;
1344 cmp word ptr ds:[di], 0 ;AN001; di-> segment value
1345 jne Chk_Rvst_Cont ;AN001;
1346 cmp word ptr ds:[di-2], 0 ;AN001; offset
1347 jne Chk_Rvst_Cont ;AN001;
1348 jmp Chk_Rvst_New ;AN001; Encountered a blank entry in the buffer
1349 Chk_Rvst_Cont: ;AN001;
1350 cmp word ptr ds:[di], bx ;AN001;
1351 jne Chk_Rvst_Next ;AN001;
1352 cmp word ptr ds:[di-2], ax ;AN001;
1353 jne Chk_Rvst_Next ;AN001;
1354 stc ;AN001; found a match
1355 jmp Chk_Rvst_Ret ;AN001;
1356 Chk_Rvst_Next: ;AN001;
1357 sub di, 4 ;AN001; move the pointer to the next entry
1358 jmp Chk_Rvst_While ;AN001;
1359 Chk_Rvst_New: ;AN001;
1360 mov word ptr ds:[di],bx ;AN001; Keep the current open device segment
1361 mov word ptr ds:[di-2], ax ;AN001; and offset
1362 clc ;AN001; New device
1363 Chk_Rvst_Ret: ;AN001;
1371 subttl end nlsfunc resident code
1373 NLSRES_LENG equ $-NLSRES_CODE+DATASIZE
1374 subttl initialization
1376 ;***************************** NLSFUNC Initialization **************************
1378 ASSUME CS:NLS_INIT_CODE,SS:STACK
1384 mov ax,NLS_DATA ;set up data segment
1390 call SYSLOADMSG ;does DOS version check
1393 mov dx,NLSRES_LENG ;calculate paragraph
1395 shr dx,1 ;divide by 16 to get conversion from
1396 shr dx,1 ;bytes to paragraphs
1399 add dx,11h ;size based on the byte size of
1400 mov RES_PARASIZE,dx ;the resident procedure
1409 .IF <NO_PARMS eq 1> or
1410 .IF <GOOD_PATH eq 1>
1411 call INSTALL_NLS ;let's install NLSFUNC
1413 mov EXIT_STAY,1 ;if nothing wrong occured
1416 ;determine path of exit
1418 ;****************************** EXIT PROG *********************************************
1419 push ax ;AN004;save existing values
1426 mov ax,4900H ;AN004;make the free allocate mem func
1430 pop es ;AN004;restore existing values
1433 .IF <EXIT_STAY eq 1> ;Terminate and stay resident
1434 mov bx,4 ;1st close file handles
1442 mov dx,RES_PARASIZE ;paragraphs allocated
1445 mov ah,04ch ;value passed to ERRORLEVEL
1448 mov al,ERROR_CODE ;check for an error
1458 ;****************************** EXIT PROG *********************************************
1461 ; On entry: ES points at the PSP
1462 ; DS points at NLS_DATA
1463 ; DX was used to calculate paragraph size
1465 ; PARSER EFFECTS ES & DS wil be swapped
1467 ; Changes : ES:DI seg:off containing PARM Input Block
1468 ; to DS:SI seg:off containing command line
1476 ;****************************** PROCESS PATH ***********************************
1477 ;=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=
1479 PROCESS_PATH PROC NEAR
1481 ;to command line parms
1484 push es ;;AC000;e original es (nothing)
1486 push ds ;AC000;he original ds (Nls_data)
1488 push ds ;save for both es & ds to point at data
1490 push es ;AC000;hat's in my es the PSP value
1492 push ds ;AN000;he segment id that points to my
1493 ;es now points to data
1495 ;input parameter control block (NLS_DATA)
1498 pop ds ;AN000; points to the segment for
1499 ;the command line string
1502 ASSUME DS:NOTHING,ES:NLS_DATA
1509 mov si,80h ;get the command line length
1511 mov cl,byte ptr ds:[si] ;get the length for the counter
1513 mov LENGTH_HOLD,cl ;save the length of the command line
1520 mov di,OFFSET NLS_BUFFER ;
1523 ; mov di,OFFSET PATH_SPEC ;
1527 mov si,CL_NUM ;AN000; points to the offset command
1528 ;line input string at value 81h
1531 rep movsb ;transfer command line to NLS_BUFFER
1542 mov di,OFFSET NLS_PARMS ;AN000; into ES of the PARMS INPUT
1545 pop ds ; ds also point at NLS_DATA
1551 mov si,OFFSET NLS_BUFFER ;si now points to the offset command
1554 PUSH AX ;AN003;Save environment
1555 MOV AX,CUR_PTR ;AN003;Set advancing ptr to end of argument
1556 MOV OLD_PTR,AX ;AN003;after saving the beginning the string
1557 MOV CUR_PTR,SI ;AN003;
1558 POP AX ;AN003;Restore the environment
1564 xor cx,cx ;AN000;l value should be atleast 1
1565 xor dx,dx ;AN000;ut dx for input into the PARSER
1568 .WHILE <PAR_RETC eq 0> ;AN000;
1569 call SYSPARSE ;AN000;empt to parse
1572 PUSH AX ;AN003;Save environment
1573 MOV AX,CUR_PTR ;AN003;Set advancing ptr to end of argument
1574 MOV OLD_PTR,AX ;AN003;after saving the beginning the string
1575 MOV CUR_PTR,SI ;AN003;
1576 POP AX ;AN003;Restore the environment
1580 .IF <Res_type eq 5> ;AN000;ound
1582 mov USER_PATH,1 ;AN000;;path specified
1586 mov PAR_RETC,AX ;AN000;;keep parsing until eoln
1591 .IF <PAR_RETC gt 0> ;AN000;;parse error
1593 ; .IF <PAR_RETC eq 3> ;AN003;IF invalid switch return command line
1598 LEA DI,PATH_SPEC ;AN003;Set PTR to look at the STRING
1599 PUSH SI ;AN003;Save current SI index
1601 MOV AX,OLD_PTR ;AN003;Last locale of the end of a PARAM
1602 SUB CUR_PTR,AX ;AN003;Get the length via the PSP
1604 MOV CX,SI ;AN003;Save it in CX to move in the chars
1605 POP AX ;AN003;Restore the PTR to the command line position
1607 MOV SI,OLD_PTR ;AN003;Last locale of the end of a PARAM
1608 REP MOVSB ;AN003;Move in the chars until no more
1610 LEA DI,PATH_SPEC ;AN003;Set PTR to look at the STRING
1612 POP SI ;AN003;Restore the PTR to the command line position
1618 mov bx,STDERR ;AN003;
1619 mov dl,no_input ;AN003;
1620 mov dh,PARSE_ERR_CLASS ;AN003;
1621 mov ds,PATHSEG ;AN003;
1622 mov si,OFFSET PARMLIST3 ;AN003;
1623 call SYSDISPMSG ;AN003;
1624 mov PARSE_ERR,1 ;AN003;;PARSE ERROR OCCURED
1628 ; xor cx,cx ;AN000;;
1629 ; mov bx,STDERR ;AN000;
1630 ; mov dl,no_input ;AN000;
1631 ; mov dh,PARSE_ERR_CLASS ;AN000;
1632 ; mov ds,PATHSEG ;AN000;
1634 ; call SYSDISPMSG ;AN000;
1635 ; mov PARSE_ERR,1 ;AN000;;PARSE ERROR OCCURED
1639 .ELSEIF <CX eq 1> ;AN000;ordinal check
1641 mov GOOD_PAR,1 ;AN000;you are at the end of the line
1644 mov NO_PARMS,1 ;AN000;there is no argument go install
1645 .ENDIF ;AN000;NLSFUNC
1647 .IF <PARSE_ERR eq 0> NEAR ;AN000;if not true you encountered a parse error
1648 .IF <GOOD_PAR eq 1> NEAR ;AN000;there is a parameter line available
1651 ;Check the flags to see what
1652 ;was returned in the return block
1654 lea di,path_spec ;AC000;es:di > final path_spec
1655 ;that will be used after fixup
1657 .IF <USER_PATH gt 0> ;AC000;drive has been solved need
1658 ;to check the filespec
1660 xor in_dex,in_dex ;AN000;clear ctr
1661 mov bx,Res_POFF ;AN000;get file spec ptr to text
1662 push ds ;AN000;prepare for entry
1663 mov ds,Res_PSEG ;AN000;
1664 mov in_dex,bx ;AN000;string seg value if filename
1665 .ENDIF ;user path ;AN000;
1668 .WHILE <Filespec_PTR ne NULL> ;load chars until no more
1671 mov al,FILESPEC_PTR ;AN000;
1672 mov byte ptr es:[di],al ;move value into pathspec and
1673 inc in_dex ;increment to next char position
1677 ;************************** CNS **********************************************
1678 ;The new method of checking for a "bogus" file will be to attempt an
1679 ;open on the path_spec if pathspec exist close path and continue if
1680 ;carry set stuff error code with 02 and exit.....
1681 ;*****************************************************************************
1683 pop ds ;into find first
1689 mov byte ptr ds:[si],NULL ;add asciiz value
1691 lea dx,PATH_SPEC ;check full pathname
1694 ;set up addressability
1696 clc ;ok-clear carry/exit
1701 mov bx,STDERR ;AN000;
1702 mov dl,no_input ;AN000;
1703 mov dh,UTILITY_MSG_CLASS ;AN000;
1704 mov ds,PATHSEG ;AN000;
1705 mov si,OFFSET PARMLIST1 ;AN000;
1706 call SYSDISPMSG ;AN000;
1717 .ENDIF ;EXIT on bad parse
1718 .ENDIF ;END OF PROCESS PATH
1721 pop ds ;AN000;;restore original ds (NLS_DATA)
1723 pop es ;AN000;;restore original es (nothing)
1725 ;AN000;;after munging around with the PARSER
1727 ASSUME DS:NLS_DATA,ES:NOTHING
1737 ;****************************** CNS *******************************************
1738 subttl install NLSFUNC
1740 ;******************************** INSTALL NLSFUNC *****************************
1742 INSTALL_NLS PROC NEAR
1744 xor ax,ax ;clear the ax
1745 mov ah,MULT_NLSFUNC ;load in my multiplex
1746 INT 2fh ;id value 14
1747 or al,al ;check to see if
1748 ; jz DO_INSTALL ;hooked in the chain
1749 ; *********************** CNS *************************************************
1754 mov al,2fh ;Get interrupt
1755 mov ah,GET_INT ;2f in the chain
1757 mov word ptr INT_2f_NEXT+2,ES ;store the address
1758 mov word ptr INT_2f_NEXT,BX ;to make the current
1759 push ds ;2f handler next in
1761 pop ds ;set Dataseg to the Code
1762 mov dx,offset NLSRES_CODE ;give start address
1763 mov al,2fh ;of resident logic
1764 mov ah,SET_INT ;set the 2f in the
1766 pop ds ;restore original ds
1769 ;FREE THE ENVIRONMENT ;no then install
1771 ; push ax ;AN004;save existing values
1773 ; mov ah,49H ;AN004;make the free allocate mem func
1774 ; mov es,es:[2ch] ;AN004;get the segment address
1776 ; pop es ;AN004;restore existing values
1780 ;TBR Message retriever ;otherwise
1783 mov bx,STDERR ;AN000;
1784 mov dl,no_input ;AN000;
1785 mov dh,UTILITY_MSG_CLASS ;AN000;
1787 mov si,OFFSET PARMLIST2
1788 call SYSDISPMSG ;AN000;
1789 mov ERROR_CODE,80 ;UTILITY ERROR CODE
1798 msg_services <LOADmsg> ;AN000;
1799 msg_services <DISPLAYmsg,CHARmsg> ;AN000;
1800 msg_services <nlsfunc.cl1,nlsfunc.cl2,nlsfunc.cla> ;AN000;
1802 ;******************************** END OF NLS_INIT_CODE **************************
1807 STACK SEGMENT PARA STACK 'STACK'