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
25 #include "wine/port.h"
36 #define WIN32_NO_STATUS
40 #include "wine/unicode.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 /***********************************************************************
73 * Retrieve the ANSI codepage for a given locale.
75 static inline UINT
get_lcid_codepage( LCID lcid
)
78 if (!GetLocaleInfoW( lcid
, LOCALE_IDEFAULTANSICODEPAGE
|LOCALE_RETURN_NUMBER
, (WCHAR
*)&ret
,
79 sizeof(ret
)/sizeof(WCHAR
) )) ret
= 0;
84 static BOOL
get_dummy_preferred_ui_language( DWORD flags
, ULONG
*count
, WCHAR
*buffer
, ULONG
*size
)
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
;
96 lsize
= GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, type
, NULL
, 0);
99 /* keep last error from callee */
113 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
117 if (!GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT
, type
, buffer
, *size
))
119 /* keep last error from callee */
126 TRACE("returned variable content: %d, \"%s\", %d\n", *count
, debugstr_w(buffer
), *size
);
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
);
150 if ((flags
& MUI_LANGUAGE_NAME
) && (flags
& MUI_LANGUAGE_ID
))
152 SetLastError(ERROR_INVALID_PARAMETER
);
155 if (*size
&& !buffer
)
157 SetLastError(ERROR_INVALID_PARAMETER
);
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
);
173 /***********************************************************************
174 * SetThreadPreferredUILanguages (KERNEL32.@)
176 BOOL WINAPI
SetThreadPreferredUILanguages( DWORD flags
, PCZZWSTR buffer
, PULONG count
)
178 FIXME( "%u, %p, %p\n", flags
, buffer
, count
);
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
);
203 if ((flags
& MUI_LANGUAGE_NAME
) && (flags
& MUI_LANGUAGE_ID
))
205 SetLastError(ERROR_INVALID_PARAMETER
);
208 if (*size
&& !buffer
)
210 SetLastError(ERROR_INVALID_PARAMETER
);
214 return get_dummy_preferred_ui_language( flags
, count
, buffer
, size
);
217 /******************************************************************************
218 * SetLocaleInfoA [KERNEL32.@]
220 * Set information about an aspect of a locale.
223 * lcid [I] LCID of the locale
224 * lctype [I] LCTYPE_ flags from "winnls.h"
225 * data [I] Information to set
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.
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
;
248 if (!(lctype
& LOCALE_USE_CP_ACP
)) codepage
= get_lcid_codepage( lcid
);
252 SetLastError( ERROR_INVALID_PARAMETER
);
255 len
= MultiByteToWideChar( codepage
, 0, data
, -1, NULL
, 0 );
256 if (!(strW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
258 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
261 MultiByteToWideChar( codepage
, 0, data
, -1, strW
, len
);
262 ret
= SetLocaleInfoW( lcid
, lctype
, strW
);
263 HeapFree( GetProcessHeap(), 0, strW
);
268 /******************************************************************************
269 * SetCPGlobal (KERNEL32.@)
271 * Set the current Ansi code page Id for the system.
274 * acp [I] code page ID to be the new ACP.
279 UINT WINAPI
SetCPGlobal( UINT acp
)
281 FIXME( "not supported\n" );
286 /***********************************************************************
287 * GetCPInfoExA (KERNEL32.@)
289 * Get extended information about a code page.
292 * codepage [I] Code page number
293 * dwFlags [I] Reserved, must to 0.
294 * cpinfo [O] Destination for code page information
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
)
304 if (!GetCPInfoExW( codepage
, dwFlags
, &cpinfoW
))
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
);
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.
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
335 * Success: TRUE. chartype is filled with the requested characteristics of each char
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.
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
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
);
374 srclenW
= MultiByteToWideChar(CP_ACP
, 0, src
, srclen
, NULL
, 0);
375 srcW
= HeapAlloc(GetProcessHeap(), 0, srclenW
* sizeof(WCHAR
));
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);
388 dstW
= HeapAlloc(GetProcessHeap(), 0, ret
* sizeof(WCHAR
));
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
))
400 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
404 HeapFree(GetProcessHeap(), 0, dstW
);
407 HeapFree(GetProcessHeap(), 0, srcW
);
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
);
480 return Internal_EnumTimeFormats( (TIMEFMT_ENUMPROCW
)proc
, lcid
, flags
, FALSE
, FALSE
, 0 );
483 /******************************************************************************
484 * InvalidateNLSCache (KERNEL32.@)
486 * Invalidate the cache of NLS values.
495 BOOL WINAPI
InvalidateNLSCache(void)
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
)
518 TRACE("%d %d %p %d %d\n", geoid
, geotype
, data
, data_len
, lang
);
520 len
= GetGeoInfoW(geoid
, geotype
, NULL
, 0, lang
);
524 buffW
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
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
);
535 len
= WideCharToMultiByte(CP_ACP
, 0, buffW
, -1, data
, data_len
, NULL
, NULL
);
536 HeapFree(GetProcessHeap(), 0, buffW
);
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
);
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
);