makefiles: Don't use standard libs for programs that specify -nodefaultlibs.
[wine/zf.git] / dlls / kernel32 / locale.c
blobac04e859460e69c2599de4d42465eba3ff619d42
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 "config.h"
25 #include "wine/port.h"
27 #include <assert.h>
28 #include <locale.h>
29 #include <string.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <ctype.h>
33 #include <stdlib.h>
35 #include "ntstatus.h"
36 #define WIN32_NO_STATUS
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winternl.h"
40 #include "wine/unicode.h"
41 #include "winnls.h"
42 #include "winerror.h"
43 #include "winver.h"
44 #include "kernel_private.h"
45 #include "wine/heap.h"
46 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(nls);
50 extern BOOL WINAPI Internal_EnumCalendarInfo( CALINFO_ENUMPROCW proc, LCID lcid, CALID id,
51 CALTYPE type, BOOL unicode, BOOL ex,
52 BOOL exex, LPARAM lparam );
53 extern BOOL WINAPI Internal_EnumDateFormats( DATEFMT_ENUMPROCW proc, LCID lcid, DWORD flags, BOOL unicode,
54 BOOL ex, BOOL exex, LPARAM lparam );
55 extern BOOL WINAPI Internal_EnumLanguageGroupLocales( LANGGROUPLOCALE_ENUMPROCW proc, LGRPID id,
56 DWORD flags, LONG_PTR param, BOOL unicode );
57 extern BOOL WINAPI Internal_EnumSystemCodePages( CODEPAGE_ENUMPROCW proc, DWORD flags, BOOL unicode );
58 extern BOOL WINAPI Internal_EnumSystemLanguageGroups( LANGUAGEGROUP_ENUMPROCW proc, DWORD flags,
59 LONG_PTR param, BOOL unicode );
60 extern BOOL WINAPI Internal_EnumTimeFormats( TIMEFMT_ENUMPROCW proc, LCID lcid, DWORD flags,
61 BOOL unicode, BOOL ex, LPARAM lparam );
62 extern BOOL WINAPI Internal_EnumUILanguages( UILANGUAGE_ENUMPROCW proc, DWORD flags,
63 LONG_PTR param, BOOL unicode );
65 static inline unsigned short get_table_entry( const unsigned short *table, WCHAR ch )
67 return table[table[table[ch >> 8] + ((ch >> 4) & 0x0f)] + (ch & 0xf)];
70 /***********************************************************************
71 * get_lcid_codepage
73 * Retrieve the ANSI codepage for a given locale.
75 static inline UINT get_lcid_codepage( LCID lcid )
77 UINT ret;
78 if (!GetLocaleInfoW( lcid, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER, (WCHAR *)&ret,
79 sizeof(ret)/sizeof(WCHAR) )) ret = 0;
80 return ret;
84 static BOOL get_dummy_preferred_ui_language( DWORD flags, ULONG *count, WCHAR *buffer, ULONG *size )
86 LCTYPE type;
87 int lsize;
89 FIXME("(0x%x %p %p %p) returning a dummy value (current locale)\n", flags, count, buffer, size);
91 if (flags & MUI_LANGUAGE_ID)
92 type = LOCALE_ILANGUAGE;
93 else
94 type = LOCALE_SNAME;
96 lsize = GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, type, NULL, 0);
97 if (!lsize)
99 /* keep last error from callee */
100 return FALSE;
102 lsize++;
103 if (!*size)
105 *size = lsize;
106 *count = 1;
107 return TRUE;
110 if (lsize > *size)
112 *size = lsize;
113 SetLastError(ERROR_INSUFFICIENT_BUFFER);
114 return FALSE;
117 if (!GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, type, buffer, *size))
119 /* keep last error from callee */
120 return FALSE;
123 buffer[lsize-1] = 0;
124 *size = lsize;
125 *count = 1;
126 TRACE("returned variable content: %d, \"%s\", %d\n", *count, debugstr_w(buffer), *size);
127 return TRUE;
131 /***********************************************************************
132 * GetProcessPreferredUILanguages (KERNEL32.@)
134 BOOL WINAPI GetProcessPreferredUILanguages( DWORD flags, ULONG *count, WCHAR *buf, ULONG *size )
136 FIXME( "%08x, %p, %p %p\n", flags, count, buf, size );
137 return get_dummy_preferred_ui_language( flags, count, buf, size );
140 /***********************************************************************
141 * GetSystemPreferredUILanguages (KERNEL32.@)
143 BOOL WINAPI GetSystemPreferredUILanguages(DWORD flags, ULONG* count, WCHAR* buffer, ULONG* size)
145 if (flags & ~(MUI_LANGUAGE_NAME | MUI_LANGUAGE_ID | MUI_MACHINE_LANGUAGE_SETTINGS))
147 SetLastError(ERROR_INVALID_PARAMETER);
148 return FALSE;
150 if ((flags & MUI_LANGUAGE_NAME) && (flags & MUI_LANGUAGE_ID))
152 SetLastError(ERROR_INVALID_PARAMETER);
153 return FALSE;
155 if (*size && !buffer)
157 SetLastError(ERROR_INVALID_PARAMETER);
158 return FALSE;
161 return get_dummy_preferred_ui_language( flags, count, buffer, size );
164 /***********************************************************************
165 * SetProcessPreferredUILanguages (KERNEL32.@)
167 BOOL WINAPI SetProcessPreferredUILanguages( DWORD flags, PCZZWSTR buffer, PULONG count )
169 FIXME("%u, %p, %p\n", flags, buffer, count );
170 return TRUE;
173 /***********************************************************************
174 * SetThreadPreferredUILanguages (KERNEL32.@)
176 BOOL WINAPI SetThreadPreferredUILanguages( DWORD flags, PCZZWSTR buffer, PULONG count )
178 FIXME( "%u, %p, %p\n", flags, buffer, count );
179 return TRUE;
182 /***********************************************************************
183 * GetThreadPreferredUILanguages (KERNEL32.@)
185 BOOL WINAPI GetThreadPreferredUILanguages( DWORD flags, ULONG *count, WCHAR *buf, ULONG *size )
187 FIXME( "%08x, %p, %p %p\n", flags, count, buf, size );
188 return get_dummy_preferred_ui_language( flags, count, buf, size );
191 /******************************************************************************
192 * GetUserPreferredUILanguages (KERNEL32.@)
194 BOOL WINAPI GetUserPreferredUILanguages( DWORD flags, ULONG *count, WCHAR *buffer, ULONG *size )
196 TRACE( "%u %p %p %p\n", flags, count, buffer, size );
198 if (flags & ~(MUI_LANGUAGE_NAME | MUI_LANGUAGE_ID))
200 SetLastError(ERROR_INVALID_PARAMETER);
201 return FALSE;
203 if ((flags & MUI_LANGUAGE_NAME) && (flags & MUI_LANGUAGE_ID))
205 SetLastError(ERROR_INVALID_PARAMETER);
206 return FALSE;
208 if (*size && !buffer)
210 SetLastError(ERROR_INVALID_PARAMETER);
211 return FALSE;
214 return get_dummy_preferred_ui_language( flags, count, buffer, size );
217 /******************************************************************************
218 * SetLocaleInfoA [KERNEL32.@]
220 * Set information about an aspect of a locale.
222 * PARAMS
223 * lcid [I] LCID of the locale
224 * lctype [I] LCTYPE_ flags from "winnls.h"
225 * data [I] Information to set
227 * RETURNS
228 * Success: TRUE. The information given will be returned by GetLocaleInfoA()
229 * whenever it is called without LOCALE_NOUSEROVERRIDE.
230 * Failure: FALSE. Use GetLastError() to determine the cause.
232 * NOTES
233 * - Values are only be set for the current user locale; the system locale
234 * settings cannot be changed.
235 * - Any settings changed by this call are lost when the locale is changed by
236 * the control panel (in Wine, this happens every time you change LANG).
237 * - The native implementation of this function does not check that lcid matches
238 * the current user locale, and simply sets the new values. Wine warns you in
239 * this case, but behaves the same.
241 BOOL WINAPI SetLocaleInfoA(LCID lcid, LCTYPE lctype, LPCSTR data)
243 UINT codepage = CP_ACP;
244 WCHAR *strW;
245 DWORD len;
246 BOOL ret;
248 if (!(lctype & LOCALE_USE_CP_ACP)) codepage = get_lcid_codepage( lcid );
250 if (!data)
252 SetLastError( ERROR_INVALID_PARAMETER );
253 return FALSE;
255 len = MultiByteToWideChar( codepage, 0, data, -1, NULL, 0 );
256 if (!(strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
258 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
259 return FALSE;
261 MultiByteToWideChar( codepage, 0, data, -1, strW, len );
262 ret = SetLocaleInfoW( lcid, lctype, strW );
263 HeapFree( GetProcessHeap(), 0, strW );
264 return ret;
268 /******************************************************************************
269 * SetCPGlobal (KERNEL32.@)
271 * Set the current Ansi code page Id for the system.
273 * PARAMS
274 * acp [I] code page ID to be the new ACP.
276 * RETURNS
277 * The previous ACP.
279 UINT WINAPI SetCPGlobal( UINT acp )
281 FIXME( "not supported\n" );
282 return GetACP();
286 /***********************************************************************
287 * GetCPInfoExA (KERNEL32.@)
289 * Get extended information about a code page.
291 * PARAMS
292 * codepage [I] Code page number
293 * dwFlags [I] Reserved, must to 0.
294 * cpinfo [O] Destination for code page information
296 * RETURNS
297 * Success: TRUE. cpinfo is updated with the information about codepage.
298 * Failure: FALSE, if codepage is invalid or cpinfo is NULL.
300 BOOL WINAPI GetCPInfoExA( UINT codepage, DWORD dwFlags, LPCPINFOEXA cpinfo )
302 CPINFOEXW cpinfoW;
304 if (!GetCPInfoExW( codepage, dwFlags, &cpinfoW ))
305 return FALSE;
307 /* the layout is the same except for CodePageName */
308 memcpy(cpinfo, &cpinfoW, sizeof(CPINFOEXA));
309 WideCharToMultiByte(CP_ACP, 0, cpinfoW.CodePageName, -1, cpinfo->CodePageName, sizeof(cpinfo->CodePageName), NULL, NULL);
310 return TRUE;
313 /***********************************************************************
314 * EnumSystemCodePagesA (KERNEL32.@)
316 BOOL WINAPI EnumSystemCodePagesA( CODEPAGE_ENUMPROCA proc, DWORD flags )
318 return Internal_EnumSystemCodePages( (CODEPAGE_ENUMPROCW)proc, flags, FALSE );
322 /******************************************************************************
323 * GetStringTypeExA (KERNEL32.@)
325 * Get characteristics of the characters making up a string.
327 * PARAMS
328 * locale [I] Locale Id for the string
329 * type [I] CT_CTYPE1 = classification, CT_CTYPE2 = directionality, CT_CTYPE3 = typographic info
330 * src [I] String to analyse
331 * count [I] Length of src in chars, or -1 if src is NUL terminated
332 * chartype [O] Destination for the calculated characteristics
334 * RETURNS
335 * Success: TRUE. chartype is filled with the requested characteristics of each char
336 * in src.
337 * Failure: FALSE. Use GetLastError() to determine the cause.
339 BOOL WINAPI GetStringTypeExA( LCID locale, DWORD type, LPCSTR src, INT count, LPWORD chartype )
341 return GetStringTypeA(locale, type, src, count, chartype);
344 /*************************************************************************
345 * FoldStringA (KERNEL32.@)
347 * Map characters in a string.
349 * PARAMS
350 * dwFlags [I] Flags controlling chars to map (MAP_ constants from "winnls.h")
351 * src [I] String to map
352 * srclen [I] Length of src, or -1 if src is NUL terminated
353 * dst [O] Destination for mapped string
354 * dstlen [I] Length of dst, or 0 to find the required length for the mapped string
356 * RETURNS
357 * Success: The length of the string written to dst, including the terminating NUL. If
358 * dstlen is 0, the value returned is the same, but nothing is written to dst,
359 * and dst may be NULL.
360 * Failure: 0. Use GetLastError() to determine the cause.
362 INT WINAPI FoldStringA(DWORD dwFlags, LPCSTR src, INT srclen,
363 LPSTR dst, INT dstlen)
365 INT ret = 0, srclenW = 0;
366 WCHAR *srcW = NULL, *dstW = NULL;
368 if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst)
370 SetLastError(ERROR_INVALID_PARAMETER);
371 return 0;
374 srclenW = MultiByteToWideChar(CP_ACP, 0, src, srclen, NULL, 0);
375 srcW = HeapAlloc(GetProcessHeap(), 0, srclenW * sizeof(WCHAR));
377 if (!srcW)
379 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
380 goto FoldStringA_exit;
383 MultiByteToWideChar(CP_ACP, 0, src, srclen, srcW, srclenW);
385 ret = FoldStringW(dwFlags, srcW, srclenW, NULL, 0);
386 if (ret && dstlen)
388 dstW = HeapAlloc(GetProcessHeap(), 0, ret * sizeof(WCHAR));
390 if (!dstW)
392 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
393 goto FoldStringA_exit;
396 ret = FoldStringW(dwFlags, srcW, srclenW, dstW, ret);
397 if (!WideCharToMultiByte(CP_ACP, 0, dstW, ret, dst, dstlen, NULL, NULL))
399 ret = 0;
400 SetLastError(ERROR_INSUFFICIENT_BUFFER);
404 HeapFree(GetProcessHeap(), 0, dstW);
406 FoldStringA_exit:
407 HeapFree(GetProcessHeap(), 0, srcW);
408 return ret;
411 /******************************************************************************
412 * EnumSystemLanguageGroupsA (KERNEL32.@)
414 BOOL WINAPI EnumSystemLanguageGroupsA( LANGUAGEGROUP_ENUMPROCA proc, DWORD flags, LONG_PTR param )
416 return Internal_EnumSystemLanguageGroups( (LANGUAGEGROUP_ENUMPROCW)proc, flags, param, FALSE );
419 /******************************************************************************
420 * EnumLanguageGroupLocalesA (KERNEL32.@)
422 BOOL WINAPI EnumLanguageGroupLocalesA( LANGGROUPLOCALE_ENUMPROCA proc, LGRPID id,
423 DWORD flags, LONG_PTR param )
425 return Internal_EnumLanguageGroupLocales( (LANGGROUPLOCALE_ENUMPROCW)proc, id, flags, param, FALSE );
428 /******************************************************************************
429 * EnumCalendarInfoA [KERNEL32.@]
431 BOOL WINAPI EnumCalendarInfoA( CALINFO_ENUMPROCA proc, LCID lcid, CALID id, CALTYPE type )
433 return Internal_EnumCalendarInfo( (CALINFO_ENUMPROCW)proc, lcid, id, type, FALSE, FALSE, FALSE, 0 );
436 /******************************************************************************
437 * EnumCalendarInfoExA [KERNEL32.@]
439 BOOL WINAPI EnumCalendarInfoExA( CALINFO_ENUMPROCEXA proc, LCID lcid, CALID id, CALTYPE type )
441 return Internal_EnumCalendarInfo( (CALINFO_ENUMPROCW)proc, lcid, id, type, FALSE, TRUE, FALSE, 0 );
444 /**************************************************************************
445 * EnumDateFormatsExA (KERNEL32.@)
447 * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle
448 * LOCALE_NOUSEROVERRIDE here as well?
450 BOOL WINAPI EnumDateFormatsExA(DATEFMT_ENUMPROCEXA proc, LCID lcid, DWORD flags)
452 return Internal_EnumDateFormats( (DATEFMT_ENUMPROCW)proc, lcid, flags, FALSE, TRUE, FALSE, 0 );
455 /**************************************************************************
456 * EnumDateFormatsA (KERNEL32.@)
458 * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle
459 * LOCALE_NOUSEROVERRIDE here as well?
461 BOOL WINAPI EnumDateFormatsA(DATEFMT_ENUMPROCA proc, LCID lcid, DWORD flags)
463 return Internal_EnumDateFormats( (DATEFMT_ENUMPROCW)proc, lcid, flags, FALSE, FALSE, FALSE, 0 );
466 /**************************************************************************
467 * EnumTimeFormatsA (KERNEL32.@)
469 * FIXME: MSDN mentions only LOCALE_USE_CP_ACP, should we handle
470 * LOCALE_NOUSEROVERRIDE here as well?
472 BOOL WINAPI EnumTimeFormatsA( TIMEFMT_ENUMPROCA proc, LCID lcid, DWORD flags )
474 /* EnumTimeFormatsA doesn't support flags, EnumTimeFormatsW does. */
475 if (flags & ~LOCALE_USE_CP_ACP)
477 SetLastError(ERROR_INVALID_FLAGS);
478 return FALSE;
480 return Internal_EnumTimeFormats( (TIMEFMT_ENUMPROCW)proc, lcid, flags, FALSE, FALSE, 0 );
483 /******************************************************************************
484 * InvalidateNLSCache (KERNEL32.@)
486 * Invalidate the cache of NLS values.
488 * PARAMS
489 * None.
491 * RETURNS
492 * Success: TRUE.
493 * Failure: FALSE.
495 BOOL WINAPI InvalidateNLSCache(void)
497 FIXME("() stub\n");
498 return FALSE;
501 /******************************************************************************
502 * EnumUILanguagesA (KERNEL32.@)
504 BOOL WINAPI EnumUILanguagesA( UILANGUAGE_ENUMPROCA proc, DWORD flags, LONG_PTR param )
506 return Internal_EnumUILanguages( (UILANGUAGE_ENUMPROCW)proc, flags, param, FALSE );
510 /******************************************************************************
511 * GetGeoInfoA (KERNEL32.@)
513 INT WINAPI GetGeoInfoA(GEOID geoid, GEOTYPE geotype, LPSTR data, int data_len, LANGID lang)
515 WCHAR *buffW;
516 INT len;
518 TRACE("%d %d %p %d %d\n", geoid, geotype, data, data_len, lang);
520 len = GetGeoInfoW(geoid, geotype, NULL, 0, lang);
521 if (!len)
522 return 0;
524 buffW = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
525 if (!buffW)
526 return 0;
528 GetGeoInfoW(geoid, geotype, buffW, len, lang);
529 len = WideCharToMultiByte(CP_ACP, 0, buffW, -1, NULL, 0, NULL, NULL);
530 if (!data || !data_len) {
531 HeapFree(GetProcessHeap(), 0, buffW);
532 return len;
535 len = WideCharToMultiByte(CP_ACP, 0, buffW, -1, data, data_len, NULL, NULL);
536 HeapFree(GetProcessHeap(), 0, buffW);
538 if (data_len < len)
539 SetLastError(ERROR_INSUFFICIENT_BUFFER);
540 return data_len < len ? 0 : len;
544 /******************************************************************************
545 * GetFileMUIPath (KERNEL32.@)
548 BOOL WINAPI GetFileMUIPath(DWORD flags, PCWSTR filepath, PWSTR language, PULONG languagelen,
549 PWSTR muipath, PULONG muipathlen, PULONGLONG enumerator)
551 FIXME("stub: 0x%x, %s, %s, %p, %p, %p, %p\n", flags, debugstr_w(filepath),
552 debugstr_w(language), languagelen, muipath, muipathlen, enumerator);
554 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
556 return FALSE;
559 /******************************************************************************
560 * GetFileMUIInfo (KERNEL32.@)
563 BOOL WINAPI GetFileMUIInfo(DWORD flags, PCWSTR path, FILEMUIINFO *info, DWORD *size)
565 FIXME("stub: %u, %s, %p, %p\n", flags, debugstr_w(path), info, size);
567 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
568 return FALSE;