- Implementation of GetCPFileNameFromRegistry, GetNlsSectionName and IsValidCodePage.
[reactos.git] / reactos / lib / kernel32 / misc / lang.c
1 /* $Id: lang.c,v 1.21 2004/08/24 17:21:11 navaraf 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 #ifndef _OLE2NLS_IN_BUILD_
321
322 /*
323 * @unimplemented
324 */
325 UINT
326 STDCALL
327 GetACP (VOID)
328 {
329 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
330 return 1252;
331 }
332
333 #endif
334
335
336 /*
337 * @unimplemented
338 */
339 int
340 STDCALL
341 GetCalendarInfoA(
342 LCID Locale,
343 CALID Calendar,
344 CALTYPE CalType,
345 LPSTR lpCalData,
346 int cchData,
347 LPDWORD lpValue)
348 {
349 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
350 return 0;
351 }
352
353
354 /*
355 * @unimplemented
356 */
357 int
358 STDCALL
359 GetCalendarInfoW(
360 LCID Locale,
361 CALID Calendar,
362 CALTYPE CalType,
363 LPWSTR lpCalData,
364 int cchData,
365 LPDWORD lpValue)
366 {
367 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
368 return 0;
369 }
370
371
372 #ifndef _OLE2NLS_IN_BUILD_
373
374 /*
375 * @unimplemented
376 */
377 BOOL
378 STDCALL
379 GetCPInfo (
380 UINT CodePage,
381 LPCPINFO CodePageInfo
382 )
383 {
384 unsigned i;
385
386 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
387
388 CodePageInfo->MaxCharSize = 1;
389 CodePageInfo->DefaultChar[0] = '?';
390 for (i = 1; i < MAX_DEFAULTCHAR; i++)
391 {
392 CodePageInfo->DefaultChar[i] = 0;
393 }
394 for (i = 0; i < MAX_LEADBYTES; i++)
395 {
396 CodePageInfo->LeadByte[i] = 0;
397 }
398
399 return TRUE;
400 }
401
402 #endif
403
404
405 /*
406 * @unimplemented
407 */
408 BOOL
409 STDCALL
410 GetCPInfoExW(
411 UINT CodePage,
412 DWORD dwFlags,
413 LPCPINFOEXW lpCPInfoEx)
414 {
415 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
416 return 0;
417 }
418
419
420 /*
421 * @unimplemented
422 */
423 BOOL
424 STDCALL
425 GetCPInfoExA(
426 UINT CodePage,
427 DWORD dwFlags,
428 LPCPINFOEXA lpCPInfoEx)
429 {
430 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
431 return 0;
432 }
433
434
435 /*
436 * @unimplemented
437 */
438 int
439 STDCALL
440 GetGeoInfoW(
441 GEOID Location,
442 GEOTYPE GeoType,
443 LPWSTR lpGeoData,
444 int cchData,
445 LANGID LangId)
446 {
447 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
448 return 0;
449 }
450
451
452 /*
453 * @unimplemented
454 */
455 int
456 STDCALL
457 GetGeoInfoA(
458 GEOID Location,
459 GEOTYPE GeoType,
460 LPSTR lpGeoData,
461 int cchData,
462 LANGID LangId)
463 {
464 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
465 return 0;
466 }
467
468 const WCHAR *RosGetLocaleValueName( DWORD lctype )
469 {
470 switch (lctype & ~LOCALE_LOCALEINFOFLAGSMASK)
471 {
472 /* These values are used by SetLocaleInfo and GetLocaleInfo, and
473 * the values are stored in the registry, confirmed under Windows.
474 */
475 case LOCALE_ICALENDARTYPE: return L"iCalendarType";
476 case LOCALE_ICURRDIGITS: return L"iCurrDigits";
477 case LOCALE_ICURRENCY: return L"iCurrency";
478 case LOCALE_IDIGITS: return L"iDigits";
479 case LOCALE_IFIRSTDAYOFWEEK: return L"iFirstDayOfWeek";
480 case LOCALE_IFIRSTWEEKOFYEAR: return L"iFirstWeekOfYear";
481 case LOCALE_ILZERO: return L"iLZero";
482 case LOCALE_IMEASURE: return L"iMeasure";
483 case LOCALE_INEGCURR: return L"iNegCurr";
484 case LOCALE_INEGNUMBER: return L"iNegNumber";
485 case LOCALE_IPAPERSIZE: return L"iPaperSize";
486 case LOCALE_ITIME: return L"iTime";
487 case LOCALE_S1159: return L"s1159";
488 case LOCALE_S2359: return L"s2359";
489 case LOCALE_SCURRENCY: return L"sCurrency";
490 case LOCALE_SDATE: return L"sDate";
491 case LOCALE_SDECIMAL: return L"sDecimal";
492 case LOCALE_SGROUPING: return L"sGrouping";
493 case LOCALE_SLIST: return L"sList";
494 case LOCALE_SLONGDATE: return L"sLongDate";
495 case LOCALE_SMONDECIMALSEP: return L"sMonDecimalSep";
496 case LOCALE_SMONGROUPING: return L"sMonGrouping";
497 case LOCALE_SMONTHOUSANDSEP: return L"sMonThousandSep";
498 case LOCALE_SNEGATIVESIGN: return L"sNegativeSign";
499 case LOCALE_SPOSITIVESIGN: return L"sPositiveSign";
500 case LOCALE_SSHORTDATE: return L"sShortDate";
501 case LOCALE_STHOUSAND: return L"sThousand";
502 case LOCALE_STIME: return L"sTime";
503 case LOCALE_STIMEFORMAT: return L"sTimeFormat";
504 case LOCALE_SYEARMONTH: return L"sYearMonth";
505
506 /* The following are not listed under MSDN as supported,
507 * but seem to be used and also stored in the registry.
508 */
509 case LOCALE_ICOUNTRY: return L"iCountry";
510 case LOCALE_IDATE: return L"iDate";
511 case LOCALE_ILDATE: return L"iLDate";
512 case LOCALE_ITLZERO: return L"iTLZero";
513 case LOCALE_SCOUNTRY: return L"sCountry";
514 case LOCALE_SLANGUAGE: return L"sLanguage";
515 }
516 return NULL;
517 }
518
519 HKEY RosCreateRegistryKey(void)
520 {
521 OBJECT_ATTRIBUTES objAttr;
522 UNICODE_STRING nameW;
523 HANDLE hKey;
524
525 if (RtlOpenCurrentUser( KEY_ALL_ACCESS, &hKey ) != STATUS_SUCCESS) return 0;
526
527 objAttr.Length = sizeof(objAttr);
528 objAttr.RootDirectory = hKey;
529 objAttr.ObjectName = &nameW;
530 objAttr.Attributes = 0;
531 objAttr.SecurityDescriptor = NULL;
532 objAttr.SecurityQualityOfService = NULL;
533 RtlInitUnicodeString( &nameW, L"Control Panel\\International");
534
535 if (NtCreateKey( &hKey, KEY_ALL_ACCESS, &objAttr, 0, NULL, 0, NULL ) != STATUS_SUCCESS) hKey = 0;
536 NtClose( objAttr.RootDirectory );
537 return hKey;
538 }
539
540 INT RosGetRegistryLocaleInfo( LPCWSTR lpValue, LPWSTR lpBuffer, INT nLen )
541 {
542 DWORD dwSize;
543 HKEY hKey;
544 INT nRet;
545 NTSTATUS ntStatus;
546 UNICODE_STRING usNameW;
547 KEY_VALUE_PARTIAL_INFORMATION *kvpiInfo;
548 const int nInfoSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
549
550 if (!(hKey = RosCreateRegistryKey())) return -1;
551
552 RtlInitUnicodeString( &usNameW, lpValue );
553 dwSize = nInfoSize + nLen * sizeof(WCHAR);
554
555 if (!(kvpiInfo = HeapAlloc( GetProcessHeap(), 0, dwSize )))
556 {
557 NtClose( hKey );
558 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
559 return 0;
560 }
561
562 ntStatus = NtQueryValueKey( hKey, &usNameW, KeyValuePartialInformation, kvpiInfo, dwSize, &dwSize );
563 if (ntStatus == STATUS_BUFFER_OVERFLOW && !lpBuffer) ntStatus = 0;
564
565 if (!ntStatus)
566 {
567 nRet = (dwSize - nInfoSize) / sizeof(WCHAR);
568
569 if (!nRet || ((WCHAR *)kvpiInfo->Data)[nRet - 1])
570 {
571 if (nRet < nLen || !lpBuffer) nRet++;
572 else
573 {
574 SetLastError( ERROR_INSUFFICIENT_BUFFER );
575 nRet = 0;
576 }
577 }
578 if (nRet && lpBuffer)
579 {
580 memcpy( lpBuffer, kvpiInfo->Data, (nRet - 1) * sizeof(WCHAR) );
581 lpBuffer[nRet - 1] = 0;
582 }
583 }
584 else
585 {
586 if (ntStatus == STATUS_OBJECT_NAME_NOT_FOUND) nRet = -1;
587 else
588 {
589 SetLastError( RtlNtStatusToDosError(ntStatus) );
590 nRet = 0;
591 }
592 }
593 NtClose( hKey );
594 HeapFree( GetProcessHeap(), 0, kvpiInfo );
595 return nRet;
596 }
597
598 /*
599 * @implemented
600 */
601 int
602 STDCALL
603 GetLocaleInfoW (
604 LCID Locale,
605 LCTYPE LCType,
606 LPWSTR lpLCData,
607 int cchData
608 )
609 {
610 LANGID liLangID;
611 HRSRC hRsrc;
612 HGLOBAL hMem;
613 HMODULE hModule;
614 INT nRet;
615 UINT uiFlags;
616 const WCHAR *ch;
617 int i;
618
619 if (cchData < 0 || (cchData && !lpLCData))
620 {
621 SetLastError( ERROR_INVALID_PARAMETER );
622 return 0;
623 }
624 if (!cchData) lpLCData = NULL;
625
626 if (Locale == LOCALE_NEUTRAL || Locale == LOCALE_SYSTEM_DEFAULT) Locale = GetSystemDefaultLCID();
627 else if (Locale == LOCALE_USER_DEFAULT) Locale = GetUserDefaultLCID();
628
629 uiFlags = LCType & LOCALE_LOCALEINFOFLAGSMASK;
630 LCType &= ~LOCALE_LOCALEINFOFLAGSMASK;
631
632 if (!(uiFlags & LOCALE_NOUSEROVERRIDE) && Locale == GetUserDefaultLCID())
633 {
634 const WCHAR *value = RosGetLocaleValueName(LCType);
635
636 if (value && ((nRet = RosGetRegistryLocaleInfo( value, lpLCData, cchData )) != -1)) return nRet;
637 }
638
639 liLangID = LANGIDFROMLCID( Locale );
640
641 if (SUBLANGID(liLangID) == SUBLANG_NEUTRAL)
642 liLangID = MAKELANGID(PRIMARYLANGID(liLangID), SUBLANG_DEFAULT);
643
644 hModule = GetModuleHandleW( L"kernel32.dll" );
645 if (!(hRsrc = FindResourceExW( hModule, (LPWSTR)RT_STRING, (LPCWSTR)((LCType >> 4) + 1), liLangID )))
646 {
647 SetLastError( ERROR_INVALID_FLAGS );
648 return 0;
649 }
650 if (!(hMem = LoadResource( hModule, hRsrc )))
651 return 0;
652
653 ch = LockResource( hMem );
654 for (i = 0; i < (LCType & 0x0f); i++) ch += *ch + 1;
655
656 if (uiFlags & LOCALE_RETURN_NUMBER) nRet = sizeof(UINT) / sizeof(WCHAR);
657 else nRet = (LCType == LOCALE_FONTSIGNATURE) ? *ch : *ch + 1;
658
659 if (!lpLCData) return nRet;
660
661 if (nRet > cchData)
662 {
663 SetLastError( ERROR_INSUFFICIENT_BUFFER );
664 return 0;
665 }
666
667 if (uiFlags & LOCALE_RETURN_NUMBER)
668 {
669 UINT uiNum;
670 WCHAR *chEnd, *chTmp = HeapAlloc( GetProcessHeap(), 0, (*ch + 1) * sizeof(WCHAR) );
671
672 if (!chTmp)
673 return 0;
674
675 memcpy( chTmp, ch + 1, *ch * sizeof(WCHAR) );
676 chTmp[*ch] = L'\0';
677 uiNum = wcstol( chTmp, &chEnd, 10 );
678
679 if (!*chEnd)
680 memcpy( lpLCData, &uiNum, sizeof(uiNum) );
681 else
682 {
683 SetLastError( ERROR_INVALID_FLAGS );
684 nRet = 0;
685 }
686 HeapFree( GetProcessHeap(), 0, chTmp );
687 }
688 else
689 {
690 memcpy( lpLCData, ch + 1, *ch * sizeof(WCHAR) );
691 if (LCType != LOCALE_FONTSIGNATURE) lpLCData[nRet-1] = 0;
692 }
693 return nRet;
694 }
695
696
697
698 /***********************************************************************
699 * get_lcid_codepage
700 *
701 * Retrieve the ANSI codepage for a given locale.
702 */
703 inline static UINT get_lcid_codepage( LCID lcid )
704 {
705 UINT ret;
706 if (!GetLocaleInfoW( lcid, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER, (WCHAR *)&ret,
707 sizeof(ret)/sizeof(WCHAR) )) ret = 0;
708 return ret;
709 }
710
711
712
713 /*
714 * @implemented
715 *
716 * Get information about an aspect of a locale.
717 *
718 * PARAMS
719 * lcid [I] LCID of the locale
720 * lctype [I] LCTYPE_ flags from "winnls.h"
721 * buffer [O] Destination for the information
722 * len [I] Length of buffer in characters
723 *
724 * RETURNS
725 * Success: The size of the data requested. If buffer is non-NULL, it is filled
726 * with the information.
727 * Failure: 0. Use GetLastError() to determine the cause.
728 *
729 * NOTES
730 * - LOCALE_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT
731 * - The string returned is NUL terminated, except for LOCALE_FONTSIGNATURE,
732 * which is a bit string.
733 */
734 INT STDCALL GetLocaleInfoA( LCID lcid, LCTYPE lctype, LPSTR buffer, INT len )
735 {
736 WCHAR *bufferW;
737 INT lenW, ret;
738
739 if (len < 0 || (len && !buffer))
740 {
741 SetLastError( ERROR_INVALID_PARAMETER );
742 return 0;
743 }
744 if (!len) buffer = NULL;
745
746 if (!(lenW = GetLocaleInfoW( lcid, lctype, NULL, 0 ))) return 0;
747
748 if (!(bufferW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) )))
749 {
750 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
751 return 0;
752 }
753 if ((ret = GetLocaleInfoW( lcid, lctype, bufferW, lenW )))
754 {
755 if ((lctype & LOCALE_RETURN_NUMBER) ||
756 ((lctype & ~LOCALE_LOCALEINFOFLAGSMASK) == LOCALE_FONTSIGNATURE))
757 {
758 /* it's not an ASCII string, just bytes */
759 ret *= sizeof(WCHAR);
760 if (buffer)
761 {
762 if (ret <= len) memcpy( buffer, bufferW, ret );
763 else
764 {
765 SetLastError( ERROR_INSUFFICIENT_BUFFER );
766 ret = 0;
767 }
768 }
769 }
770 else
771 {
772 UINT codepage = CP_ACP;
773 if (!(lctype & LOCALE_USE_CP_ACP)) codepage = get_lcid_codepage( lcid );
774 ret = WideCharToMultiByte( codepage, 0, bufferW, ret, buffer, len, NULL, NULL );
775 }
776 }
777 HeapFree( GetProcessHeap(), 0, bufferW );
778 return ret;
779 }
780
781
782
783
784
785 /*
786 * @unimplemented
787 */
788 UINT
789 STDCALL
790 GetOEMCP (VOID)
791 {
792 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
793 return 437; /* FIXME: call csrss.exe */
794 }
795
796
797 #ifndef _OLE2NLS_IN_BUILD_
798
799 /*
800 * @implemented
801 */
802 LANGID
803 STDCALL
804 GetSystemDefaultLangID (VOID)
805 {
806 return LANGIDFROMLCID(GetSystemDefaultLCID());
807 }
808
809
810 /*
811 * @implemented
812 */
813 LCID
814 STDCALL
815 GetSystemDefaultLCID (VOID)
816 {
817 LCID lcid;
818 NtQueryDefaultLocale( FALSE, &lcid );
819 return lcid;
820
821 // return SystemLocale;
822 }
823
824 #endif
825
826
827 /*
828 * @unimplemented
829 */
830 LANGID
831 STDCALL
832 GetSystemDefaultUILanguage(VOID)
833 {
834 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
835 return 0;
836 }
837
838
839 #ifndef _OLE2NLS_IN_BUILD_
840
841 /*
842 * @implemented
843 */
844 LCID
845 STDCALL
846 GetThreadLocale (VOID)
847 {
848 return NtCurrentTeb()->CurrentLocale;
849 }
850
851 #endif
852
853
854
855
856
857 #ifndef _OLE2NLS_IN_BUILD_
858
859 /*
860 * @implemented
861 */
862 LANGID
863 STDCALL
864 GetUserDefaultLangID (VOID)
865 {
866 return LANGIDFROMLCID(GetUserDefaultLCID());
867 }
868
869
870 /*
871 * @implemented
872 */
873 LCID
874 STDCALL
875 GetUserDefaultLCID (VOID)
876 {
877 LCID lcid;
878 NtQueryDefaultLocale(TRUE, &lcid);
879 return lcid;
880 }
881
882 #endif
883
884
885 /*
886 * @unimplemented
887 */
888 LANGID
889 STDCALL
890 GetUserDefaultUILanguage(VOID)
891 {
892 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
893 return 0;
894 }
895
896
897 /*
898 * @unimplemented
899 */
900 GEOID
901 STDCALL
902 GetUserGeoID(
903 GEOCLASS GeoClass)
904 {
905 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
906 return 0;
907 }
908
909
910 /*
911 * @unimplemented
912 */
913 BOOL
914 STDCALL
915 IsValidLanguageGroup(
916 LGRPID LanguageGroup,
917 DWORD dwFlags)
918 {
919 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
920 return 0;
921 }
922
923
924
925 /******************************************************************************
926 * @implemented
927 * RIPPED FROM WINE's dlls\kernel\locale.c rev 1.44
928 *
929 * IsValidLocale (KERNEL32.@)
930 *
931 * Determine if a locale is valid.
932 *
933 * PARAMS
934 * lcid [I] LCID of the locale to check
935 * flags [I] LCID_SUPPORTED = Valid, LCID_INSTALLED = Valid and installed on the system
936 *
937 * RETURN
938 * TRUE, if lcid is valid,
939 * FALSE, otherwise.
940 *
941 * NOTES
942 * Wine does not currently make the distinction between supported and installed. All
943 * languages supported are installed by default.
944 */
945 BOOL STDCALL
946 IsValidLocale(
947 LCID lcid,
948 DWORD flags
949 )
950 {
951 /* check if language is registered in the kernel32 resources */
952 return FindResourceExW( hCurrentModule, (LPWSTR)RT_STRING,
953 (LPCWSTR)LOCALE_ILANGUAGE, LANGIDFROMLCID(lcid)) != 0;
954 }
955
956
957
958 #ifndef _OLE2NLS_IN_BUILD_
959
960 /*
961 * @unimplemented
962 */
963 int
964 STDCALL
965 LCMapStringA (
966 LCID Locale,
967 DWORD dwMapFlags,
968 LPCSTR lpSrcStr,
969 int cchSrc,
970 LPSTR lpDestStr,
971 int cchDest
972 )
973 {
974 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
975 return 0;
976 }
977
978
979 /*
980 * @unimplemented
981 */
982 int
983 STDCALL
984 LCMapStringW (
985 LCID Locale,
986 DWORD dwMapFlags,
987 LPCWSTR lpSrcStr,
988 int cchSrc,
989 LPWSTR lpDestStr,
990 int cchDest
991 )
992 {
993 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
994 return 0;
995 }
996
997 #endif
998
999
1000 /*
1001 * @unimplemented
1002 */
1003 BOOL
1004 STDCALL
1005 SetCalendarInfoA(
1006 LCID Locale,
1007 CALID Calendar,
1008 CALTYPE CalType,
1009 LPCSTR lpCalData)
1010 {
1011 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1012 return 0;
1013 }
1014
1015 /*
1016 * @unimplemented
1017 */
1018 BOOL
1019 STDCALL
1020 SetCalendarInfoW(
1021 LCID Locale,
1022 CALID Calendar,
1023 CALTYPE CalType,
1024 LPCWSTR lpCalData)
1025 {
1026 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1027 return 0;
1028 }
1029
1030
1031 #ifndef _OLE2NLS_IN_BUILD_
1032
1033 /*
1034 * @unimplemented
1035 */
1036 BOOL
1037 STDCALL
1038 SetLocaleInfoA (
1039 LCID Locale,
1040 LCTYPE LCType,
1041 LPCSTR lpLCData
1042 )
1043 {
1044 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1045 return FALSE;
1046 }
1047
1048
1049 /*
1050 * @unimplemented
1051 */
1052 BOOL
1053 STDCALL
1054 SetLocaleInfoW (
1055 LCID Locale,
1056 LCTYPE LCType,
1057 LPCWSTR lpLCData
1058 )
1059 {
1060 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1061 return FALSE;
1062 }
1063
1064
1065 /**********************************************************************
1066 * @implemented
1067 * RIPPED FROM WINE's dlls\kernel\locale.c rev 1.42
1068 *
1069 * SetThreadLocale (KERNEL32.@)
1070 *
1071 * Set the current threads locale.
1072 *
1073 * PARAMS
1074 * lcid [I] LCID of the locale to set
1075 *
1076 * RETURNS
1077 * Success: TRUE. The threads locale is set to lcid.
1078 * Failure: FALSE. Use GetLastError() to determine the cause.
1079 *
1080 */
1081 BOOL WINAPI SetThreadLocale( LCID lcid )
1082 {
1083 DPRINT("SetThreadLocale(0x%04lX)\n", lcid);
1084
1085 lcid = ConvertDefaultLocale(lcid);
1086
1087 if (lcid != GetThreadLocale())
1088 {
1089 if (!IsValidLocale(lcid, LCID_SUPPORTED))
1090 {
1091 SetLastError(ERROR_INVALID_PARAMETER);
1092 return FALSE;
1093 }
1094
1095 NtCurrentTeb()->CurrentLocale = lcid;
1096 /* FIXME: NtCurrentTeb()->code_page = get_lcid_codepage( lcid );
1097 * Wine save the acp for easy/fast access, but ROS has no such Teb member.
1098 * Maybe add this member to ros as well?
1099 */
1100
1101 /*
1102 Lag test app for å se om locale etc, endres i en app. etter at prosessen er
1103 startet, eller om bare nye prosesser blir berørt.
1104 */
1105 }
1106 return TRUE;
1107 }
1108
1109 #endif
1110
1111
1112 /*
1113 * @unimplemented
1114 */
1115 BOOL
1116 STDCALL
1117 SetUserGeoID(
1118 GEOID GeoId)
1119 {
1120 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1121 return 0;
1122 }