1 /* $Id: lang.c,v 1.21 2004/08/24 17:21:11 navaraf Exp $
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
13 #include "../include/debug.h"
15 /* FIXME: these are included in winnls.h, however including this file causes alot of
16 conflicting type errors. */
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)
24 //static LCID SystemLocale = MAKELCID(LANG_ENGLISH, SORT_DEFAULT);
26 //#define _OLE2NLS_IN_BUILD_
29 /******************************************************************************
31 * RIPPED FROM WINE's dlls\kernel\locale.c rev 1.42
33 * ConvertDefaultLocale (KERNEL32.@)
35 * Convert a default locale identifier into a real identifier.
38 * lcid [I] LCID identifier of the locale to convert
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.
47 LCID WINAPI
ConvertDefaultLocale( LCID lcid
)
53 case LOCALE_SYSTEM_DEFAULT
:
54 lcid
= GetSystemDefaultLCID();
56 case LOCALE_USER_DEFAULT
:
58 lcid
= GetUserDefaultLCID();
61 /* Replace SUBLANG_NEUTRAL with SUBLANG_DEFAULT */
62 langid
= LANGIDFROMLCID(lcid
);
63 if (SUBLANGID(langid
) == SUBLANG_NEUTRAL
)
65 langid
= MAKELANGID(PRIMARYLANGID(langid
), SUBLANG_DEFAULT
);
66 lcid
= MAKELCID(langid
, SORTIDFROMLCID(lcid
));
82 CALINFO_ENUMPROCEXA lpCalInfoEnumProcEx
,
87 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
98 CALINFO_ENUMPROCEXW lpCalInfoEnumProcEx
,
103 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
116 DATEFMT_ENUMPROCEXA lpDateFmtEnumProcEx
,
120 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
131 DATEFMT_ENUMPROCEXW lpDateFmtEnumProcEx
,
135 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
145 EnumLanguageGroupLocalesA(
146 LANGGROUPLOCALE_ENUMPROCA lpLangGroupLocaleEnumProc
,
147 LGRPID LanguageGroup
,
151 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
161 EnumLanguageGroupLocalesW(
162 LANGGROUPLOCALE_ENUMPROCW lpLangGroupLocaleEnumProc
,
163 LGRPID LanguageGroup
,
167 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
177 EnumSystemCodePagesW (
178 CODEPAGE_ENUMPROCW lpCodePageEnumProc
,
182 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
192 EnumSystemCodePagesA (
193 CODEPAGE_ENUMPROCA lpCodePageEnumProc
,
197 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
210 GEO_ENUMPROC lpGeoEnumProc
)
214 SetLastError(ERROR_INVALID_PARAMETER
);
220 case GEOCLASS_NATION
:
221 /*RtlEnterCriticalSection(&DllLock);
223 FIXME - Get GEO IDs calling Csr
225 RtlLeaveCriticalSection(&DllLock);*/
227 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
231 SetLastError(ERROR_INVALID_FLAGS
);
244 EnumSystemLanguageGroupsA(
245 LANGUAGEGROUP_ENUMPROCA lpLanguageGroupEnumProc
,
249 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
254 #ifndef _OLE2NLS_IN_BUILD_
262 LOCALE_ENUMPROCW lpLocaleEnumProc
,
266 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
277 LOCALE_ENUMPROCA lpLocaleEnumProc
,
281 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
296 UILANGUAGE_ENUMPROCA lpUILanguageEnumProc
,
300 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
311 UILANGUAGE_ENUMPROCW lpUILanguageEnumProc
,
315 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
320 #ifndef _OLE2NLS_IN_BUILD_
329 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
349 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
367 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
372 #ifndef _OLE2NLS_IN_BUILD_
381 LPCPINFO CodePageInfo
386 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
388 CodePageInfo
->MaxCharSize
= 1;
389 CodePageInfo
->DefaultChar
[0] = '?';
390 for (i
= 1; i
< MAX_DEFAULTCHAR
; i
++)
392 CodePageInfo
->DefaultChar
[i
] = 0;
394 for (i
= 0; i
< MAX_LEADBYTES
; i
++)
396 CodePageInfo
->LeadByte
[i
] = 0;
413 LPCPINFOEXW lpCPInfoEx
)
415 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
428 LPCPINFOEXA lpCPInfoEx
)
430 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
447 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
464 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
468 const WCHAR
*RosGetLocaleValueName( DWORD lctype
)
470 switch (lctype
& ~LOCALE_LOCALEINFOFLAGSMASK
)
472 /* These values are used by SetLocaleInfo and GetLocaleInfo, and
473 * the values are stored in the registry, confirmed under Windows.
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";
506 /* The following are not listed under MSDN as supported,
507 * but seem to be used and also stored in the registry.
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";
519 HKEY
RosCreateRegistryKey(void)
521 OBJECT_ATTRIBUTES objAttr
;
522 UNICODE_STRING nameW
;
525 if (RtlOpenCurrentUser( KEY_ALL_ACCESS
, &hKey
) != STATUS_SUCCESS
) return 0;
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");
535 if (NtCreateKey( &hKey
, KEY_ALL_ACCESS
, &objAttr
, 0, NULL
, 0, NULL
) != STATUS_SUCCESS
) hKey
= 0;
536 NtClose( objAttr
.RootDirectory
);
540 INT
RosGetRegistryLocaleInfo( LPCWSTR lpValue
, LPWSTR lpBuffer
, INT nLen
)
546 UNICODE_STRING usNameW
;
547 KEY_VALUE_PARTIAL_INFORMATION
*kvpiInfo
;
548 const int nInfoSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
);
550 if (!(hKey
= RosCreateRegistryKey())) return -1;
552 RtlInitUnicodeString( &usNameW
, lpValue
);
553 dwSize
= nInfoSize
+ nLen
* sizeof(WCHAR
);
555 if (!(kvpiInfo
= HeapAlloc( GetProcessHeap(), 0, dwSize
)))
558 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
562 ntStatus
= NtQueryValueKey( hKey
, &usNameW
, KeyValuePartialInformation
, kvpiInfo
, dwSize
, &dwSize
);
563 if (ntStatus
== STATUS_BUFFER_OVERFLOW
&& !lpBuffer
) ntStatus
= 0;
567 nRet
= (dwSize
- nInfoSize
) / sizeof(WCHAR
);
569 if (!nRet
|| ((WCHAR
*)kvpiInfo
->Data
)[nRet
- 1])
571 if (nRet
< nLen
|| !lpBuffer
) nRet
++;
574 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
578 if (nRet
&& lpBuffer
)
580 memcpy( lpBuffer
, kvpiInfo
->Data
, (nRet
- 1) * sizeof(WCHAR
) );
581 lpBuffer
[nRet
- 1] = 0;
586 if (ntStatus
== STATUS_OBJECT_NAME_NOT_FOUND
) nRet
= -1;
589 SetLastError( RtlNtStatusToDosError(ntStatus
) );
594 HeapFree( GetProcessHeap(), 0, kvpiInfo
);
619 if (cchData
< 0 || (cchData
&& !lpLCData
))
621 SetLastError( ERROR_INVALID_PARAMETER
);
624 if (!cchData
) lpLCData
= NULL
;
626 if (Locale
== LOCALE_NEUTRAL
|| Locale
== LOCALE_SYSTEM_DEFAULT
) Locale
= GetSystemDefaultLCID();
627 else if (Locale
== LOCALE_USER_DEFAULT
) Locale
= GetUserDefaultLCID();
629 uiFlags
= LCType
& LOCALE_LOCALEINFOFLAGSMASK
;
630 LCType
&= ~LOCALE_LOCALEINFOFLAGSMASK
;
632 if (!(uiFlags
& LOCALE_NOUSEROVERRIDE
) && Locale
== GetUserDefaultLCID())
634 const WCHAR
*value
= RosGetLocaleValueName(LCType
);
636 if (value
&& ((nRet
= RosGetRegistryLocaleInfo( value
, lpLCData
, cchData
)) != -1)) return nRet
;
639 liLangID
= LANGIDFROMLCID( Locale
);
641 if (SUBLANGID(liLangID
) == SUBLANG_NEUTRAL
)
642 liLangID
= MAKELANGID(PRIMARYLANGID(liLangID
), SUBLANG_DEFAULT
);
644 hModule
= GetModuleHandleW( L
"kernel32.dll" );
645 if (!(hRsrc
= FindResourceExW( hModule
, (LPWSTR
)RT_STRING
, (LPCWSTR
)((LCType
>> 4) + 1), liLangID
)))
647 SetLastError( ERROR_INVALID_FLAGS
);
650 if (!(hMem
= LoadResource( hModule
, hRsrc
)))
653 ch
= LockResource( hMem
);
654 for (i
= 0; i
< (LCType
& 0x0f); i
++) ch
+= *ch
+ 1;
656 if (uiFlags
& LOCALE_RETURN_NUMBER
) nRet
= sizeof(UINT
) / sizeof(WCHAR
);
657 else nRet
= (LCType
== LOCALE_FONTSIGNATURE
) ? *ch
: *ch
+ 1;
659 if (!lpLCData
) return nRet
;
663 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
667 if (uiFlags
& LOCALE_RETURN_NUMBER
)
670 WCHAR
*chEnd
, *chTmp
= HeapAlloc( GetProcessHeap(), 0, (*ch
+ 1) * sizeof(WCHAR
) );
675 memcpy( chTmp
, ch
+ 1, *ch
* sizeof(WCHAR
) );
677 uiNum
= wcstol( chTmp
, &chEnd
, 10 );
680 memcpy( lpLCData
, &uiNum
, sizeof(uiNum
) );
683 SetLastError( ERROR_INVALID_FLAGS
);
686 HeapFree( GetProcessHeap(), 0, chTmp
);
690 memcpy( lpLCData
, ch
+ 1, *ch
* sizeof(WCHAR
) );
691 if (LCType
!= LOCALE_FONTSIGNATURE
) lpLCData
[nRet
-1] = 0;
698 /***********************************************************************
701 * Retrieve the ANSI codepage for a given locale.
703 inline static UINT
get_lcid_codepage( LCID lcid
)
706 if (!GetLocaleInfoW( lcid
, LOCALE_IDEFAULTANSICODEPAGE
|LOCALE_RETURN_NUMBER
, (WCHAR
*)&ret
,
707 sizeof(ret
)/sizeof(WCHAR
) )) ret
= 0;
716 * Get information about an aspect of a locale.
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
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.
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.
734 INT STDCALL
GetLocaleInfoA( LCID lcid
, LCTYPE lctype
, LPSTR buffer
, INT len
)
739 if (len
< 0 || (len
&& !buffer
))
741 SetLastError( ERROR_INVALID_PARAMETER
);
744 if (!len
) buffer
= NULL
;
746 if (!(lenW
= GetLocaleInfoW( lcid
, lctype
, NULL
, 0 ))) return 0;
748 if (!(bufferW
= HeapAlloc( GetProcessHeap(), 0, lenW
* sizeof(WCHAR
) )))
750 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
753 if ((ret
= GetLocaleInfoW( lcid
, lctype
, bufferW
, lenW
)))
755 if ((lctype
& LOCALE_RETURN_NUMBER
) ||
756 ((lctype
& ~LOCALE_LOCALEINFOFLAGSMASK
) == LOCALE_FONTSIGNATURE
))
758 /* it's not an ASCII string, just bytes */
759 ret
*= sizeof(WCHAR
);
762 if (ret
<= len
) memcpy( buffer
, bufferW
, ret
);
765 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
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
);
777 HeapFree( GetProcessHeap(), 0, bufferW
);
792 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
793 return 437; /* FIXME: call csrss.exe */
797 #ifndef _OLE2NLS_IN_BUILD_
804 GetSystemDefaultLangID (VOID
)
806 return LANGIDFROMLCID(GetSystemDefaultLCID());
815 GetSystemDefaultLCID (VOID
)
818 NtQueryDefaultLocale( FALSE
, &lcid
);
821 // return SystemLocale;
832 GetSystemDefaultUILanguage(VOID
)
834 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
839 #ifndef _OLE2NLS_IN_BUILD_
846 GetThreadLocale (VOID
)
848 return NtCurrentTeb()->CurrentLocale
;
857 #ifndef _OLE2NLS_IN_BUILD_
864 GetUserDefaultLangID (VOID
)
866 return LANGIDFROMLCID(GetUserDefaultLCID());
875 GetUserDefaultLCID (VOID
)
878 NtQueryDefaultLocale(TRUE
, &lcid
);
890 GetUserDefaultUILanguage(VOID
)
892 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
905 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
915 IsValidLanguageGroup(
916 LGRPID LanguageGroup
,
919 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
925 /******************************************************************************
927 * RIPPED FROM WINE's dlls\kernel\locale.c rev 1.44
929 * IsValidLocale (KERNEL32.@)
931 * Determine if a locale is valid.
934 * lcid [I] LCID of the locale to check
935 * flags [I] LCID_SUPPORTED = Valid, LCID_INSTALLED = Valid and installed on the system
938 * TRUE, if lcid is valid,
942 * Wine does not currently make the distinction between supported and installed. All
943 * languages supported are installed by default.
951 /* check if language is registered in the kernel32 resources */
952 return FindResourceExW( hCurrentModule
, (LPWSTR
)RT_STRING
,
953 (LPCWSTR
)LOCALE_ILANGUAGE
, LANGIDFROMLCID(lcid
)) != 0;
958 #ifndef _OLE2NLS_IN_BUILD_
974 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
993 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1011 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1026 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1031 #ifndef _OLE2NLS_IN_BUILD_
1044 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1060 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1065 /**********************************************************************
1067 * RIPPED FROM WINE's dlls\kernel\locale.c rev 1.42
1069 * SetThreadLocale (KERNEL32.@)
1071 * Set the current threads locale.
1074 * lcid [I] LCID of the locale to set
1077 * Success: TRUE. The threads locale is set to lcid.
1078 * Failure: FALSE. Use GetLastError() to determine the cause.
1081 BOOL WINAPI
SetThreadLocale( LCID lcid
)
1083 DPRINT("SetThreadLocale(0x%04lX)\n", lcid
);
1085 lcid
= ConvertDefaultLocale(lcid
);
1087 if (lcid
!= GetThreadLocale())
1089 if (!IsValidLocale(lcid
, LCID_SUPPORTED
))
1091 SetLastError(ERROR_INVALID_PARAMETER
);
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?
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.
1120 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);