Emanuele Aliberti <ea@reactos.com>
[reactos.git] / reactos / lib / kernel32 / misc / lang.c
1 /* $Id: lang.c,v 1.22 2004/08/26 16:03:09 hbirr Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT : ReactOS user mode libraries
5 * MODULE : kernel32.dll
6 * FILE : reactos/lib/kernel32/misc/lang.c
7 * AUTHOR : ???
8 */
9
10 #include <k32.h>
11
12 #define NDEBUG
13 #include "../include/debug.h"
14
15 /* FIXME: these are included in winnls.h, however including this file causes alot of
16 conflicting type errors. */
17
18 #define LOCALE_SYEARMONTH 0x1006
19 #define LOCALE_IPAPERSIZE 0x100A
20 #define LOCALE_RETURN_NUMBER 0x20000000
21 #define LOCALE_USE_CP_ACP 0x40000000
22 #define LOCALE_LOCALEINFOFLAGSMASK (LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP|LOCALE_RETURN_NUMBER)
23
24 //static LCID SystemLocale = MAKELCID(LANG_ENGLISH, SORT_DEFAULT);
25
26 //#define _OLE2NLS_IN_BUILD_
27
28
29 /******************************************************************************
30 * @implemented
31 * RIPPED FROM WINE's dlls\kernel\locale.c rev 1.42
32 *
33 * ConvertDefaultLocale (KERNEL32.@)
34 *
35 * Convert a default locale identifier into a real identifier.
36 *
37 * PARAMS
38 * lcid [I] LCID identifier of the locale to convert
39 *
40 * RETURNS
41 * lcid unchanged, if not a default locale or its sublanguage is
42 * not SUBLANG_NEUTRAL.
43 * GetSystemDefaultLCID(), if lcid == LOCALE_SYSTEM_DEFAULT.
44 * GetUserDefaultLCID(), if lcid == LOCALE_USER_DEFAULT or LOCALE_NEUTRAL.
45 * Otherwise, lcid with sublanguage changed to SUBLANG_DEFAULT.
46 */
47 LCID WINAPI ConvertDefaultLocale( LCID lcid )
48 {
49 LANGID langid;
50
51 switch (lcid)
52 {
53 case LOCALE_SYSTEM_DEFAULT:
54 lcid = GetSystemDefaultLCID();
55 break;
56 case LOCALE_USER_DEFAULT:
57 case LOCALE_NEUTRAL:
58 lcid = GetUserDefaultLCID();
59 break;
60 default:
61 /* Replace SUBLANG_NEUTRAL with SUBLANG_DEFAULT */
62 langid = LANGIDFROMLCID(lcid);
63 if (SUBLANGID(langid) == SUBLANG_NEUTRAL)
64 {
65 langid = MAKELANGID(PRIMARYLANGID(langid), SUBLANG_DEFAULT);
66 lcid = MAKELCID(langid, SORTIDFROMLCID(lcid));
67 }
68 }
69 return lcid;
70 }
71
72
73
74
75
76 /*
77 * @unimplemented
78 */
79 BOOL
80 STDCALL
81 EnumCalendarInfoExA(
82 CALINFO_ENUMPROCEXA lpCalInfoEnumProcEx,
83 LCID Locale,
84 CALID Calendar,
85 CALTYPE CalType)
86 {
87 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
88 return 0;
89 }
90
91
92 /*
93 * @unimplemented
94 */
95 BOOL
96 STDCALL
97 EnumCalendarInfoExW(
98 CALINFO_ENUMPROCEXW lpCalInfoEnumProcEx,
99 LCID Locale,
100 CALID Calendar,
101 CALTYPE CalType)
102 {
103 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
104 return 0;
105 }
106
107
108
109
110 /*
111 * @unimplemented
112 */
113 BOOL
114 STDCALL
115 EnumDateFormatsExA(
116 DATEFMT_ENUMPROCEXA lpDateFmtEnumProcEx,
117 LCID Locale,
118 DWORD dwFlags)
119 {
120 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
121 return 0;
122 }
123
124
125 /*
126 * @unimplemented
127 */
128 BOOL
129 STDCALL
130 EnumDateFormatsExW(
131 DATEFMT_ENUMPROCEXW lpDateFmtEnumProcEx,
132 LCID Locale,
133 DWORD dwFlags)
134 {
135 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
136 return 0;
137 }
138
139
140 /*
141 * @unimplemented
142 */
143 BOOL
144 STDCALL
145 EnumLanguageGroupLocalesA(
146 LANGGROUPLOCALE_ENUMPROCA lpLangGroupLocaleEnumProc,
147 LGRPID LanguageGroup,
148 DWORD dwFlags,
149 LONG_PTR lParam)
150 {
151 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
152 return 0;
153 }
154
155
156 /*
157 * @unimplemented
158 */
159 BOOL
160 STDCALL
161 EnumLanguageGroupLocalesW(
162 LANGGROUPLOCALE_ENUMPROCW lpLangGroupLocaleEnumProc,
163 LGRPID LanguageGroup,
164 DWORD dwFlags,
165 LONG_PTR lParam)
166 {
167 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
168 return 0;
169 }
170
171
172 /*
173 * @unimplemented
174 */
175 BOOL
176 STDCALL
177 EnumSystemCodePagesW (
178 CODEPAGE_ENUMPROCW lpCodePageEnumProc,
179 DWORD dwFlags
180 )
181 {
182 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
183 return FALSE;
184 }
185
186
187 /*
188 * @unimplemented
189 */
190 BOOL
191 STDCALL
192 EnumSystemCodePagesA (
193 CODEPAGE_ENUMPROCA lpCodePageEnumProc,
194 DWORD dwFlags
195 )
196 {
197 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
198 return FALSE;
199 }
200
201
202 /*
203 * @unimplemented
204 */
205 BOOL
206 STDCALL
207 EnumSystemGeoID(
208 GEOCLASS GeoClass,
209 GEOID ParentGeoId,
210 GEO_ENUMPROC lpGeoEnumProc)
211 {
212 if(!lpGeoEnumProc)
213 {
214 SetLastError(ERROR_INVALID_PARAMETER);
215 return FALSE;
216 }
217
218 switch(GeoClass)
219 {
220 case GEOCLASS_NATION:
221 /*RtlEnterCriticalSection(&DllLock);
222
223 FIXME - Get GEO IDs calling Csr
224
225 RtlLeaveCriticalSection(&DllLock);*/
226
227 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
228 break;
229
230 default:
231 SetLastError(ERROR_INVALID_FLAGS);
232 return FALSE;
233 }
234
235 return FALSE;
236 }
237
238
239 /*
240 * @unimplemented
241 */
242 BOOL
243 STDCALL
244 EnumSystemLanguageGroupsA(
245 LANGUAGEGROUP_ENUMPROCA lpLanguageGroupEnumProc,
246 DWORD dwFlags,
247 LONG_PTR lParam)
248 {
249 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
250 return 0;
251 }
252
253
254 #ifndef _OLE2NLS_IN_BUILD_
255
256 /*
257 * @unimplemented
258 */
259 BOOL
260 STDCALL
261 EnumSystemLocalesW (
262 LOCALE_ENUMPROCW lpLocaleEnumProc,
263 DWORD dwFlags
264 )
265 {
266 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
267 return FALSE;
268 }
269
270
271 /*
272 * @unimplemented
273 */
274 BOOL
275 STDCALL
276 EnumSystemLocalesA (
277 LOCALE_ENUMPROCA lpLocaleEnumProc,
278 DWORD dwFlags
279 )
280 {
281 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
282 return FALSE;
283 }
284
285 #endif
286
287
288
289
290 /*
291 * @unimplemented
292 */
293 BOOL
294 STDCALL
295 EnumUILanguagesA(
296 UILANGUAGE_ENUMPROCA lpUILanguageEnumProc,
297 DWORD dwFlags,
298 LONG_PTR lParam)
299 {
300 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
301 return 0;
302 }
303
304
305 /*
306 * @unimplemented
307 */
308 BOOL
309 STDCALL
310 EnumUILanguagesW(
311 UILANGUAGE_ENUMPROCW lpUILanguageEnumProc,
312 DWORD dwFlags,
313 LONG_PTR lParam)
314 {
315 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
316 return 0;
317 }
318
319 /*
320 * @unimplemented
321 */
322 int
323 STDCALL
324 GetCalendarInfoA(
325 LCID Locale,
326 CALID Calendar,
327 CALTYPE CalType,
328 LPSTR lpCalData,
329 int cchData,
330 LPDWORD lpValue)
331 {
332 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
333 return 0;
334 }
335
336
337 /*
338 * @unimplemented
339 */
340 int
341 STDCALL
342 GetCalendarInfoW(
343 LCID Locale,
344 CALID Calendar,
345 CALTYPE CalType,
346 LPWSTR lpCalData,
347 int cchData,
348 LPDWORD lpValue)
349 {
350 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
351 return 0;
352 }
353
354
355 #ifndef _OLE2NLS_IN_BUILD_
356
357 /*
358 * @unimplemented
359 */
360 BOOL
361 STDCALL
362 GetCPInfo (
363 UINT CodePage,
364 LPCPINFO CodePageInfo
365 )
366 {
367 unsigned i;
368
369 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
370
371 CodePageInfo->MaxCharSize = 1;
372 CodePageInfo->DefaultChar[0] = '?';
373 for (i = 1; i < MAX_DEFAULTCHAR; i++)
374 {
375 CodePageInfo->DefaultChar[i] = 0;
376 }
377 for (i = 0; i < MAX_LEADBYTES; i++)
378 {
379 CodePageInfo->LeadByte[i] = 0;
380 }
381
382 return TRUE;
383 }
384
385 #endif
386
387
388 /*
389 * @unimplemented
390 */
391 BOOL
392 STDCALL
393 GetCPInfoExW(
394 UINT CodePage,
395 DWORD dwFlags,
396 LPCPINFOEXW lpCPInfoEx)
397 {
398 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
399 return 0;
400 }
401
402
403 /*
404 * @unimplemented
405 */
406 BOOL
407 STDCALL
408 GetCPInfoExA(
409 UINT CodePage,
410 DWORD dwFlags,
411 LPCPINFOEXA lpCPInfoEx)
412 {
413 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
414 return 0;
415 }
416
417
418 /*
419 * @unimplemented
420 */
421 int
422 STDCALL
423 GetGeoInfoW(
424 GEOID Location,
425 GEOTYPE GeoType,
426 LPWSTR lpGeoData,
427 int cchData,
428 LANGID LangId)
429 {
430 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
431 return 0;
432 }
433
434
435 /*
436 * @unimplemented
437 */
438 int
439 STDCALL
440 GetGeoInfoA(
441 GEOID Location,
442 GEOTYPE GeoType,
443 LPSTR lpGeoData,
444 int cchData,
445 LANGID LangId)
446 {
447 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
448 return 0;
449 }
450
451 const WCHAR *RosGetLocaleValueName( DWORD lctype )
452 {
453 switch (lctype & ~LOCALE_LOCALEINFOFLAGSMASK)
454 {
455 /* These values are used by SetLocaleInfo and GetLocaleInfo, and
456 * the values are stored in the registry, confirmed under Windows.
457 */
458 case LOCALE_ICALENDARTYPE: return L"iCalendarType";
459 case LOCALE_ICURRDIGITS: return L"iCurrDigits";
460 case LOCALE_ICURRENCY: return L"iCurrency";
461 case LOCALE_IDIGITS: return L"iDigits";
462 case LOCALE_IFIRSTDAYOFWEEK: return L"iFirstDayOfWeek";
463 case LOCALE_IFIRSTWEEKOFYEAR: return L"iFirstWeekOfYear";
464 case LOCALE_ILZERO: return L"iLZero";
465 case LOCALE_IMEASURE: return L"iMeasure";
466 case LOCALE_INEGCURR: return L"iNegCurr";
467 case LOCALE_INEGNUMBER: return L"iNegNumber";
468 case LOCALE_IPAPERSIZE: return L"iPaperSize";
469 case LOCALE_ITIME: return L"iTime";
470 case LOCALE_S1159: return L"s1159";
471 case LOCALE_S2359: return L"s2359";
472 case LOCALE_SCURRENCY: return L"sCurrency";
473 case LOCALE_SDATE: return L"sDate";
474 case LOCALE_SDECIMAL: return L"sDecimal";
475 case LOCALE_SGROUPING: return L"sGrouping";
476 case LOCALE_SLIST: return L"sList";
477 case LOCALE_SLONGDATE: return L"sLongDate";
478 case LOCALE_SMONDECIMALSEP: return L"sMonDecimalSep";
479 case LOCALE_SMONGROUPING: return L"sMonGrouping";
480 case LOCALE_SMONTHOUSANDSEP: return L"sMonThousandSep";
481 case LOCALE_SNEGATIVESIGN: return L"sNegativeSign";
482 case LOCALE_SPOSITIVESIGN: return L"sPositiveSign";
483 case LOCALE_SSHORTDATE: return L"sShortDate";
484 case LOCALE_STHOUSAND: return L"sThousand";
485 case LOCALE_STIME: return L"sTime";
486 case LOCALE_STIMEFORMAT: return L"sTimeFormat";
487 case LOCALE_SYEARMONTH: return L"sYearMonth";
488
489 /* The following are not listed under MSDN as supported,
490 * but seem to be used and also stored in the registry.
491 */
492 case LOCALE_ICOUNTRY: return L"iCountry";
493 case LOCALE_IDATE: return L"iDate";
494 case LOCALE_ILDATE: return L"iLDate";
495 case LOCALE_ITLZERO: return L"iTLZero";
496 case LOCALE_SCOUNTRY: return L"sCountry";
497 case LOCALE_SLANGUAGE: return L"sLanguage";
498 }
499 return NULL;
500 }
501
502 HKEY RosCreateRegistryKey(void)
503 {
504 OBJECT_ATTRIBUTES objAttr;
505 UNICODE_STRING nameW;
506 HANDLE hKey;
507
508 if (RtlOpenCurrentUser( KEY_ALL_ACCESS, &hKey ) != STATUS_SUCCESS) return 0;
509
510 objAttr.Length = sizeof(objAttr);
511 objAttr.RootDirectory = hKey;
512 objAttr.ObjectName = &nameW;
513 objAttr.Attributes = 0;
514 objAttr.SecurityDescriptor = NULL;
515 objAttr.SecurityQualityOfService = NULL;
516 RtlInitUnicodeString( &nameW, L"Control Panel\\International");
517
518 if (NtCreateKey( &hKey, KEY_ALL_ACCESS, &objAttr, 0, NULL, 0, NULL ) != STATUS_SUCCESS) hKey = 0;
519 NtClose( objAttr.RootDirectory );
520 return hKey;
521 }
522
523 INT RosGetRegistryLocaleInfo( LPCWSTR lpValue, LPWSTR lpBuffer, INT nLen )
524 {
525 DWORD dwSize;
526 HKEY hKey;
527 INT nRet;
528 NTSTATUS ntStatus;
529 UNICODE_STRING usNameW;
530 KEY_VALUE_PARTIAL_INFORMATION *kvpiInfo;
531 const int nInfoSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
532
533 if (!(hKey = RosCreateRegistryKey())) return -1;
534
535 RtlInitUnicodeString( &usNameW, lpValue );
536 dwSize = nInfoSize + nLen * sizeof(WCHAR);
537
538 if (!(kvpiInfo = HeapAlloc( GetProcessHeap(), 0, dwSize )))
539 {
540 NtClose( hKey );
541 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
542 return 0;
543 }
544
545 ntStatus = NtQueryValueKey( hKey, &usNameW, KeyValuePartialInformation, kvpiInfo, dwSize, &dwSize );
546 if (ntStatus == STATUS_BUFFER_OVERFLOW && !lpBuffer) ntStatus = 0;
547
548 if (!ntStatus)
549 {
550 nRet = (dwSize - nInfoSize) / sizeof(WCHAR);
551
552 if (!nRet || ((WCHAR *)kvpiInfo->Data)[nRet - 1])
553 {
554 if (nRet < nLen || !lpBuffer) nRet++;
555 else
556 {
557 SetLastError( ERROR_INSUFFICIENT_BUFFER );
558 nRet = 0;
559 }
560 }
561 if (nRet && lpBuffer)
562 {
563 memcpy( lpBuffer, kvpiInfo->Data, (nRet - 1) * sizeof(WCHAR) );
564 lpBuffer[nRet - 1] = 0;
565 }
566 }
567 else
568 {
569 if (ntStatus == STATUS_OBJECT_NAME_NOT_FOUND) nRet = -1;
570 else
571 {
572 SetLastError( RtlNtStatusToDosError(ntStatus) );
573 nRet = 0;
574 }
575 }
576 NtClose( hKey );
577 HeapFree( GetProcessHeap(), 0, kvpiInfo );
578 return nRet;
579 }
580
581 /*
582 * @implemented
583 */
584 int
585 STDCALL
586 GetLocaleInfoW (
587 LCID Locale,
588 LCTYPE LCType,
589 LPWSTR lpLCData,
590 int cchData
591 )
592 {
593 LANGID liLangID;
594 HRSRC hRsrc;
595 HGLOBAL hMem;
596 HMODULE hModule;
597 INT nRet;
598 UINT uiFlags;
599 const WCHAR *ch;
600 int i;
601
602 if (cchData < 0 || (cchData && !lpLCData))
603 {
604 SetLastError( ERROR_INVALID_PARAMETER );
605 return 0;
606 }
607 if (!cchData) lpLCData = NULL;
608
609 if (Locale == LOCALE_NEUTRAL || Locale == LOCALE_SYSTEM_DEFAULT) Locale = GetSystemDefaultLCID();
610 else if (Locale == LOCALE_USER_DEFAULT) Locale = GetUserDefaultLCID();
611
612 uiFlags = LCType & LOCALE_LOCALEINFOFLAGSMASK;
613 LCType &= ~LOCALE_LOCALEINFOFLAGSMASK;
614
615 if (!(uiFlags & LOCALE_NOUSEROVERRIDE) && Locale == GetUserDefaultLCID())
616 {
617 const WCHAR *value = RosGetLocaleValueName(LCType);
618
619 if (value && ((nRet = RosGetRegistryLocaleInfo( value, lpLCData, cchData )) != -1)) return nRet;
620 }
621
622 liLangID = LANGIDFROMLCID( Locale );
623
624 if (SUBLANGID(liLangID) == SUBLANG_NEUTRAL)
625 liLangID = MAKELANGID(PRIMARYLANGID(liLangID), SUBLANG_DEFAULT);
626
627 hModule = GetModuleHandleW( L"kernel32.dll" );
628 if (!(hRsrc = FindResourceExW( hModule, (LPWSTR)RT_STRING, (LPCWSTR)((LCType >> 4) + 1), liLangID )))
629 {
630 SetLastError( ERROR_INVALID_FLAGS );
631 return 0;
632 }
633 if (!(hMem = LoadResource( hModule, hRsrc )))
634 return 0;
635
636 ch = LockResource( hMem );
637 for (i = 0; i < (LCType & 0x0f); i++) ch += *ch + 1;
638
639 if (uiFlags & LOCALE_RETURN_NUMBER) nRet = sizeof(UINT) / sizeof(WCHAR);
640 else nRet = (LCType == LOCALE_FONTSIGNATURE) ? *ch : *ch + 1;
641
642 if (!lpLCData) return nRet;
643
644 if (nRet > cchData)
645 {
646 SetLastError( ERROR_INSUFFICIENT_BUFFER );
647 return 0;
648 }
649
650 if (uiFlags & LOCALE_RETURN_NUMBER)
651 {
652 UINT uiNum;
653 WCHAR *chEnd, *chTmp = HeapAlloc( GetProcessHeap(), 0, (*ch + 1) * sizeof(WCHAR) );
654
655 if (!chTmp)
656 return 0;
657
658 memcpy( chTmp, ch + 1, *ch * sizeof(WCHAR) );
659 chTmp[*ch] = L'\0';
660 uiNum = wcstol( chTmp, &chEnd, 10 );
661
662 if (!*chEnd)
663 memcpy( lpLCData, &uiNum, sizeof(uiNum) );
664 else
665 {
666 SetLastError( ERROR_INVALID_FLAGS );
667 nRet = 0;
668 }
669 HeapFree( GetProcessHeap(), 0, chTmp );
670 }
671 else
672 {
673 memcpy( lpLCData, ch + 1, *ch * sizeof(WCHAR) );
674 if (LCType != LOCALE_FONTSIGNATURE) lpLCData[nRet-1] = 0;
675 }
676 return nRet;
677 }
678
679
680
681 /***********************************************************************
682 * get_lcid_codepage
683 *
684 * Retrieve the ANSI codepage for a given locale.
685 */
686 inline static UINT get_lcid_codepage( LCID lcid )
687 {
688 UINT ret;
689 if (!GetLocaleInfoW( lcid, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER, (WCHAR *)&ret,
690 sizeof(ret)/sizeof(WCHAR) )) ret = 0;
691 return ret;
692 }
693
694
695
696 /*
697 * @implemented
698 *
699 * Get information about an aspect of a locale.
700 *
701 * PARAMS
702 * lcid [I] LCID of the locale
703 * lctype [I] LCTYPE_ flags from "winnls.h"
704 * buffer [O] Destination for the information
705 * len [I] Length of buffer in characters
706 *
707 * RETURNS
708 * Success: The size of the data requested. If buffer is non-NULL, it is filled
709 * with the information.
710 * Failure: 0. Use GetLastError() to determine the cause.
711 *
712 * NOTES
713 * - LOCALE_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT
714 * - The string returned is NUL terminated, except for LOCALE_FONTSIGNATURE,
715 * which is a bit string.
716 */
717 INT STDCALL GetLocaleInfoA( LCID lcid, LCTYPE lctype, LPSTR buffer, INT len )
718 {
719 WCHAR *bufferW;
720 INT lenW, ret;
721
722 if (len < 0 || (len && !buffer))
723 {
724 SetLastError( ERROR_INVALID_PARAMETER );
725 return 0;
726 }
727 if (!len) buffer = NULL;
728
729 if (!(lenW = GetLocaleInfoW( lcid, lctype, NULL, 0 ))) return 0;
730
731 if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) )))
732 {
733 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
734 return 0;
735 }
736 if ((ret = GetLocaleInfoW( lcid, lctype, bufferW, lenW )))
737 {
738 if ((lctype & LOCALE_RETURN_NUMBER) ||
739 ((lctype & ~LOCALE_LOCALEINFOFLAGSMASK) == LOCALE_FONTSIGNATURE))
740 {
741 /* it's not an ASCII string, just bytes */
742 ret *= sizeof(WCHAR);
743 if (buffer)
744 {
745 if (ret <= len) memcpy( buffer, bufferW, ret );
746 else
747 {
748 SetLastError( ERROR_INSUFFICIENT_BUFFER );
749 ret = 0;
750 }
751 }
752 }
753 else
754 {
755 UINT codepage = CP_ACP;
756 if (!(lctype & LOCALE_USE_CP_ACP)) codepage = get_lcid_codepage( lcid );
757 ret = WideCharToMultiByte( codepage, 0, bufferW, ret, buffer, len, NULL, NULL );
758 }
759 }
760 HeapFree( GetProcessHeap(), 0, bufferW );
761 return ret;
762 }
763
764
765 #ifndef _OLE2NLS_IN_BUILD_
766
767 /*
768 * @implemented
769 */
770 LANGID
771 STDCALL
772 GetSystemDefaultLangID (VOID)
773 {
774 return LANGIDFROMLCID(GetSystemDefaultLCID());
775 }
776
777
778 /*
779 * @implemented
780 */
781 LCID
782 STDCALL
783 GetSystemDefaultLCID (VOID)
784 {
785 LCID lcid;
786 NtQueryDefaultLocale( FALSE, &lcid );
787 return lcid;
788
789 // return SystemLocale;
790 }
791
792 #endif
793
794
795 /*
796 * @unimplemented
797 */
798 LANGID
799 STDCALL
800 GetSystemDefaultUILanguage(VOID)
801 {
802 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
803 return 0;
804 }
805
806
807 #ifndef _OLE2NLS_IN_BUILD_
808
809 /*
810 * @implemented
811 */
812 LCID
813 STDCALL
814 GetThreadLocale (VOID)
815 {
816 return NtCurrentTeb()->CurrentLocale;
817 }
818
819 #endif
820
821
822
823
824
825 #ifndef _OLE2NLS_IN_BUILD_
826
827 /*
828 * @implemented
829 */
830 LANGID
831 STDCALL
832 GetUserDefaultLangID (VOID)
833 {
834 return LANGIDFROMLCID(GetUserDefaultLCID());
835 }
836
837
838 /*
839 * @implemented
840 */
841 LCID
842 STDCALL
843 GetUserDefaultLCID (VOID)
844 {
845 LCID lcid;
846 NtQueryDefaultLocale(TRUE, &lcid);
847 return lcid;
848 }
849
850 #endif
851
852
853 /*
854 * @unimplemented
855 */
856 LANGID
857 STDCALL
858 GetUserDefaultUILanguage(VOID)
859 {
860 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
861 return 0;
862 }
863
864
865 /*
866 * @unimplemented
867 */
868 GEOID
869 STDCALL
870 GetUserGeoID(
871 GEOCLASS GeoClass)
872 {
873 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
874 return 0;
875 }
876
877
878 /*
879 * @unimplemented
880 */
881 BOOL
882 STDCALL
883 IsValidLanguageGroup(
884 LGRPID LanguageGroup,
885 DWORD dwFlags)
886 {
887 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
888 return 0;
889 }
890
891
892
893 /******************************************************************************
894 * @implemented
895 * RIPPED FROM WINE's dlls\kernel\locale.c rev 1.44
896 *
897 * IsValidLocale (KERNEL32.@)
898 *
899 * Determine if a locale is valid.
900 *
901 * PARAMS
902 * lcid [I] LCID of the locale to check
903 * flags [I] LCID_SUPPORTED = Valid, LCID_INSTALLED = Valid and installed on the system
904 *
905 * RETURN
906 * TRUE, if lcid is valid,
907 * FALSE, otherwise.
908 *
909 * NOTES
910 * Wine does not currently make the distinction between supported and installed. All
911 * languages supported are installed by default.
912 */
913 BOOL STDCALL
914 IsValidLocale(
915 LCID lcid,
916 DWORD flags
917 )
918 {
919 /* check if language is registered in the kernel32 resources */
920 return FindResourceExW( hCurrentModule, (LPWSTR)RT_STRING,
921 (LPCWSTR)LOCALE_ILANGUAGE, LANGIDFROMLCID(lcid)) != 0;
922 }
923
924
925
926 #ifndef _OLE2NLS_IN_BUILD_
927
928 /*
929 * @unimplemented
930 */
931 int
932 STDCALL
933 LCMapStringA (
934 LCID Locale,
935 DWORD dwMapFlags,
936 LPCSTR lpSrcStr,
937 int cchSrc,
938 LPSTR lpDestStr,
939 int cchDest
940 )
941 {
942 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
943 return 0;
944 }
945
946
947 /*
948 * @unimplemented
949 */
950 int
951 STDCALL
952 LCMapStringW (
953 LCID Locale,
954 DWORD dwMapFlags,
955 LPCWSTR lpSrcStr,
956 int cchSrc,
957 LPWSTR lpDestStr,
958 int cchDest
959 )
960 {
961 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
962 return 0;
963 }
964
965 #endif
966
967
968 /*
969 * @unimplemented
970 */
971 BOOL
972 STDCALL
973 SetCalendarInfoA(
974 LCID Locale,
975 CALID Calendar,
976 CALTYPE CalType,
977 LPCSTR lpCalData)
978 {
979 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
980 return 0;
981 }
982
983 /*
984 * @unimplemented
985 */
986 BOOL
987 STDCALL
988 SetCalendarInfoW(
989 LCID Locale,
990 CALID Calendar,
991 CALTYPE CalType,
992 LPCWSTR lpCalData)
993 {
994 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
995 return 0;
996 }
997
998
999 #ifndef _OLE2NLS_IN_BUILD_
1000
1001 /*
1002 * @unimplemented
1003 */
1004 BOOL
1005 STDCALL
1006 SetLocaleInfoA (
1007 LCID Locale,
1008 LCTYPE LCType,
1009 LPCSTR lpLCData
1010 )
1011 {
1012 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1013 return FALSE;
1014 }
1015
1016
1017 /*
1018 * @unimplemented
1019 */
1020 BOOL
1021 STDCALL
1022 SetLocaleInfoW (
1023 LCID Locale,
1024 LCTYPE LCType,
1025 LPCWSTR lpLCData
1026 )
1027 {
1028 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1029 return FALSE;
1030 }
1031
1032
1033 /**********************************************************************
1034 * @implemented
1035 * RIPPED FROM WINE's dlls\kernel\locale.c rev 1.42
1036 *
1037 * SetThreadLocale (KERNEL32.@)
1038 *
1039 * Set the current threads locale.
1040 *
1041 * PARAMS
1042 * lcid [I] LCID of the locale to set
1043 *
1044 * RETURNS
1045 * Success: TRUE. The threads locale is set to lcid.
1046 * Failure: FALSE. Use GetLastError() to determine the cause.
1047 *
1048 */
1049 BOOL WINAPI SetThreadLocale( LCID lcid )
1050 {
1051 DPRINT("SetThreadLocale(0x%04lX)\n", lcid);
1052
1053 lcid = ConvertDefaultLocale(lcid);
1054
1055 if (lcid != GetThreadLocale())
1056 {
1057 if (!IsValidLocale(lcid, LCID_SUPPORTED))
1058 {
1059 SetLastError(ERROR_INVALID_PARAMETER);
1060 return FALSE;
1061 }
1062
1063 NtCurrentTeb()->CurrentLocale = lcid;
1064 /* FIXME: NtCurrentTeb()->code_page = get_lcid_codepage( lcid );
1065 * Wine save the acp for easy/fast access, but ROS has no such Teb member.
1066 * Maybe add this member to ros as well?
1067 */
1068
1069 /*
1070 Lag test app for å se om locale etc, endres i en app. etter at prosessen er
1071 startet, eller om bare nye prosesser blir berørt.
1072 */
1073 }
1074 return TRUE;
1075 }
1076
1077 #endif
1078
1079
1080 /*
1081 * @unimplemented
1082 */
1083 BOOL
1084 STDCALL
1085 SetUserGeoID(
1086 GEOID GeoId)
1087 {
1088 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1089 return 0;
1090 }