1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #define UNICODE
25 #ifdef _MSC_VER
26 #pragma warning(push,1) /* disable warnings within system headers */
27 #endif
28 #include <windows.h>
29 #ifdef _MSC_VER
30 #pragma warning(pop)
31 #endif
32 #include <wchar.h>
33
34 #include <osl/mutex.h>
35 #include <osl/nlsupport.h>
36 #include <osl/diagnose.h>
37 #include <osl/process.h>
38 #include <rtl/tencinfo.h>
39
40 struct EnumLocalesParams
41 {
42 WCHAR Language[3];
43 WCHAR Country[3];
44 LCID Locale;
45 };
46
47 static DWORD g_dwTLSLocaleEncId = (DWORD) -1;
48
49 /*****************************************************************************/
50 /* callback function test
51 /*
52 /* osl_getTextEncodingFromLocale calls EnumSystemLocalesA, so that we don't
53 /* need to provide a unicode wrapper for this function under Win9x
54 /* that means the callback function has an ansi prototype and receives
55 /* the locale strings as ansi strings
56 /*****************************************************************************/
57
EnumLocalesProcA(LPSTR lpLocaleStringA)58 BOOL CALLBACK EnumLocalesProcA( LPSTR lpLocaleStringA )
59 {
60 struct EnumLocalesParams * params;
61
62 LCID localeId;
63 LPSTR pszEndA;
64
65 WCHAR langCode[4];
66
67 /* convert hex-string to LCID */
68 localeId = strtol( lpLocaleStringA, &pszEndA, 16 );
69
70 /* check params received via TLS */
71 params = (struct EnumLocalesParams *) TlsGetValue( g_dwTLSLocaleEncId );
72 if( NULL == params || '\0' == params->Language[0] )
73 return FALSE;
74
75 /*
76 get the ISO language code for this locale
77
78 remember: we call the GetLocaleInfoW function
79 because the ansi version of this function returns
80 an error under WinNT/2000 when called with an
81 unicode only lcid
82 */
83 if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 ) )
84 {
85 WCHAR ctryCode[4];
86
87 /* continue if language code does not match */
88 if( 0 != wcscmp( langCode, params->Language ) )
89 return TRUE;
90
91 /* check if country code is set and equals the current locale */
92 if( '\0' != params->Country[0] && GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
93 {
94 /* save return value in TLS and break if found desired locale */
95 if( 0 == wcscmp( ctryCode, params->Country ) )
96 {
97 params->Locale = localeId;
98 return FALSE;
99 }
100 }
101 else
102 {
103 /* fill with default values for that language */
104 LANGID langId = LANGIDFROMLCID( localeId );
105
106 /* exchange sublanguage with SUBLANG_NEUTRAL */
107 langId = MAKELANGID( PRIMARYLANGID( langId ), SUBLANG_NEUTRAL );
108
109 /* and use default sorting order */
110 params->Locale = MAKELCID( langId, SORT_DEFAULT );
111
112 return FALSE;
113 }
114 }
115
116 /* retry by going on */
117 return TRUE;
118 }
119
120
121 /*****************************************************************************/
122 /* GetTextEncodingFromLCID
123 /*****************************************************************************/
124
GetTextEncodingFromLCID(LCID localeId)125 rtl_TextEncoding GetTextEncodingFromLCID( LCID localeId )
126 {
127 rtl_TextEncoding Encoding = RTL_TEXTENCODING_DONTKNOW;
128 WCHAR ansiCP[6];
129
130 /* query ansi codepage for given locale */
131 if( localeId && GetLocaleInfo( localeId, LOCALE_IDEFAULTANSICODEPAGE, ansiCP, 6 ) )
132 {
133 /* if GetLocaleInfo returns "0", it is a UNICODE only locale */
134 if( 0 != wcscmp( ansiCP, L"0" ) )
135 {
136 WCHAR *pwcEnd;
137 UINT codepage;
138
139 /* values returned from GetLocaleInfo are dezimal based */
140 codepage = wcstol( ansiCP, &pwcEnd, 10 );
141
142 /* find matching rtl encoding */
143 Encoding = rtl_getTextEncodingFromWindowsCodePage( codepage );
144 }
145 else
146 Encoding = RTL_TEXTENCODING_UNICODE;
147 }
148
149 return Encoding;
150 }
151
152
153 /*****************************************************************************/
154 /* osl_getTextEncodingFromLocale
155 /*****************************************************************************/
156
osl_getTextEncodingFromLocale(rtl_Locale * pLocale)157 rtl_TextEncoding SAL_CALL osl_getTextEncodingFromLocale( rtl_Locale * pLocale )
158 {
159 struct EnumLocalesParams params = { L"", L"", 0 };
160
161 /* initialise global TLS id */
162 if( (DWORD) -1 == g_dwTLSLocaleEncId )
163 {
164 oslMutex globalMutex = * osl_getGlobalMutex();
165
166 /* initializing must be thread save */
167 osl_acquireMutex( globalMutex );
168
169 if( (DWORD) -1 == g_dwTLSLocaleEncId )
170 g_dwTLSLocaleEncId = TlsAlloc();
171
172 osl_releaseMutex( globalMutex );
173 }
174
175 /* if pLocale is NULL, use process locale as default */
176 if( NULL == pLocale )
177 osl_getProcessLocale( &pLocale );
178
179 /* copy in parameters to structure */
180 if( pLocale && pLocale->Language )
181 {
182 wcscpy( params.Language, pLocale->Language->buffer );
183
184 if( pLocale->Country )
185 wcscpy( params.Country, pLocale->Country->buffer );
186
187 /* save pointer to local structure in TLS */
188 TlsSetValue( g_dwTLSLocaleEncId, ¶ms );
189
190 /* enum all locales known to Windows */
191 EnumSystemLocalesA( EnumLocalesProcA, LCID_SUPPORTED );
192
193 /* use the LCID found in iteration */
194 return GetTextEncodingFromLCID( params.Locale );
195 }
196
197 return RTL_TEXTENCODING_DONTKNOW;
198 }
199
200 /*****************************************************************************/
201 /* imp_getProcessLocale
202 /*****************************************************************************/
203
_imp_getProcessLocale(rtl_Locale ** ppLocale)204 void _imp_getProcessLocale( rtl_Locale ** ppLocale )
205 {
206 WCHAR langCode[4];
207 WCHAR ctryCode[4];
208 LCID localeId;
209
210 OSL_ASSERT( ppLocale );
211
212 /* get the LCID to retrieve information from */
213 localeId = GetUserDefaultLCID();
214
215 /* call GetLocaleInfo to retrieve the iso codes */
216 if( GetLocaleInfo( localeId, LOCALE_SISO639LANGNAME , langCode, 4 ) &&
217 GetLocaleInfo( localeId, LOCALE_SISO3166CTRYNAME , ctryCode, 4 ) )
218 {
219 *ppLocale = rtl_locale_register( langCode, ctryCode, L"" );
220 }
221 else
222 {
223 *ppLocale = rtl_locale_register( L"C", L"", L"" );
224 }
225 }
226
227
228