kernel32: Move EnumCalendarInfo functions to kernelbase.
[wine.git] / dlls / kernelbase / locale.c
blob367618c48a419e738422939ffb2d4abf5294131a
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
8 * Copyright 2003 Jon Griffiths
9 * Copyright 2005 Dmitry Timoshkov
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include <stdarg.h>
27 #include <stdlib.h>
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winreg.h"
34 #include "winnls.h"
35 #include "winuser.h"
36 #include "winternl.h"
37 #include "kernelbase.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(nls);
43 static const WCHAR codepages_key[] =
44 { 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
45 '\\','C','o','n','t','r','o','l','\\','N','l','s','\\','C','o','d','e','P','a','g','e',0};
46 static const WCHAR language_groups_key[] =
47 { 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
48 '\\','C','o','n','t','r','o','l','\\','N','l','s',
49 '\\','L','a','n','g','u','a','g','e',' ','G','r','o','u','p','s',0 };
50 static const WCHAR locales_key[] =
51 { 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t',
52 '\\','C','o','n','t','r','o','l','\\','N','l','s','\\','L','o','c','a','l','e',0};
53 static const WCHAR altsort_key[] = {'A','l','t','e','r','n','a','t','e',' ','S','o','r','t','s',0};
56 /* Note: the Internal_ functions are not documented. The number of parameters
57 * should be correct, but their exact meaning may not.
60 /******************************************************************************
61 * Internal_EnumCalendarInfo (kernelbase.@)
63 BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumCalendarInfo( CALINFO_ENUMPROCW proc, LCID lcid, CALID id,
64 CALTYPE type, BOOL unicode, BOOL ex,
65 BOOL exex, LPARAM lparam )
67 WCHAR buffer[256];
68 DWORD optional;
69 INT ret;
71 if (!proc)
73 SetLastError( ERROR_INVALID_PARAMETER );
74 return FALSE;
77 if (id == ENUM_ALL_CALENDARS)
79 if (!GetLocaleInfoW( lcid, LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER,
80 (WCHAR *)&id, sizeof(id) / sizeof(WCHAR) )) return FALSE;
81 if (!GetLocaleInfoW( lcid, LOCALE_IOPTIONALCALENDAR | LOCALE_RETURN_NUMBER,
82 (WCHAR *)&optional, sizeof(optional) / sizeof(WCHAR) )) optional = 0;
85 for (;;)
87 if (type & CAL_RETURN_NUMBER)
88 ret = GetCalendarInfoW( lcid, id, type, NULL, 0, (LPDWORD)buffer );
89 else if (unicode)
90 ret = GetCalendarInfoW( lcid, id, type, buffer, ARRAY_SIZE(buffer), NULL );
91 else
93 WCHAR bufW[256];
94 ret = GetCalendarInfoW( lcid, id, type, bufW, ARRAY_SIZE(bufW), NULL );
95 if (ret) WideCharToMultiByte( CP_ACP, 0, bufW, -1, (char *)buffer, sizeof(buffer), NULL, NULL );
98 if (ret)
100 if (exex) ret = ((CALINFO_ENUMPROCEXEX)proc)( buffer, id, NULL, lparam );
101 else if (ex) ret = ((CALINFO_ENUMPROCEXW)proc)( buffer, id );
102 else ret = proc( buffer );
104 if (!ret) break;
105 if (!optional) break;
106 id = optional;
108 return TRUE;
112 /**************************************************************************
113 * Internal_EnumDateFormats (kernelbase.@)
115 BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumDateFormats( DATEFMT_ENUMPROCW proc, LCID lcid, DWORD flags,
116 BOOL unicode, BOOL ex, BOOL exex, LPARAM lparam )
118 WCHAR buffer[256];
119 LCTYPE lctype;
120 CALID cal_id;
121 INT ret;
123 if (!proc)
125 SetLastError( ERROR_INVALID_PARAMETER );
126 return FALSE;
128 if (!GetLocaleInfoW( lcid, LOCALE_ICALENDARTYPE|LOCALE_RETURN_NUMBER,
129 (LPWSTR)&cal_id, sizeof(cal_id)/sizeof(WCHAR) ))
130 return FALSE;
132 switch (flags & ~LOCALE_USE_CP_ACP)
134 case 0:
135 case DATE_SHORTDATE:
136 lctype = LOCALE_SSHORTDATE;
137 break;
138 case DATE_LONGDATE:
139 lctype = LOCALE_SLONGDATE;
140 break;
141 case DATE_YEARMONTH:
142 lctype = LOCALE_SYEARMONTH;
143 break;
144 default:
145 FIXME( "unknown date format 0x%08x\n", flags );
146 SetLastError( ERROR_INVALID_PARAMETER );
147 return FALSE;
150 lctype |= flags & LOCALE_USE_CP_ACP;
151 if (unicode)
152 ret = GetLocaleInfoW( lcid, lctype, buffer, ARRAY_SIZE(buffer) );
153 else
154 ret = GetLocaleInfoA( lcid, lctype, (char *)buffer, sizeof(buffer) );
156 if (ret)
158 if (exex) ((DATEFMT_ENUMPROCEXEX)proc)( buffer, cal_id, lparam );
159 else if (ex) ((DATEFMT_ENUMPROCEXW)proc)( buffer, cal_id );
160 else proc( buffer );
162 return TRUE;
166 /******************************************************************************
167 * Internal_EnumLanguageGroupLocales (kernelbase.@)
169 BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumLanguageGroupLocales( LANGGROUPLOCALE_ENUMPROCW proc, LGRPID id,
170 DWORD flags, LONG_PTR param, BOOL unicode )
172 WCHAR name[10], value[10];
173 DWORD name_len, value_len, type, index = 0, alt = 0;
174 HKEY key, altkey;
175 LCID lcid;
177 if (!proc || id < LGRPID_WESTERN_EUROPE || id > LGRPID_ARMENIAN)
179 SetLastError( ERROR_INVALID_PARAMETER );
180 return FALSE;
183 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, locales_key, 0, KEY_READ, &key )) return FALSE;
184 if (RegOpenKeyExW( key, altsort_key, 0, KEY_READ, &altkey )) altkey = 0;
186 for (;;)
188 name_len = ARRAY_SIZE(name);
189 value_len = sizeof(value);
190 if (RegEnumValueW( alt ? altkey : key, index++, name, &name_len, NULL,
191 &type, (BYTE *)value, &value_len ))
193 if (alt++) break;
194 index = 0;
195 continue;
197 if (type != REG_SZ) continue;
198 if (id != wcstoul( value, NULL, 16 )) continue;
199 lcid = wcstoul( name, NULL, 16 );
200 if (!unicode)
202 char nameA[10];
203 WideCharToMultiByte( CP_ACP, 0, name, -1, nameA, sizeof(nameA), NULL, NULL );
204 if (!((LANGGROUPLOCALE_ENUMPROCA)proc)( id, lcid, nameA, param )) break;
206 else if (!proc( id, lcid, name, param )) break;
208 RegCloseKey( altkey );
209 RegCloseKey( key );
210 return TRUE;
214 /***********************************************************************
215 * Internal_EnumSystemCodePages (kernelbase.@)
217 BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumSystemCodePages( CODEPAGE_ENUMPROCW proc, DWORD flags,
218 BOOL unicode )
220 WCHAR name[10];
221 DWORD name_len, type, index = 0;
222 HKEY key;
224 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, codepages_key, 0, KEY_READ, &key )) return FALSE;
226 for (;;)
228 name_len = ARRAY_SIZE(name);
229 if (RegEnumValueW( key, index++, name, &name_len, NULL, &type, NULL, NULL )) break;
230 if (type != REG_SZ) continue;
231 if (!wcstoul( name, NULL, 10 )) continue;
232 if (!unicode)
234 char nameA[10];
235 WideCharToMultiByte( CP_ACP, 0, name, -1, nameA, sizeof(nameA), NULL, NULL );
236 if (!((CODEPAGE_ENUMPROCA)proc)( nameA )) break;
238 else if (!proc( name )) break;
240 RegCloseKey( key );
241 return TRUE;
245 /******************************************************************************
246 * Internal_EnumSystemLanguageGroups (kernelbase.@)
248 BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumSystemLanguageGroups( LANGUAGEGROUP_ENUMPROCW proc,
249 DWORD flags, LONG_PTR param, BOOL unicode )
251 WCHAR name[10], value[10], descr[80];
252 DWORD name_len, value_len, type, index = 0;
253 HKEY key;
254 LGRPID id;
256 if (!proc)
258 SetLastError( ERROR_INVALID_PARAMETER );
259 return FALSE;
262 switch (flags)
264 case 0:
265 flags = LGRPID_INSTALLED;
266 break;
267 case LGRPID_INSTALLED:
268 case LGRPID_SUPPORTED:
269 break;
270 default:
271 SetLastError( ERROR_INVALID_FLAGS );
272 return FALSE;
275 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, language_groups_key, 0, KEY_READ, &key )) return FALSE;
277 for (;;)
279 name_len = ARRAY_SIZE(name);
280 value_len = sizeof(value);
281 if (RegEnumValueW( key, index++, name, &name_len, NULL, &type, (BYTE *)value, &value_len )) break;
282 if (type != REG_SZ) continue;
284 id = wcstoul( name, NULL, 16 );
286 if (!(flags & LGRPID_SUPPORTED) && !wcstoul( value, NULL, 10 )) continue;
287 if (!LoadStringW( kernel32_handle, 0x2000 + id, descr, ARRAY_SIZE(descr) )) descr[0] = 0;
288 TRACE( "%p: %u %s %s %x %lx\n", proc, id, debugstr_w(name), debugstr_w(descr), flags, param );
289 if (!unicode)
291 char nameA[10], descrA[80];
292 WideCharToMultiByte( CP_ACP, 0, name, -1, nameA, sizeof(nameA), NULL, NULL );
293 WideCharToMultiByte( CP_ACP, 0, descr, -1, descrA, sizeof(descrA), NULL, NULL );
294 if (!((LANGUAGEGROUP_ENUMPROCA)proc)( id, nameA, descrA, flags, param )) break;
296 else if (!proc( id, name, descr, flags, param )) break;
298 RegCloseKey( key );
299 return TRUE;
303 /**************************************************************************
304 * Internal_EnumTimeFormats (kernelbase.@)
306 BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumTimeFormats( TIMEFMT_ENUMPROCW proc, LCID lcid, DWORD flags,
307 BOOL unicode, BOOL ex, LPARAM lparam )
309 WCHAR buffer[256];
310 LCTYPE lctype;
311 INT ret;
313 if (!proc)
315 SetLastError( ERROR_INVALID_PARAMETER );
316 return FALSE;
318 switch (flags & ~LOCALE_USE_CP_ACP)
320 case 0:
321 lctype = LOCALE_STIMEFORMAT;
322 break;
323 case TIME_NOSECONDS:
324 lctype = LOCALE_SSHORTTIME;
325 break;
326 default:
327 FIXME( "Unknown time format %x\n", flags );
328 SetLastError( ERROR_INVALID_PARAMETER );
329 return FALSE;
332 lctype |= flags & LOCALE_USE_CP_ACP;
333 if (unicode)
334 ret = GetLocaleInfoW( lcid, lctype, buffer, ARRAY_SIZE(buffer) );
335 else
336 ret = GetLocaleInfoA( lcid, lctype, (char *)buffer, sizeof(buffer) );
338 if (ret)
340 if (ex) ((TIMEFMT_ENUMPROCEX)proc)( buffer, lparam );
341 else proc( buffer );
343 return TRUE;
347 /******************************************************************************
348 * Internal_EnumUILanguages (kernelbase.@)
350 BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumUILanguages( UILANGUAGE_ENUMPROCW proc, DWORD flags,
351 LONG_PTR param, BOOL unicode )
353 WCHAR name[10];
354 DWORD name_len, type, index = 0;
355 HKEY key;
357 if (!proc)
359 SetLastError( ERROR_INVALID_PARAMETER );
360 return FALSE;
362 if (flags & ~MUI_LANGUAGE_ID)
364 SetLastError( ERROR_INVALID_FLAGS );
365 return FALSE;
368 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, locales_key, 0, KEY_READ, &key )) return FALSE;
370 for (;;)
372 name_len = ARRAY_SIZE(name);
373 if (RegEnumValueW( key, index++, name, &name_len, NULL, &type, NULL, NULL )) break;
374 if (type != REG_SZ) continue;
375 if (!wcstoul( name, NULL, 16 )) continue;
376 if (!unicode)
378 char nameA[10];
379 WideCharToMultiByte( CP_ACP, 0, name, -1, nameA, sizeof(nameA), NULL, NULL );
380 if (!((UILANGUAGE_ENUMPROCA)proc)( nameA, param )) break;
382 else if (!proc( name, param )) break;
384 RegCloseKey( key );
385 return TRUE;
389 /******************************************************************************
390 * CompareStringOrdinal (kernelbase.@)
392 INT WINAPI DECLSPEC_HOTPATCH CompareStringOrdinal( const WCHAR *str1, INT len1,
393 const WCHAR *str2, INT len2, BOOL ignore_case )
395 int ret;
397 if (!str1 || !str2)
399 SetLastError( ERROR_INVALID_PARAMETER );
400 return 0;
402 if (len1 < 0) len1 = lstrlenW( str1 );
403 if (len2 < 0) len2 = lstrlenW( str2 );
405 ret = RtlCompareUnicodeStrings( str1, len1, str2, len2, ignore_case );
406 if (ret < 0) return CSTR_LESS_THAN;
407 if (ret > 0) return CSTR_GREATER_THAN;
408 return CSTR_EQUAL;
412 /******************************************************************************
413 * EnumCalendarInfoW (kernelbase.@)
415 BOOL WINAPI DECLSPEC_HOTPATCH EnumCalendarInfoW( CALINFO_ENUMPROCW proc, LCID lcid,
416 CALID id, CALTYPE type )
418 return Internal_EnumCalendarInfo( proc, lcid, id, type, TRUE, FALSE, FALSE, 0 );
422 /******************************************************************************
423 * EnumCalendarInfoExW (kernelbase.@)
425 BOOL WINAPI DECLSPEC_HOTPATCH EnumCalendarInfoExW( CALINFO_ENUMPROCEXW proc, LCID lcid,
426 CALID id, CALTYPE type )
428 return Internal_EnumCalendarInfo( (CALINFO_ENUMPROCW)proc, lcid, id, type, TRUE, TRUE, FALSE, 0 );
431 /******************************************************************************
432 * EnumCalendarInfoExEx (kernelbase.@)
434 BOOL WINAPI DECLSPEC_HOTPATCH EnumCalendarInfoExEx( CALINFO_ENUMPROCEXEX proc, LPCWSTR locale, CALID id,
435 LPCWSTR reserved, CALTYPE type, LPARAM lparam )
437 LCID lcid = LocaleNameToLCID( locale, 0 );
438 return Internal_EnumCalendarInfo( (CALINFO_ENUMPROCW)proc, lcid, id, type, TRUE, TRUE, TRUE, lparam );
442 /**************************************************************************
443 * EnumDateFormatsW (kernelbase.@)
445 BOOL WINAPI DECLSPEC_HOTPATCH EnumDateFormatsW( DATEFMT_ENUMPROCW proc, LCID lcid, DWORD flags )
447 return Internal_EnumDateFormats( proc, lcid, flags, TRUE, FALSE, FALSE, 0 );
451 /**************************************************************************
452 * EnumDateFormatsExW (kernelbase.@)
454 BOOL WINAPI DECLSPEC_HOTPATCH EnumDateFormatsExW( DATEFMT_ENUMPROCEXW proc, LCID lcid, DWORD flags )
456 return Internal_EnumDateFormats( (DATEFMT_ENUMPROCW)proc, lcid, flags, TRUE, TRUE, FALSE, 0 );
460 /**************************************************************************
461 * EnumDateFormatsExEx (kernelbase.@)
463 BOOL WINAPI DECLSPEC_HOTPATCH EnumDateFormatsExEx( DATEFMT_ENUMPROCEXEX proc, const WCHAR *locale,
464 DWORD flags, LPARAM lparam )
466 LCID lcid = LocaleNameToLCID( locale, 0 );
467 return Internal_EnumDateFormats( (DATEFMT_ENUMPROCW)proc, lcid, flags, TRUE, TRUE, TRUE, lparam );
471 /******************************************************************************
472 * EnumLanguageGroupLocalesW (kernelbase.@)
474 BOOL WINAPI DECLSPEC_HOTPATCH EnumLanguageGroupLocalesW( LANGGROUPLOCALE_ENUMPROCW proc, LGRPID id,
475 DWORD flags, LONG_PTR param )
477 return Internal_EnumLanguageGroupLocales( proc, id, flags, param, TRUE );
481 /******************************************************************************
482 * EnumUILanguagesW (kernelbase.@)
484 BOOL WINAPI DECLSPEC_HOTPATCH EnumUILanguagesW( UILANGUAGE_ENUMPROCW proc, DWORD flags, LONG_PTR param )
486 return Internal_EnumUILanguages( proc, flags, param, TRUE );
490 /***********************************************************************
491 * EnumSystemCodePagesW (kernelbase.@)
493 BOOL WINAPI DECLSPEC_HOTPATCH EnumSystemCodePagesW( CODEPAGE_ENUMPROCW proc, DWORD flags )
495 return Internal_EnumSystemCodePages( proc, flags, TRUE );
499 /******************************************************************************
500 * EnumSystemLanguageGroupsW (kernelbase.@)
502 BOOL WINAPI DECLSPEC_HOTPATCH EnumSystemLanguageGroupsW( LANGUAGEGROUP_ENUMPROCW proc,
503 DWORD flags, LONG_PTR param )
505 return Internal_EnumSystemLanguageGroups( proc, flags, param, TRUE );
509 /******************************************************************************
510 * EnumSystemLocalesA (kernelbase.@)
512 BOOL WINAPI DECLSPEC_HOTPATCH EnumSystemLocalesA( LOCALE_ENUMPROCA proc, DWORD flags )
514 char name[10];
515 DWORD name_len, type, index = 0;
516 HKEY key;
518 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, locales_key, 0, KEY_READ, &key )) return FALSE;
520 for (;;)
522 name_len = ARRAY_SIZE(name);
523 if (RegEnumValueA( key, index++, name, &name_len, NULL, &type, NULL, NULL )) break;
524 if (type != REG_SZ) continue;
525 if (!strtoul( name, NULL, 16 )) continue;
526 if (!proc( name )) break;
528 RegCloseKey( key );
529 return TRUE;
533 /******************************************************************************
534 * EnumSystemLocalesW (kernelbase.@)
536 BOOL WINAPI DECLSPEC_HOTPATCH EnumSystemLocalesW( LOCALE_ENUMPROCW proc, DWORD flags )
538 WCHAR name[10];
539 DWORD name_len, type, index = 0;
540 HKEY key;
542 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, locales_key, 0, KEY_READ, &key )) return FALSE;
544 for (;;)
546 name_len = ARRAY_SIZE(name);
547 if (RegEnumValueW( key, index++, name, &name_len, NULL, &type, NULL, NULL )) break;
548 if (type != REG_SZ) continue;
549 if (!wcstoul( name, NULL, 16 )) continue;
550 if (!proc( name )) break;
552 RegCloseKey( key );
553 return TRUE;
557 /******************************************************************************
558 * EnumSystemLocalesEx (kernelbase.@)
560 BOOL WINAPI DECLSPEC_HOTPATCH EnumSystemLocalesEx( LOCALE_ENUMPROCEX proc, DWORD wanted_flags,
561 LPARAM param, void *reserved )
563 WCHAR buffer[256], name[10];
564 DWORD name_len, type, neutral, flags, index = 0, alt = 0;
565 HKEY key, altkey;
566 LCID lcid;
568 if (reserved)
570 SetLastError( ERROR_INVALID_PARAMETER );
571 return FALSE;
574 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, locales_key, 0, KEY_READ, &key )) return FALSE;
575 if (RegOpenKeyExW( key, altsort_key, 0, KEY_READ, &altkey )) altkey = 0;
577 for (;;)
579 name_len = ARRAY_SIZE(name);
580 if (RegEnumValueW( alt ? altkey : key, index++, name, &name_len, NULL, &type, NULL, NULL ))
582 if (alt++) break;
583 index = 0;
584 continue;
586 if (type != REG_SZ) continue;
587 if (!(lcid = wcstoul( name, NULL, 16 ))) continue;
589 GetLocaleInfoW( lcid, LOCALE_SNAME | LOCALE_NOUSEROVERRIDE, buffer, ARRAY_SIZE( buffer ));
590 if (!GetLocaleInfoW( lcid, LOCALE_INEUTRAL | LOCALE_NOUSEROVERRIDE | LOCALE_RETURN_NUMBER,
591 (LPWSTR)&neutral, sizeof(neutral) / sizeof(WCHAR) ))
592 neutral = 0;
594 if (alt)
595 flags = LOCALE_ALTERNATE_SORTS;
596 else
597 flags = LOCALE_WINDOWS | (neutral ? LOCALE_NEUTRALDATA : LOCALE_SPECIFICDATA);
599 if (wanted_flags && !(flags & wanted_flags)) continue;
600 if (!proc( buffer, flags, param )) break;
602 RegCloseKey( altkey );
603 RegCloseKey( key );
604 return TRUE;
608 /**************************************************************************
609 * EnumTimeFormatsW (kernelbase.@)
611 BOOL WINAPI DECLSPEC_HOTPATCH EnumTimeFormatsW( TIMEFMT_ENUMPROCW proc, LCID lcid, DWORD flags )
613 return Internal_EnumTimeFormats( proc, lcid, flags, TRUE, FALSE, 0 );
617 /**************************************************************************
618 * EnumTimeFormatsEx (kernelbase.@)
620 BOOL WINAPI DECLSPEC_HOTPATCH EnumTimeFormatsEx( TIMEFMT_ENUMPROCEX proc, const WCHAR *locale,
621 DWORD flags, LPARAM lparam )
623 LCID lcid = LocaleNameToLCID( locale, 0 );
624 return Internal_EnumTimeFormats( (TIMEFMT_ENUMPROCW)proc, lcid, flags, TRUE, TRUE, lparam );
628 /******************************************************************************
629 * FindStringOrdinal (kernelbase.@)
631 INT WINAPI DECLSPEC_HOTPATCH FindStringOrdinal( DWORD flag, const WCHAR *src, INT src_size,
632 const WCHAR *val, INT val_size, BOOL ignore_case )
634 INT offset, inc, count;
636 TRACE( "%#x %s %d %s %d %d\n", flag, wine_dbgstr_w(src), src_size,
637 wine_dbgstr_w(val), val_size, ignore_case );
639 if (!src || !val)
641 SetLastError( ERROR_INVALID_PARAMETER );
642 return -1;
645 if (flag != FIND_FROMSTART && flag != FIND_FROMEND && flag != FIND_STARTSWITH && flag != FIND_ENDSWITH)
647 SetLastError( ERROR_INVALID_FLAGS );
648 return -1;
651 if (src_size == -1) src_size = lstrlenW( src );
652 if (val_size == -1) val_size = lstrlenW( val );
654 SetLastError( ERROR_SUCCESS );
655 src_size -= val_size;
656 if (src_size < 0) return -1;
658 count = flag & (FIND_FROMSTART | FIND_FROMEND) ? src_size + 1 : 1;
659 offset = flag & (FIND_FROMSTART | FIND_STARTSWITH) ? 0 : src_size;
660 inc = flag & (FIND_FROMSTART | FIND_STARTSWITH) ? 1 : -1;
661 while (count--)
663 if (CompareStringOrdinal( src + offset, val_size, val, val_size, ignore_case ) == CSTR_EQUAL)
664 return offset;
665 offset += inc;
667 return -1;
671 /******************************************************************************
672 * IsValidLanguageGroup (kernelbase.@)
674 BOOL WINAPI DECLSPEC_HOTPATCH IsValidLanguageGroup( LGRPID id, DWORD flags )
676 static const WCHAR format[] = { '%','x',0 };
677 WCHAR name[10], value[10];
678 DWORD type, value_len = sizeof(value);
679 BOOL ret = FALSE;
680 HKEY key;
682 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, language_groups_key, 0, KEY_READ, &key )) return FALSE;
684 swprintf( name, ARRAY_SIZE(name), format, id );
685 if (!RegQueryValueExW( key, name, NULL, &type, (BYTE *)value, &value_len ) && type == REG_SZ)
686 ret = (flags & LGRPID_SUPPORTED) || wcstoul( value, NULL, 10 );
688 RegCloseKey( key );
689 return ret;
693 /***********************************************************************
694 * LCIDToLocaleName (kernelbase.@)
696 INT WINAPI DECLSPEC_HOTPATCH LCIDToLocaleName( LCID lcid, LPWSTR name, INT count, DWORD flags )
698 static int once;
699 if (flags && !once++) FIXME( "unsupported flags %x\n", flags );
701 return GetLocaleInfoW( lcid, LOCALE_SNAME | LOCALE_NOUSEROVERRIDE, name, count );
705 /***********************************************************************
706 * GetSystemDefaultLCID (kernelbase.@)
708 LCID WINAPI DECLSPEC_HOTPATCH GetSystemDefaultLCID(void)
710 LCID lcid;
711 NtQueryDefaultLocale( FALSE, &lcid );
712 return lcid;
716 /***********************************************************************
717 * GetSystemDefaultLangID (kernelbase.@)
719 LANGID WINAPI DECLSPEC_HOTPATCH GetSystemDefaultLangID(void)
721 return LANGIDFROMLCID( GetSystemDefaultLCID() );
725 /***********************************************************************
726 * GetSystemDefaultLocaleName (kernelbase.@)
728 INT WINAPI DECLSPEC_HOTPATCH GetSystemDefaultLocaleName( LPWSTR name, INT len )
730 return LCIDToLocaleName( GetSystemDefaultLCID(), name, len, 0 );
734 /***********************************************************************
735 * GetSystemDefaultUILanguage (kernelbase.@)
737 LANGID WINAPI DECLSPEC_HOTPATCH GetSystemDefaultUILanguage(void)
739 LANGID lang;
740 NtQueryInstallUILanguage( &lang );
741 return lang;
745 /***********************************************************************
746 * GetUserDefaultLCID (kernelbase.@)
748 LCID WINAPI DECLSPEC_HOTPATCH GetUserDefaultLCID(void)
750 LCID lcid;
751 NtQueryDefaultLocale( TRUE, &lcid );
752 return lcid;
756 /***********************************************************************
757 * GetUserDefaultLangID (kernelbase.@)
759 LANGID WINAPI DECLSPEC_HOTPATCH GetUserDefaultLangID(void)
761 return LANGIDFROMLCID( GetUserDefaultLCID() );
765 /***********************************************************************
766 * GetUserDefaultLocaleName (kernelbase.@)
768 INT WINAPI DECLSPEC_HOTPATCH GetUserDefaultLocaleName( LPWSTR name, INT len )
770 return LCIDToLocaleName( GetUserDefaultLCID(), name, len, 0 );
774 /***********************************************************************
775 * GetUserDefaultUILanguage (kernelbase.@)
777 LANGID WINAPI DECLSPEC_HOTPATCH GetUserDefaultUILanguage(void)
779 LANGID lang;
780 NtQueryDefaultUILanguage( &lang );
781 return lang;
785 /******************************************************************************
786 * ResolveLocaleName (kernelbase.@)
788 INT WINAPI DECLSPEC_HOTPATCH ResolveLocaleName( LPCWSTR name, LPWSTR buffer, INT len )
790 FIXME( "stub: %s, %p, %d\n", wine_dbgstr_w(name), buffer, len );
792 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
793 return 0;
797 /***********************************************************************
798 * VerLanguageNameA (kernelbase.@)
800 DWORD WINAPI DECLSPEC_HOTPATCH VerLanguageNameA( DWORD lang, LPSTR buffer, DWORD size )
802 return GetLocaleInfoA( MAKELCID( lang, SORT_DEFAULT ), LOCALE_SENGLANGUAGE, buffer, size );
806 /***********************************************************************
807 * VerLanguageNameW (kernelbase.@)
809 DWORD WINAPI DECLSPEC_HOTPATCH VerLanguageNameW( DWORD lang, LPWSTR buffer, DWORD size )
811 return GetLocaleInfoW( MAKELCID( lang, SORT_DEFAULT ), LOCALE_SENGLANGUAGE, buffer, size );