;       SCCSID = @(#)d_gctrcd.asm	6.1 91/02/15
;      SCCSID = @(#)d_gctrcd.asm	1.4 90/01/22
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************
;
;	06-Jan-87 (billme): Replace initial pushes and final pops
;	with calls to __api_begin and __api_end resp.  This will
;	reduce the size of FAPI and allow support for signals.
;
;	13-Jan-87 (billme): Clean up version code; call local version
;	provider (__api_getvrsn) and revise the logic to cut code size.
;
;
;	04-May-87 (robertc): Install hooks for DOSErrorClass Support.
;	All int 21h errors are passed through api_get_extended to get the
;	extended errorcode and to provide the class, action, and locus for
;	the dynamic error FIFO queue.
;
;/*************** START OF SPECIFICATIONS ******************************/
;/*								       */
;/* SUBROUTINE NAME: DosGetCtryInfo				       */
;/*								       */
;/* SOURCE FILE NAME: D_Gctrcd.ASM				       */
;/*								       */
;/* DESCRIPTIVE NAME: Dos Get Country Info			       */
;/*								       */
;/* FUNCTION:  Gets the Country Information			       */
;/*								       */
;/* NOTES:  @@ DosGetCtryInfo is a new routine to the 1.10 Family API  */
;/*	    Library.						       */
;/*								       */
;/* ENTRY POINT:						       */
;/*	    LINKAGE:  EXTRN DosGetCtryInfo:FAR			       */
;/*								       */
;/* INPUT:  PUSH     WORD    Length	  ;Length of data area provided*/
;/*	    PUSH@    OTHER   Structure	  ;Address of country code     */
;/*					  ;and code page	       */
;/*	    PUSH@    OTHER   MemoryBuffer ;Pointer to the data area    */
;/*					  ;to be filled		       */
;/*	    PUSH@    WORD    DataLength	  ;Length of table returned    */
;/*	    call  DosGetCtryInfo				       */
;/*								       */
;/*								       */
;/* EXIT-NORMAL:  AX = 0					       */
;/*								       */
;/* EXIT-ERROR:	 AX = Error Code				       */
;/*								       */
;/*    ReturnCode Value = 1, Error_invalid_function		       */
;/*			  ?, Country code not found in file	       */
;/*			  ?, Country information not found	       */
;/*			  ?, Error_NLS_Table_Truncated		       */
;/*			  ?, Code page value not found		       */
;/*								       */
;/* EFFECTS:  BP, ES, DS, DI, SI, BX, CX, and DX, registers are saved. */
;/*								       */
;/* PSUEDO CODE:						       */
;/*								       */
;/*	save registers						       */
;/*								       */
;/*	get DOS version						       */
;/*								       */
;/*	If version >= 3.30 goto Get_Ext_Cnty			       */
;/*	If (3.00 <= version < 3.30) goto Old_Get_Cnty_Info	       */
;/*	If version < 3.00					       */
;/*	    then AX=invalid DOS version and goto DosGetCtryExit	       */
;/*								       */
;/*	use BP as pointer to stack parameters			       */
;/*								       */
;/*Old_Get_Cnty_Info:						       */
;/*								       */
;/*	load registers for int 21 call				       */
;/*								       */
;/*	execute int 21 with function 38H			       */
;/*								       */
;/*	if carry flag set goto DOSGetCtryExit			       */
;/*								       */
;/*	Fill in buffer returned with info not returned by old	       */
;/*	get country info call, that is, length of info returned,       */
;/*	country code and code page				       */
;/*								       */
;/*	Goto Copy_into_app_buffer				       */
;/*								       */
;/*Get_Ext_Cnty:						       */
;/*								       */
;/*	load registers for int 21 call				       */
;/*	  al = 01 = Get country information			       */
;/*	  bx = codepage						       */
;/*	  dx = country_id					       */
;/*	  cx = length						       */
;/*	  es:di = address of country_info (internal buffer)	       */
;/*								       */
;/*	execute int 21 with function 6501H			       */
;/*								       */
;/*	if carry flag set goto DOSGetCtryExit			       */
;/*								       */
;/*Copy_into_app_buffer:					       */
;/*								       */
;/*	CX = Lower of caller's Length or length of ctry info.          */
;/*	Length of info is second byte of info buffer.		       */
;/*	If caller's buffer length is less than length of               */
;/*	table then truncate flag = 1				       */
;/*								       */
;/*	DataLength = CX						       */
;/*								       */
;/*	At this point, the address of the ctry table is in the	       */
;/*	buffer filled in by the get exteneded country info call.       */
;/*	We will move CX bytes from that buffer, into the caller's      */
;/*	buffer.							       */
;/*								       */
;/*	If truncate flag = 1 then AX=Error_NLS_Table_Truncated and     */
;/*	goto DOSGetCtryExit					       */
;/*								       */
;/*Exit_no_error:						       */
;/*								       */
;/*	AX=0							       */
;/*								       */
;/*DosGetCtryExit:						       */
;/*								       */
;/*	restore registers					       */
;/*								       */
;/*	return clearing stack frame				       */
;/*								       */
;/*								       */
;/* INTERNAL REFERENCES:					       */
;/*    ROUTINES:						       */
;/*								       */
;/* EXTERNAL REFERENCES:					       */
;/*    ROUTINES:    INT 21H FUNCTION 6501H    GET COUNTRY INFORMATION  */
;/*		    INT 21H FUNCTION 38??H    GET COUNTRY INFORMATION  */
;/*		    _api_getvrsn				       */
;/*								       */
;/*************** END OF SPECIFICATIONS ********************************/
;
;
; LIBRARIES
;
.XLIST
include error2.inc
include error.inc

	EXTRN	__api_begin:near
	EXTRN	__api_end:near
	EXTRN	_api_getvrsn:near
	EXTRN	api_get_extended:far	;@@ added support for DOSErrorClass
.LIST
;
; PUBLIC SYMBOLS
;
	PUBLIC	DosGetCtryInfo

	PAGE

_TEXT	segment byte public 'CODE'
	assume	CS:_TEXT,DS:NOTHING

country_info	db	42 dup (0)		; Buffer for returning from
						; Get Extended Country Info call
country_id	dw	0			; Country to return info for
						; Environment
size_cntry_info dw	42			; Size of country_info
truncate_flag	db	0			; Ctry table truncate flag
old_cntry_length     dw	    38			; PC DOS 3.20 and lower length
						; of country info returned
						; plus 4 bytes for country
						; code and code page
;
; stack frame:
; +0	bp
; +2	ip
; +4	cs
; +6	ptr_datalength
; +10	ptr_membuffer
; +14	ptr_structure
; +18	length
;
str	struc
old_bp		dw	?
return		dd	?
ptr_datalength	dd	?
ptr_membuffer	dd	?
ptr_structure	dd	?
strlength	dw	?
str	ends
;
DosGetCtryInfo	PROC	FAR

	call	__api_begin	; init bp and save bp,ds,bx,cx,dx,si,di,es
				; required to save: bp,es,ds,di,si,bx,cs,dx

		push	cs			; Set DS to CS so we can get to
		pop	ds			; our own variables
		mov	cs:truncate_flag,0	; initialize truncate flag
;
;
; Check DOS version to make sure PC DOS 3.30 or higher
;
		call	_api_getvrsn		; AH <- major, AL <- minor

		cmp	ax,031Eh		; if version >= 3.30
		jae	Get_Ext_Cnty		; then get extended country
		cmp	ah,03h			; else if version >= 3.00
		jae	Old_Get_Cnty_Info	; then old get country info
		mov	ax,error_invalid_function ; else invalid function
		jmp	NormalExit
;
; Set up get country information interrupt for PC DOS 3.20 or lower.  This
; is interrupt 21h, function call 38h.
;
Old_Get_Cnty_Info:
		les	di,[bp].ptr_structure	; Ptr_structure points to a
		mov	ax,word ptr es:[di]	; double word.	First word is
						; country code of interest.
						; Second word is code page of
						; interest.
		cmp	ax,255			; AL = country code, if
		jb	low_cntry_code		; country code < 255 o.k.
		mov	bx,ax			; else BX = country code
		mov	al,0ffh
low_cntry_code:
		mov	dx,offset country_info	; Buffer to be filled with
						; country info DS:DX
		add	dx,7			; Incr offset to make up for
						; difference in way infor is
						; returned
		mov	ah,38h			; Old get country info int

		int	21h			; Get country info

		jc	short ErrorExit		; Exit if error
Good_old_int_call:
;
		push	ds
		pop	es
		mov	di,offset country_info	; Fill in info in buffer to
						; make up for difference in
						; way info is returned
		mov	ax,Old_cntry_length	; Length of info
		mov	es:word ptr[di+1],ax
		mov	es:[di+3],BX		; Save country code
		mov	es:word ptr [di+5],0	; Zero out code page since we
						; don't know what it is
		jmp	short Copy_into_app_buffer	; Go copy into app buffer
;
; Set up get country information interrupt for PC DOS 3.30 or higher
; and CP DOS.
;
Get_Ext_Cnty:
		push	ds			; Save DS
		lds	di,[bp].ptr_structure	; Ptr_structure points to a
		mov	dx,word ptr ds:[di]	; double word.	First word is
		mov	bx,word ptr ds:[di+2]	; country code of interest.
						; Second word is code page of
						; interest.
		pop	ds			; Restore DS
		or	dx,dx			; If country code = 0, then
		jnz	not_default_cntrycode	; default is used, in PC DOS
		dec	dx			; 3.30, -1 says use active
not_default_cntrycode:
		or	bx,bx			; If code page = 0, then
		jnz	not_default_codepage	; current is used, in PC DOS
		dec	bx			; 3.30, -1 says use active
not_default_codepage:
		mov	cx,size_cntry_info	; CX = Size of cntry_info
		push	ds
		pop	es
		mov	di,offset country_info	; ES:DI = buffer to fill
		mov	ax,6501H		; Get country information
		int	21h
		jc	ErrorExit		; if error then exit
						; else copy into app buffer
;
Copy_into_app_buffer:
		mov	si,offset country_info	; Get addressabilty to data
						; returned by int call
		mov	cx,word ptr ds:[si+1]	; Length of move is length of
						; data returned
		cmp	cx,[bp].strlength	; See if list fits in caller's
						; buffer
		jna	No_truncate_ctry_list	; If yes then no truncate
		mov	truncate_flag,1		; else set truncate flag and
		mov	cx,[bp].strlength	; set counter to Length
No_truncate_ctry_list:
		les	di,[bp].ptr_DataLength	; Set DataLength = length of
		mov	es:[di],cx		; data returned
;
; The PC DOS Get Extended Country Info call returns in the buffer provided:
;     The country information.
;
		push	ds			; Save DS
		mov	si,offset country_info	; Source of move is buffer
						; filled by get extended
						; country info call
		add	si,3			; Skip over extra data int
						; returns
		les	di,[bp].ptr_membuffer	; Destination of move is app's
						; buffer
rep		movs	es:byte ptr[di],ds:byte ptr[si]
		pop	ds			; Restore DS
		cmp	truncate_flag,1		; if list truncate error
		mov	ax,Error_NLS_Table_Truncated ; then return error
		je	NormalExit
Exit_no_error:
		xor	ax,ax			; No errors returned
		jmp	short NormalExit ;@@ Added support for DOSErrorClass
ErrorExit:				;@@ added support for DOSErrorClass
		call	api_get_extended;@@ added support for DOSErrorClass
NormalExit:				;@@ added support for DOSErrorClass
	call	__api_end	; check sigs & restore es,di,si,dx,cx,bx,ds,bp

		ret	size str - 6		; Clear stack frame
DosGetCtryInfo	ENDP
_TEXT	ends
		END
