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);
27 /******************************************************************************
29 * RIPPED FROM WINE's dlls\kernel\locale.c rev 1.42
31 * ConvertDefaultLocale (KERNEL32.@)
33 * Convert a default locale identifier into a real identifier.
36 * lcid [I] LCID identifier of the locale to convert
39 * lcid unchanged, if not a default locale or its sublanguage is
40 * not SUBLANG_NEUTRAL.
41 * GetSystemDefaultLCID(), if lcid == LOCALE_SYSTEM_DEFAULT.
42 * GetUserDefaultLCID(), if lcid == LOCALE_USER_DEFAULT or LOCALE_NEUTRAL.
43 * Otherwise, lcid with sublanguage changed to SUBLANG_DEFAULT.
46 ConvertDefaultLocale(LCID lcid
)
52 case LOCALE_SYSTEM_DEFAULT
:
53 lcid
= GetSystemDefaultLCID();
56 case LOCALE_USER_DEFAULT
:
58 lcid
= GetUserDefaultLCID();
62 /* Replace SUBLANG_NEUTRAL with SUBLANG_DEFAULT */
63 langid
= LANGIDFROMLCID(lcid
);
64 if (SUBLANGID(langid
) == SUBLANG_NEUTRAL
)
66 langid
= MAKELANGID(PRIMARYLANGID(langid
), SUBLANG_DEFAULT
);
67 lcid
= MAKELCID(langid
, SORTIDFROMLCID(lcid
));
81 CALINFO_ENUMPROCEXA lpCalInfoEnumProcEx
,
86 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
97 CALINFO_ENUMPROCEXW lpCalInfoEnumProcEx
,
102 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
115 DATEFMT_ENUMPROCEXA lpDateFmtEnumProcEx
,
119 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
130 DATEFMT_ENUMPROCEXW lpDateFmtEnumProcEx
,
134 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
144 EnumLanguageGroupLocalesA(
145 LANGGROUPLOCALE_ENUMPROCA lpLangGroupLocaleEnumProc
,
146 LGRPID LanguageGroup
,
150 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
160 EnumLanguageGroupLocalesW(
161 LANGGROUPLOCALE_ENUMPROCW lpLangGroupLocaleEnumProc
,
162 LGRPID LanguageGroup
,
166 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
176 EnumSystemCodePagesW (
177 CODEPAGE_ENUMPROCW lpCodePageEnumProc
,
181 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
191 EnumSystemCodePagesA (
192 CODEPAGE_ENUMPROCA lpCodePageEnumProc
,
196 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
209 GEO_ENUMPROC lpGeoEnumProc
)
213 SetLastError(ERROR_INVALID_PARAMETER
);
219 case GEOCLASS_NATION
:
220 /*RtlEnterCriticalSection(&DllLock);
222 FIXME - Get GEO IDs calling Csr
224 RtlLeaveCriticalSection(&DllLock);*/
226 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
230 SetLastError(ERROR_INVALID_FLAGS
);
243 EnumSystemLanguageGroupsA(
244 LANGUAGEGROUP_ENUMPROCA pLangGroupEnumProc
,
248 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
258 EnumSystemLanguageGroupsW(
259 LANGUAGEGROUP_ENUMPROCW pLangGroupEnumProc
,
263 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
274 LOCALE_ENUMPROCA lpLocaleEnumProc
,
278 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
289 LOCALE_ENUMPROCW lpLocaleEnumProc
,
293 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
304 UILANGUAGE_ENUMPROCA lpUILanguageEnumProc
,
308 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
319 UILANGUAGE_ENUMPROCW lpUILanguageEnumProc
,
323 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
340 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
358 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
370 LPCPINFO CodePageInfo
375 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
377 CodePageInfo
->MaxCharSize
= 1;
378 CodePageInfo
->DefaultChar
[0] = '?';
379 for (i
= 1; i
< MAX_DEFAULTCHAR
; i
++)
381 CodePageInfo
->DefaultChar
[i
] = 0;
383 for (i
= 0; i
< MAX_LEADBYTES
; i
++)
385 CodePageInfo
->LeadByte
[i
] = 0;
400 LPCPINFOEXW lpCPInfoEx
)
402 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
415 LPCPINFOEXA lpCPInfoEx
)
417 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
434 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
451 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
455 const WCHAR
*RosGetLocaleValueName( DWORD lctype
)
457 switch (lctype
& ~LOCALE_LOCALEINFOFLAGSMASK
)
459 /* These values are used by SetLocaleInfo and GetLocaleInfo, and
460 * the values are stored in the registry, confirmed under Windows.
462 case LOCALE_ICALENDARTYPE
: return L
"iCalendarType";
463 case LOCALE_ICURRDIGITS
: return L
"iCurrDigits";
464 case LOCALE_ICURRENCY
: return L
"iCurrency";
465 case LOCALE_IDIGITS
: return L
"iDigits";
466 case LOCALE_IFIRSTDAYOFWEEK
: return L
"iFirstDayOfWeek";
467 case LOCALE_IFIRSTWEEKOFYEAR
: return L
"iFirstWeekOfYear";
468 case LOCALE_ILZERO
: return L
"iLZero";
469 case LOCALE_IMEASURE
: return L
"iMeasure";
470 case LOCALE_INEGCURR
: return L
"iNegCurr";
471 case LOCALE_INEGNUMBER
: return L
"iNegNumber";
472 case LOCALE_IPAPERSIZE
: return L
"iPaperSize";
473 case LOCALE_ITIME
: return L
"iTime";
474 case LOCALE_S1159
: return L
"s1159";
475 case LOCALE_S2359
: return L
"s2359";
476 case LOCALE_SCURRENCY
: return L
"sCurrency";
477 case LOCALE_SDATE
: return L
"sDate";
478 case LOCALE_SDECIMAL
: return L
"sDecimal";
479 case LOCALE_SGROUPING
: return L
"sGrouping";
480 case LOCALE_SLIST
: return L
"sList";
481 case LOCALE_SLONGDATE
: return L
"sLongDate";
482 case LOCALE_SMONDECIMALSEP
: return L
"sMonDecimalSep";
483 case LOCALE_SMONGROUPING
: return L
"sMonGrouping";
484 case LOCALE_SMONTHOUSANDSEP
: return L
"sMonThousandSep";
485 case LOCALE_SNEGATIVESIGN
: return L
"sNegativeSign";
486 case LOCALE_SPOSITIVESIGN
: return L
"sPositiveSign";
487 case LOCALE_SSHORTDATE
: return L
"sShortDate";
488 case LOCALE_STHOUSAND
: return L
"sThousand";
489 case LOCALE_STIME
: return L
"sTime";
490 case LOCALE_STIMEFORMAT
: return L
"sTimeFormat";
491 case LOCALE_SYEARMONTH
: return L
"sYearMonth";
493 /* The following are not listed under MSDN as supported,
494 * but seem to be used and also stored in the registry.
496 case LOCALE_ICOUNTRY
: return L
"iCountry";
497 case LOCALE_IDATE
: return L
"iDate";
498 case LOCALE_ILDATE
: return L
"iLDate";
499 case LOCALE_ITLZERO
: return L
"iTLZero";
500 case LOCALE_SCOUNTRY
: return L
"sCountry";
501 case LOCALE_SLANGUAGE
: return L
"sLanguage";
506 HKEY
RosCreateRegistryKey(void)
508 OBJECT_ATTRIBUTES objAttr
;
509 UNICODE_STRING nameW
;
512 if (RtlOpenCurrentUser( KEY_ALL_ACCESS
, &hKey
) != STATUS_SUCCESS
) return 0;
514 objAttr
.Length
= sizeof(objAttr
);
515 objAttr
.RootDirectory
= hKey
;
516 objAttr
.ObjectName
= &nameW
;
517 objAttr
.Attributes
= 0;
518 objAttr
.SecurityDescriptor
= NULL
;
519 objAttr
.SecurityQualityOfService
= NULL
;
520 RtlInitUnicodeString( &nameW
, L
"Control Panel\\International");
522 if (NtCreateKey( &hKey
, KEY_ALL_ACCESS
, &objAttr
, 0, NULL
, 0, NULL
) != STATUS_SUCCESS
) hKey
= 0;
523 NtClose( objAttr
.RootDirectory
);
527 INT
RosGetRegistryLocaleInfo( LPCWSTR lpValue
, LPWSTR lpBuffer
, INT nLen
)
533 UNICODE_STRING usNameW
;
534 KEY_VALUE_PARTIAL_INFORMATION
*kvpiInfo
;
535 const int nInfoSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
);
537 if (!(hKey
= RosCreateRegistryKey())) return -1;
539 RtlInitUnicodeString( &usNameW
, lpValue
);
540 dwSize
= nInfoSize
+ nLen
* sizeof(WCHAR
);
542 if (!(kvpiInfo
= HeapAlloc( GetProcessHeap(), 0, dwSize
)))
545 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
549 ntStatus
= NtQueryValueKey( hKey
, &usNameW
, KeyValuePartialInformation
, kvpiInfo
, dwSize
, &dwSize
);
550 if (ntStatus
== STATUS_BUFFER_OVERFLOW
&& !lpBuffer
) ntStatus
= 0;
554 nRet
= (dwSize
- nInfoSize
) / sizeof(WCHAR
);
556 if (!nRet
|| ((WCHAR
*)kvpiInfo
->Data
)[nRet
- 1])
558 if (nRet
< nLen
|| !lpBuffer
) nRet
++;
561 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
565 if (nRet
&& lpBuffer
)
567 memcpy( lpBuffer
, kvpiInfo
->Data
, (nRet
- 1) * sizeof(WCHAR
) );
568 lpBuffer
[nRet
- 1] = 0;
573 if (ntStatus
== STATUS_OBJECT_NAME_NOT_FOUND
) nRet
= -1;
576 SetLastError( RtlNtStatusToDosError(ntStatus
) );
581 HeapFree( GetProcessHeap(), 0, kvpiInfo
);
606 if (cchData
< 0 || (cchData
&& !lpLCData
))
608 SetLastError( ERROR_INVALID_PARAMETER
);
611 if (!cchData
) lpLCData
= NULL
;
613 if (Locale
== LOCALE_NEUTRAL
|| Locale
== LOCALE_SYSTEM_DEFAULT
) Locale
= GetSystemDefaultLCID();
614 else if (Locale
== LOCALE_USER_DEFAULT
) Locale
= GetUserDefaultLCID();
616 uiFlags
= LCType
& LOCALE_LOCALEINFOFLAGSMASK
;
617 LCType
&= ~LOCALE_LOCALEINFOFLAGSMASK
;
619 if (!(uiFlags
& LOCALE_NOUSEROVERRIDE
) && Locale
== GetUserDefaultLCID())
621 const WCHAR
*value
= RosGetLocaleValueName(LCType
);
623 if (value
&& ((nRet
= RosGetRegistryLocaleInfo( value
, lpLCData
, cchData
)) != -1)) return nRet
;
626 liLangID
= LANGIDFROMLCID( Locale
);
628 if (SUBLANGID(liLangID
) == SUBLANG_NEUTRAL
)
629 liLangID
= MAKELANGID(PRIMARYLANGID(liLangID
), SUBLANG_DEFAULT
);
631 hModule
= GetModuleHandleW( L
"kernel32.dll" );
632 if (!(hRsrc
= FindResourceExW( hModule
, (LPWSTR
)RT_STRING
, (LPCWSTR
)((LCType
>> 4) + 1), liLangID
)))
634 SetLastError( ERROR_INVALID_FLAGS
);
637 if (!(hMem
= LoadResource( hModule
, hRsrc
)))
640 ch
= LockResource( hMem
);
641 for (i
= 0; i
< (LCType
& 0x0f); i
++) ch
+= *ch
+ 1;
643 if (uiFlags
& LOCALE_RETURN_NUMBER
) nRet
= sizeof(UINT
) / sizeof(WCHAR
);
644 else nRet
= (LCType
== LOCALE_FONTSIGNATURE
) ? *ch
: *ch
+ 1;
646 if (!lpLCData
) return nRet
;
650 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
654 if (uiFlags
& LOCALE_RETURN_NUMBER
)
657 WCHAR
*chEnd
, *chTmp
= HeapAlloc( GetProcessHeap(), 0, (*ch
+ 1) * sizeof(WCHAR
) );
662 memcpy( chTmp
, ch
+ 1, *ch
* sizeof(WCHAR
) );
664 uiNum
= wcstol( chTmp
, &chEnd
, 10 );
667 memcpy( lpLCData
, &uiNum
, sizeof(uiNum
) );
670 SetLastError( ERROR_INVALID_FLAGS
);
673 HeapFree( GetProcessHeap(), 0, chTmp
);
677 memcpy( lpLCData
, ch
+ 1, *ch
* sizeof(WCHAR
) );
678 if (LCType
!= LOCALE_FONTSIGNATURE
) lpLCData
[nRet
-1] = 0;
685 /***********************************************************************
688 * Retrieve the ANSI codepage for a given locale.
690 inline static UINT
get_lcid_codepage( LCID lcid
)
693 if (!GetLocaleInfoW( lcid
, LOCALE_IDEFAULTANSICODEPAGE
|LOCALE_RETURN_NUMBER
, (WCHAR
*)&ret
,
694 sizeof(ret
)/sizeof(WCHAR
) )) ret
= 0;
713 WCHAR
*buf1W
= NtCurrentTeb()->StaticUnicodeBuffer
;
714 WCHAR
*buf2W
= buf1W
+ 130;
716 INT len1W
, len2W
, ret
;
719 if (!lpString1
|| !lpString2
)
721 SetLastError(ERROR_INVALID_PARAMETER
);
724 if (cchCount1
< 0) cchCount1
= strlen(lpString1
);
725 if (cchCount2
< 0) cchCount2
= strlen(lpString2
);
727 locale_cp
= get_lcid_codepage(Locale
);
729 len1W
= MultiByteToWideChar(locale_cp
, 0, lpString1
, cchCount1
, buf1W
, 130);
734 len1W
= MultiByteToWideChar(locale_cp
, 0, lpString1
, cchCount1
, NULL
, 0);
735 str1W
= HeapAlloc(GetProcessHeap(), 0, len1W
* sizeof(WCHAR
));
738 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
741 MultiByteToWideChar(locale_cp
, 0, lpString1
, cchCount1
, str1W
, len1W
);
743 len2W
= MultiByteToWideChar(locale_cp
, 0, lpString2
, cchCount2
, buf2W
, 130);
748 len2W
= MultiByteToWideChar(locale_cp
, 0, lpString2
, cchCount2
, NULL
, 0);
749 str2W
= HeapAlloc(GetProcessHeap(), 0, len2W
* sizeof(WCHAR
));
752 if (str1W
!= buf1W
) HeapFree(GetProcessHeap(), 0, str1W
);
753 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
756 MultiByteToWideChar(locale_cp
, 0, lpString2
, cchCount2
, str2W
, len2W
);
759 ret
= CompareStringW(Locale
, dwCmpFlags
, str1W
, len1W
, str2W
, len2W
);
761 if (str1W
!= buf1W
) HeapFree(GetProcessHeap(), 0, str1W
);
762 if (str2W
!= buf2W
) HeapFree(GetProcessHeap(), 0, str2W
);
782 UNICODE_STRING String1
, String2
;
784 if (!lpString1
|| !lpString2
)
786 SetLastError(ERROR_INVALID_PARAMETER
);
790 if (dwCmpFlags
& ~(NORM_IGNORECASE
| NORM_IGNORENONSPACE
|
791 NORM_IGNORESYMBOLS
| SORT_STRINGSORT
| NORM_IGNOREKANATYPE
|
792 NORM_IGNOREWIDTH
| 0x10000000))
794 SetLastError(ERROR_INVALID_FLAGS
);
798 if (dwCmpFlags
& ~NORM_IGNORECASE
)
800 DPRINT1("CompareString: STUB flags - 0x%x\n",
801 dwCmpFlags
& ~NORM_IGNORECASE
);
804 if (cchCount1
< 0) cchCount1
= lstrlenW(lpString1
);
805 if (cchCount2
< 0) cchCount2
= lstrlenW(lpString2
);
807 String1
.Length
= String1
.MaximumLength
= cchCount1
* sizeof(WCHAR
);
808 String1
.Buffer
= (LPWSTR
)lpString1
;
809 String2
.Length
= String2
.MaximumLength
= cchCount2
* sizeof(WCHAR
);
810 String2
.Buffer
= (LPWSTR
)lpString2
;
812 Result
= RtlCompareUnicodeString(
813 &String1
, &String2
, dwCmpFlags
& NORM_IGNORECASE
);
815 if (Result
) /* need to translate result */
816 return (Result
< 0) ? CSTR_LESS_THAN
: CSTR_GREATER_THAN
;
827 * Get information about an aspect of a locale.
830 * lcid [I] LCID of the locale
831 * lctype [I] LCTYPE_ flags from "winnls.h"
832 * buffer [O] Destination for the information
833 * len [I] Length of buffer in characters
836 * Success: The size of the data requested. If buffer is non-NULL, it is filled
837 * with the information.
838 * Failure: 0. Use GetLastError() to determine the cause.
841 * - LOCALE_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT
842 * - The string returned is NUL terminated, except for LOCALE_FONTSIGNATURE,
843 * which is a bit string.
845 INT STDCALL
GetLocaleInfoA( LCID lcid
, LCTYPE lctype
, LPSTR buffer
, INT len
)
850 if (len
< 0 || (len
&& !buffer
))
852 SetLastError( ERROR_INVALID_PARAMETER
);
855 if (!len
) buffer
= NULL
;
857 if (!(lenW
= GetLocaleInfoW( lcid
, lctype
, NULL
, 0 ))) return 0;
859 if (!(bufferW
= HeapAlloc( GetProcessHeap(), 0, lenW
* sizeof(WCHAR
) )))
861 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
864 if ((ret
= GetLocaleInfoW( lcid
, lctype
, bufferW
, lenW
)))
866 if ((lctype
& LOCALE_RETURN_NUMBER
) ||
867 ((lctype
& ~LOCALE_LOCALEINFOFLAGSMASK
) == LOCALE_FONTSIGNATURE
))
869 /* it's not an ASCII string, just bytes */
870 ret
*= sizeof(WCHAR
);
873 if (ret
<= len
) memcpy( buffer
, bufferW
, ret
);
876 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
883 UINT codepage
= CP_ACP
;
884 if (!(lctype
& LOCALE_USE_CP_ACP
)) codepage
= get_lcid_codepage( lcid
);
885 ret
= WideCharToMultiByte( codepage
, 0, bufferW
, ret
, buffer
, len
, NULL
, NULL
);
888 HeapFree( GetProcessHeap(), 0, bufferW
);
897 GetSystemDefaultLangID(VOID
)
899 return LANGIDFROMLCID(GetSystemDefaultLCID());
907 GetSystemDefaultLCID(VOID
)
911 NtQueryDefaultLocale(FALSE
, &lcid
);
921 GetSystemDefaultUILanguage(VOID
)
926 Status
= NtQueryInstallUILanguage(&LanguageId
);
927 if (!NT_SUCCESS(Status
))
929 SetLastErrorByStatus(Status
);
941 GetThreadLocale(VOID
)
943 return NtCurrentTeb()->CurrentLocale
;
951 GetUserDefaultLangID(VOID
)
953 return LANGIDFROMLCID(GetUserDefaultLCID());
961 GetUserDefaultLCID(VOID
)
966 Status
= NtQueryDefaultLocale(TRUE
, &lcid
);
967 if (!NT_SUCCESS(Status
))
969 SetLastErrorByStatus(Status
);
981 GetUserDefaultUILanguage(VOID
)
986 Status
= NtQueryDefaultUILanguage(&LangId
);
987 if (!NT_SUCCESS(Status
))
989 SetLastErrorByStatus(Status
);
1005 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1015 IsValidLanguageGroup(
1016 LGRPID LanguageGroup
,
1019 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1024 /******************************************************************************
1027 * Determine if a locale is valid.
1030 * Locale [I] LCID of the locale to check
1031 * dwFlags [I] LCID_SUPPORTED = Valid
1032 * LCID_INSTALLED = Valid and installed on the system
1035 * TRUE, if Locale is valid,
1041 IsValidLocale(LCID Locale
,
1044 OBJECT_ATTRIBUTES ObjectAttributes
;
1045 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
1046 WCHAR ValueNameBuffer
[9];
1047 UNICODE_STRING KeyName
;
1048 UNICODE_STRING ValueName
;
1055 DPRINT("IsValidLocale() called\n");
1057 if ((dwFlags
& ~(LCID_SUPPORTED
| LCID_INSTALLED
)) ||
1058 (dwFlags
== (LCID_SUPPORTED
| LCID_INSTALLED
)))
1060 DPRINT("Invalid flags: %lx\n", dwFlags
);
1064 if (Locale
& 0xFFFF0000)
1066 RtlInitUnicodeString(&KeyName
,
1067 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Nls\\Locale\\Alternate Sorts");
1071 RtlInitUnicodeString(&KeyName
,
1072 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Nls\\Locale");
1075 InitializeObjectAttributes(&ObjectAttributes
,
1077 OBJ_CASE_INSENSITIVE
,
1081 Status
= NtOpenKey(&KeyHandle
,
1084 if (!NT_SUCCESS(Status
))
1086 DPRINT("NtOpenKey() failed (Status %lx)\n", Status
);
1090 swprintf(ValueNameBuffer
, L
"%08lx", (ULONG
)Locale
);
1091 RtlInitUnicodeString(&ValueName
, ValueNameBuffer
);
1093 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 4 * sizeof(WCHAR
);
1094 KeyInfo
= RtlAllocateHeap(RtlGetProcessHeap(),
1097 if (KeyInfo
== NULL
)
1099 DPRINT("RtlAllocateHeap() failed (Status %lx)\n", Status
);
1104 Status
= NtQueryValueKey(KeyHandle
,
1106 KeyValuePartialInformation
,
1112 if (!NT_SUCCESS(Status
))
1114 DPRINT("NtQueryValueKey() failed (Status %lx)\n", Status
);
1115 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
1119 if (dwFlags
& LCID_SUPPORTED
)
1121 DPRINT("Locale is supported\n");
1122 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
1126 ValueData
= (PWSTR
)&KeyInfo
->Data
[0];
1127 if ((dwFlags
& LCID_INSTALLED
) &&
1128 (KeyInfo
->Type
== REG_SZ
) &&
1129 (KeyInfo
->DataLength
== 2 * sizeof(WCHAR
)) &&
1130 (ValueData
[0] == L
'1'))
1132 DPRINT("Locale is supported and installed\n");
1133 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
1137 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
1139 DPRINT("IsValidLocale() called\n");
1159 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1178 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1194 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1209 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1225 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1241 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1246 /**********************************************************************
1248 * RIPPED FROM WINE's dlls\kernel\locale.c rev 1.42
1250 * SetThreadLocale (KERNEL32.@)
1252 * Set the current threads locale.
1255 * lcid [I] LCID of the locale to set
1258 * Success: TRUE. The threads locale is set to lcid.
1259 * Failure: FALSE. Use GetLastError() to determine the cause.
1262 BOOL WINAPI
SetThreadLocale( LCID lcid
)
1264 DPRINT("SetThreadLocale(0x%04lX)\n", lcid
);
1266 lcid
= ConvertDefaultLocale(lcid
);
1268 if (lcid
!= GetThreadLocale())
1270 if (!IsValidLocale(lcid
, LCID_SUPPORTED
))
1272 SetLastError(ERROR_INVALID_PARAMETER
);
1276 NtCurrentTeb()->CurrentLocale
= lcid
;
1277 /* FIXME: NtCurrentTeb()->code_page = get_lcid_codepage( lcid );
1278 * Wine save the acp for easy/fast access, but ROS has no such Teb member.
1279 * Maybe add this member to ros as well?
1283 Lag test app for å se om locale etc, endres i en app. etter at prosessen er
1284 startet, eller om bare nye prosesser blir berørt.
1299 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);