kernel32: Simplify GetGeoInfoA() implementation.
[wine.git] / dlls / kernel32 / locale.c
blob4c815be43cc48e6ef2b883b5337087b141cc31ee
1 /*
2 * Locale support
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1998 David Lee Lambert
6 * Copyright 2000 Julio César Gázquez
7 * Copyright 2002 Alexandre Julliard for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include <assert.h>
25 #include <locale.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <stdlib.h>
32 #include "ntstatus.h"
33 #define WIN32_NO_STATUS
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winternl.h"
37 #include "winnls.h"
38 #include "winerror.h"
39 #include "winver.h"
40 #include "kernel_private.h"
41 #include "wine/heap.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(nls);
46 extern BOOL WINAPI Internal_EnumCalendarInfo( CALINFO_ENUMPROCW proc, LCID lcid, CALID id,
47 CALTYPE type, BOOL unicode, BOOL ex,
48 BOOL exex, LPARAM lparam );
49 extern BOOL WINAPI Internal_EnumDateFormats( DATEFMT_ENUMPROCW proc, LCID lcid, DWORD flags, BOOL unicode,
50 BOOL ex, BOOL exex, LPARAM lparam );
51 extern BOOL WINAPI Internal_EnumLanguageGroupLocales( LANGGROUPLOCALE_ENUMPROCW proc, LGRPID id,
52 DWORD flags, LONG_PTR param, BOOL unicode );
53 extern BOOL WINAPI Internal_EnumSystemCodePages( CODEPAGE_ENUMPROCW proc, DWORD flags, BOOL unicode );
54 extern BOOL WINAPI Internal_EnumSystemLanguageGroups( LANGUAGEGROUP_ENUMPROCW proc, DWORD flags,
55 LONG_PTR param, BOOL unicode );
56 extern BOOL WINAPI Internal_EnumTimeFormats( TIMEFMT_ENUMPROCW proc, LCID lcid, DWORD flags,
57 BOOL unicode, BOOL ex, LPARAM lparam );
58 extern BOOL WINAPI Internal_EnumUILanguages( UILANGUAGE_ENUMPROCW proc, DWORD flags,
59 LONG_PTR param, BOOL unicode );
61 /***********************************************************************
62 * get_lcid_codepage
64 * Retrieve the ANSI codepage for a given locale.
66 static inline UINT get_lcid_codepage( LCID lcid )
68 UINT ret;
69 if (!GetLocaleInfoW( lcid, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER, (WCHAR *)&ret,
70 sizeof(ret)/sizeof(WCHAR) )) ret = 0;
71 return ret;
75 /******************************************************************************
76 * SetLocaleInfoA [KERNEL32.@]
78 * Set information about an aspect of a locale.
80 * PARAMS
81 * lcid [I] LCID of the locale
82 * lctype [I] LCTYPE_ flags from "winnls.h"
83 * data [I] Information to set
85 * RETURNS
86 * Success: TRUE. The information given will be returned by GetLocaleInfoA()
87 * whenever it is called without LOCALE_NOUSEROVERRIDE.
88 * Failure: FALSE. Use GetLastError() to determine the cause.
90 * NOTES
91 * - Values are only be set for the current user locale; the system locale
92 * settings cannot be changed.
93 * - Any settings changed by this call are lost when the locale is changed by
94 * the control panel (in Wine, this happens every time you change LANG).
95 * - The native implementation of this function does not check that lcid matches
96 * the current user locale, and simply sets the new values. Wine warns you in
97 * this case, but behaves the same.
99 BOOL WINAPI SetLocaleInfoA(LCID lcid, LCTYPE lctype, LPCSTR data)
101 UINT codepage = CP_ACP;
102 WCHAR *strW;
103 DWORD len;
104 BOOL ret;
106 if (!(lctype & LOCALE_USE_CP_ACP)) codepage = get_lcid_codepage( lcid );
108 if (!data)
110 SetLastError( ERROR_INVALID_PARAMETER );
111 return FALSE;
113 len = MultiByteToWideChar( codepage, 0, data, -1, NULL, 0 );
114 if (!(strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
116 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
117 return FALSE;
119 MultiByteToWideChar( codepage, 0, data, -1, strW, len );
120 ret = SetLocaleInfoW( lcid, lctype, strW );
121 HeapFree( GetProcessHeap(), 0, strW );
122 return ret;
126 /******************************************************************************
127 * SetCPGlobal (KERNEL32.@)
129 * Set the current Ansi code page Id for the system.
131 * PARAMS
132 * acp [I] code page ID to be the new ACP.
134 * RETURNS
135 * The previous ACP.
137 UINT WINAPI SetCPGlobal( UINT acp )
139 FIXME( "not supported\n" );
140 return GetACP();
144 /***********************************************************************
145 * GetCPInfoExA (KERNEL32.@)
147 * Get extended information about a code page.
149 * PARAMS
150 * codepage [I] Code page number
151 * dwFlags [I] Reserved, must to 0.
152 * cpinfo [O] Destination for code page information
154 * RETURNS
155 * Success: TRUE. cpinfo is updated with the information about codepage.
156 * Failure: FALSE, if codepage is invalid or cpinfo is NULL.
158 BOOL WINAPI GetCPInfoExA( UINT codepage, DWORD dwFlags, LPCPINFOEXA cpinfo )
160 CPINFOEXW cpinfoW;
162 if (!GetCPInfoExW( codepage, dwFlags, &cpinfoW ))
163 return FALSE;
165 /* the layout is the same except for CodePageName */
166 memcpy(cpinfo, &cpinfoW, sizeof(CPINFOEXA));
167 WideCharToMultiByte(CP_ACP, 0, cpinfoW.CodePageName, -1, cpinfo->CodePageName, sizeof(cpinfo->CodePageName), NULL, NULL);
168 return TRUE;
172 /*********************************************************************
173 * GetDaylightFlag (KERNEL32.@)
175 BOOL WINAPI GetDaylightFlag(void)
177 TIME_ZONE_INFORMATION tzinfo;
178 return GetTimeZoneInformation( &tzinfo) == TIME_ZONE_ID_DAYLIGHT;
182 /***********************************************************************
183 * EnumSystemCodePagesA (KERNEL32.@)
185 BOOL WINAPI EnumSystemCodePagesA( CODEPAGE_ENUMPROCA proc, DWORD flags )
187 return Internal_EnumSystemCodePages( (CODEPAGE_ENUMPROCW)proc, flags, FALSE );
191 /******************************************************************************
192 * GetStringTypeExA (KERNEL32.@)
194 * Get characteristics of the characters making up a string.
196 * PARAMS
197 * locale [I] Locale Id for the string
198 * type [I] CT_CTYPE1 = classification, CT_CTYPE2 = directionality, CT_CTYPE3 = typographic info
199 * src [I] String to analyse
200 * count [I] Length of src in chars, or -1 if src is NUL terminated
201 * chartype [O] Destination for the calculated characteristics
203 * RETURNS
204 * Success: TRUE. chartype is filled with the requested characteristics of each char
205 * in src.
206 * Failure: FALSE. Use GetLastError() to determine the cause.
208 BOOL WINAPI GetStringTypeExA( LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype )
210 return GetStringTypeA(locale, type, src, count, chartype);
213 /*************************************************************************
214 * FoldStringA (KERNEL32.@)
216 * Map characters in a string.
218 * PARAMS
219 * dwFlags [I] Flags controlling chars to map (MAP_ constants from "winnls.h")
220 * src [I] String to map
221 * srclen [I] Length of src, or -1 if src is NUL terminated
222 * dst [O] Destination for mapped string
223 * dstlen [I] Length of dst, or 0 to find the required length for the mapped string
225 * RETURNS
226 * Success: The length of the string written to dst, including the terminating NUL. If
227 * dstlen is 0, the value returned is the same, but nothing is written to dst,
228 * and dst may be NULL.
229 * Failure: 0. Use GetLastError() to determine the cause.
231 INT WINAPI FoldStringA(DWORD dwFlags, LPCSTR src, INT srclen,
232 LPSTR dst, INT dstlen)
234 INT ret = 0, srclenW = 0;
235 WCHAR *srcW = NULL, *dstW = NULL;
237 if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst)
239 SetLastError(ERROR_INVALID_PARAMETER);
240 return 0;
243 srclenW = MultiByteToWideChar(CP_ACP, 0, src, srclen, NULL, 0);
244 srcW = HeapAlloc(GetProcessHeap(), 0, srclenW * sizeof(WCHAR));
246 if (!srcW)
248 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
249 goto FoldStringA_exit;
252 MultiByteToWideChar(CP_ACP, 0, src, srclen, srcW, srclenW);
254 ret = FoldStringW(dwFlags, srcW, srclenW, NULL, 0);
255 if (ret && dstlen)
257 dstW = HeapAlloc(GetProcessHeap(), 0, ret * sizeof(WCHAR));
259 if (!dstW)
261 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
262 goto FoldStringA_exit;
265 ret = FoldStringW(dwFlags, srcW, srclenW, dstW, ret);
266 if (!WideCharToMultiByte(CP_ACP, 0, dstW, ret, dst, dstlen, NULL, NULL))
268 ret = 0;
269 SetLastError(ERROR_INSUFFICIENT_BUFFER);
273 HeapFree(GetProcessHeap(), 0, dstW);
275 FoldStringA_exit:
276 HeapFree(GetProcessHeap(), 0, srcW);
277 return ret;
280 /******************************************************************************
281 * EnumSystemLanguageGroupsA (KERNEL32.@)
283 BOOL WINAPI EnumSystemLanguageGroupsA( LANGUAGEGROUP_ENUMPROCA proc, DWORD flags, LONG_PTR param )
285 return Internal_EnumSystemLanguageGroups( (LANGUAGEGROUP_ENUMPROCW)proc, flags, param, FALSE );
288 /******************************************************************************
289 * EnumLanguageGroupLocalesA (KERNEL32.@)
291 BOOL WINAPI EnumLanguageGroupLocalesA( LANGGROUPLOCALE_ENUMPROCA proc, LGRPID id,
292 DWORD flags, LONG_PTR param )
294 return Internal_EnumLanguageGroupLocales( (LANGGROUPLOCALE_ENUMPROCW)proc, id, flags, param, FALSE );
297 /******************************************************************************
298 * EnumCalendarInfoA [KERNEL32.@]
300 BOOL WINAPI EnumCalendarInfoA( CALINFO_ENUMPROCA proc, LCID lcid, CALID id, CALTYPE type )
302 return Internal_EnumCalendarInfo( (CALINFO_ENUMPROCW)proc, lcid, id, type, FALSE, FALSE, FALSE, 0 );
305 /******************************************************************************
306 * EnumCalendarInfoExA [KERNEL32.@]
308 BOOL WINAPI EnumCalendarInfoExA( CALINFO_ENUMPROCEXA proc, LCID lcid, CALID id, CALTYPE type )
310 return Internal_EnumCalendarInfo( (CALINFO_ENUMPROCW)proc, lcid, id, type, FALSE, TRUE, FALSE, 0 );
313 /**************************************************************************
314 * EnumDateFormatsExA (KERNEL32.@)
316 * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle
317 * LOCALE_NOUSEROVERRIDE here as well?
319 BOOL WINAPI EnumDateFormatsExA(DATEFMT_ENUMPROCEXA proc, LCID lcid, DWORD flags)
321 return Internal_EnumDateFormats( (DATEFMT_ENUMPROCW)proc, lcid, flags, FALSE, TRUE, FALSE, 0 );
324 /**************************************************************************
325 * EnumDateFormatsA (KERNEL32.@)
327 * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle
328 * LOCALE_NOUSEROVERRIDE here as well?
330 BOOL WINAPI EnumDateFormatsA(DATEFMT_ENUMPROCA proc, LCID lcid, DWORD flags)
332 return Internal_EnumDateFormats( (DATEFMT_ENUMPROCW)proc, lcid, flags, FALSE, FALSE, FALSE, 0 );
335 /**************************************************************************
336 * EnumTimeFormatsA (KERNEL32.@)
338 * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle
339 * LOCALE_NOUSEROVERRIDE here as well?
341 BOOL WINAPI EnumTimeFormatsA( TIMEFMT_ENUMPROCA proc, LCID lcid, DWORD flags )
343 /* EnumTimeFormatsA doesn't support flags, EnumTimeFormatsW does. */
344 if (flags & ~LOCALE_USE_CP_ACP)
346 SetLastError(ERROR_INVALID_FLAGS);
347 return FALSE;
349 return Internal_EnumTimeFormats( (TIMEFMT_ENUMPROCW)proc, lcid, flags, FALSE, FALSE, 0 );
352 /******************************************************************************
353 * InvalidateNLSCache (KERNEL32.@)
355 * Invalidate the cache of NLS values.
357 * PARAMS
358 * None.
360 * RETURNS
361 * Success: TRUE.
362 * Failure: FALSE.
364 BOOL WINAPI InvalidateNLSCache(void)
366 FIXME("() stub\n");
367 return FALSE;
370 /******************************************************************************
371 * EnumUILanguagesA (KERNEL32.@)
373 BOOL WINAPI EnumUILanguagesA( UILANGUAGE_ENUMPROCA proc, DWORD flags, LONG_PTR param )
375 return Internal_EnumUILanguages( (UILANGUAGE_ENUMPROCW)proc, flags, param, FALSE );
379 /******************************************************************************
380 * GetGeoInfoA (KERNEL32.@)
382 INT WINAPI GetGeoInfoA(GEOID geoid, GEOTYPE geotype, LPSTR data, int data_len, LANGID lang)
384 WCHAR buffer[256];
386 TRACE("%ld %ld %p %d %d\n", geoid, geotype, data, data_len, lang);
388 if (!GetGeoInfoW( geoid, geotype, buffer, ARRAY_SIZE(buffer), lang )) return 0;
389 return WideCharToMultiByte( CP_ACP, 0, buffer, -1, data, data_len, NULL, NULL );