2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ex/locale.c
5 * PURPOSE: Locale (Language) Support for the Executive
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * Thomas Weidenmueller (w3seek@reactos.org
11 /* INCLUDES ******************************************************************/
17 /* GLOBALS *******************************************************************/
19 /* System IDs: EN_US */
20 LCID PsDefaultSystemLocaleId
= 0x00000409;
21 LANGID PsInstallUILanguageId
= LANGIDFROMLCID(0x00000409);
23 /* UI/Thread IDs: Same as system */
24 LANGID PsDefaultUILanguageId
= 0x00000409;
25 LCID PsDefaultThreadLocaleId
= LANGIDFROMLCID(0x00000409);
27 /* PRIVATE FUNCTIONS *********************************************************/
31 ExpGetCurrentUserUILanguage(IN PWSTR MuiName
,
32 OUT LANGID
* LanguageId
)
34 UCHAR ValueBuffer
[256];
35 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
36 OBJECT_ATTRIBUTES ObjectAttributes
;
37 UNICODE_STRING KeyName
=
38 RTL_CONSTANT_STRING(L
"Control Panel\\International");
39 UNICODE_STRING ValueName
;
40 UNICODE_STRING ValueString
;
48 /* Setup the key name */
49 RtlInitUnicodeString(&ValueName
, MuiName
);
51 /* Open the use key */
52 Status
= RtlOpenCurrentUser(KEY_READ
, &UserKey
);
53 if (!NT_SUCCESS(Status
)) return Status
;
55 /* Initialize the attributes and open the key */
56 InitializeObjectAttributes(&ObjectAttributes
,
61 Status
= ZwOpenKey(&KeyHandle
, KEY_QUERY_VALUE
,&ObjectAttributes
);
62 if (NT_SUCCESS(Status
))
64 /* Set buffer and query the current value */
65 ValueInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)ValueBuffer
;
66 Status
= ZwQueryValueKey(KeyHandle
,
68 KeyValuePartialInformation
,
72 if (NT_SUCCESS(Status
))
74 /* Success, is the value the right type? */
75 if (ValueInfo
->Type
== REG_SZ
)
77 /* It is. Initialize the data and convert it */
78 RtlInitUnicodeString(&ValueString
, (PWSTR
)ValueInfo
->Data
);
79 Status
= RtlUnicodeStringToInteger(&ValueString
, 16, &Value
);
80 if (NT_SUCCESS(Status
))
82 /* Return the language */
83 *LanguageId
= (USHORT
)Value
;
89 Status
= STATUS_UNSUCCESSFUL
;
97 /* Close the user key and return */
104 ExpSetCurrentUserUILanguage(IN PWSTR MuiName
,
105 IN LANGID LanguageId
)
107 OBJECT_ATTRIBUTES ObjectAttributes
;
108 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"Control Panel\\Desktop");
109 UNICODE_STRING ValueName
;
110 WCHAR ValueBuffer
[8];
117 /* Setup the key name */
118 RtlInitUnicodeString(&ValueName
, MuiName
);
120 /* Open the use key */
121 Status
= RtlOpenCurrentUser(KEY_WRITE
, &UserHandle
);
122 if (!NT_SUCCESS(Status
)) return Status
;
124 /* Initialize the attributes */
125 InitializeObjectAttributes(&ObjectAttributes
,
127 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
132 Status
= ZwOpenKey(&KeyHandle
, KEY_SET_VALUE
, &ObjectAttributes
);
133 if (NT_SUCCESS(Status
))
135 /* Setup the value name */
136 ValueLength
= swprintf(ValueBuffer
,
140 /* Set the length for the call and set the value */
141 ValueLength
= (ValueLength
+ 1) * sizeof(WCHAR
);
142 Status
= ZwSetValueKey(KeyHandle
,
149 /* Close the handle for this key */
153 /* Close the user key and return status */
158 /* PUBLIC FUNCTIONS **********************************************************/
162 NtQueryDefaultLocale(IN BOOLEAN UserProfile
,
163 OUT PLCID DefaultLocaleId
)
165 NTSTATUS Status
= STATUS_SUCCESS
;
168 /* Enter SEH for probing */
171 /* Check if we came from user mode */
172 if (KeGetPreviousMode() != KernelMode
)
174 /* Probe the language ID */
175 ProbeForWriteLangid(DefaultLocaleId
);
178 /* Check if we have a user profile */
181 /* Return session wide thread locale */
182 *DefaultLocaleId
= MmGetSessionLocaleId();
186 /* Return system locale */
187 *DefaultLocaleId
= PsDefaultSystemLocaleId
;
190 _SEH2_EXCEPT(ExSystemExceptionFilter())
192 /* Get exception code */
193 Status
= _SEH2_GetExceptionCode();
203 NtSetDefaultLocale(IN BOOLEAN UserProfile
,
204 IN LCID DefaultLocaleId
)
206 OBJECT_ATTRIBUTES ObjectAttributes
;
207 UNICODE_STRING KeyName
;
208 UNICODE_STRING ValueName
;
209 UNICODE_STRING LocaleString
;
212 WCHAR ValueBuffer
[20];
215 UCHAR KeyValueBuffer
[256];
216 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
;
219 /* Check if we have a profile */
222 /* Open the user's key */
223 Status
= RtlOpenCurrentUser(KEY_WRITE
, &UserKey
);
224 if (!NT_SUCCESS(Status
)) return(Status
);
226 /* Initialize the registry location */
227 RtlInitUnicodeString(&KeyName
, L
"Control Panel\\International");
228 RtlInitUnicodeString(&ValueName
, L
"Locale");
232 /* Initialize the system registry location */
233 RtlInitUnicodeString(&KeyName
,
234 L
"\\Registry\\Machine\\System\\CurrentControlSet"
235 L
"\\Control\\Nls\\Language");
236 RtlInitUnicodeString(&ValueName
, L
"Default");
240 /* Initailize the object attributes */
241 InitializeObjectAttributes(&ObjectAttributes
,
243 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
247 /* Check if we don't have a default locale yet */
248 if (!DefaultLocaleId
)
250 /* Open the key for reading */
251 Status
= ZwOpenKey(&KeyHandle
, KEY_QUERY_VALUE
, &ObjectAttributes
);
252 if (!NT_SUCCESS(Status
))
258 /* Query the key value */
259 KeyValueInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyValueBuffer
;
260 Status
= ZwQueryValueKey(KeyHandle
,
262 KeyValuePartialInformation
,
264 sizeof(KeyValueBuffer
),
266 if (!NT_SUCCESS(Status
))
271 /* Check if this is a REG_DWORD */
272 if ((KeyValueInformation
->Type
== REG_DWORD
) &&
273 (KeyValueInformation
->DataLength
== sizeof(ULONG
)))
275 /* It contains the LCID as a DWORD */
276 DefaultLocaleId
= *((ULONG
*)KeyValueInformation
->Data
);
278 /* Otherwise check for a REG_SZ */
279 else if (KeyValueInformation
->Type
== REG_SZ
)
281 /* Initialize a unicode string from the value data */
282 LocaleString
.Buffer
= (PWCHAR
)KeyValueInformation
->Data
;
283 LocaleString
.Length
= (USHORT
)KeyValueInformation
->DataLength
;
284 LocaleString
.MaximumLength
= LocaleString
.Length
;
286 /* Convert the hex string to a number */
287 RtlUnicodeStringToInteger(&LocaleString
, 16, &DefaultLocaleId
);
291 Status
= STATUS_UNSUCCESSFUL
;
296 /* Otherwise, open the key */
297 Status
= ZwOpenKey(&KeyHandle
, KEY_SET_VALUE
, &ObjectAttributes
);
298 if (NT_SUCCESS(Status
))
300 /* Check if we had a profile */
303 /* Fill in the buffer */
304 ValueLength
= swprintf(ValueBuffer
,
306 (ULONG
)DefaultLocaleId
);
310 /* Fill in the buffer */
311 ValueLength
= swprintf(ValueBuffer
,
313 (ULONG
)DefaultLocaleId
& 0xFFFF);
316 /* Set the length for the registry call */
317 ValueLength
= (ValueLength
+ 1) * sizeof(WCHAR
);
319 /* Now write the actual value */
320 Status
= ZwSetValueKey(KeyHandle
,
331 /* Close the locale key */
334 ObCloseHandle(KeyHandle
, KernelMode
);
337 /* Close the user key */
340 ObCloseHandle(UserKey
, KernelMode
);
343 /* Check for success */
344 if (NT_SUCCESS(Status
))
346 /* Check if it was for a user */
349 /* Set the session wide thread locale */
350 MmSetSessionLocaleId(DefaultLocaleId
);
354 /* Set system locale */
355 PsDefaultSystemLocaleId
= DefaultLocaleId
;
368 NtQueryInstallUILanguage(OUT LANGID
* LanguageId
)
370 NTSTATUS Status
= STATUS_SUCCESS
;
373 /* Enter SEH for probing */
376 /* Check if we came from user mode */
377 if (KeGetPreviousMode() != KernelMode
)
379 /* Probe the Language ID */
380 ProbeForWriteLangid(LanguageId
);
384 *LanguageId
= PsInstallUILanguageId
;
386 _SEH2_EXCEPT(ExSystemExceptionFilter())
388 /* Get exception code */
389 Status
= _SEH2_GetExceptionCode();
402 NtQueryDefaultUILanguage(OUT LANGID
* LanguageId
)
405 LANGID SafeLanguageId
;
408 /* Call the executive helper routine */
409 Status
= ExpGetCurrentUserUILanguage(L
"MultiUILanguageId", &SafeLanguageId
);
411 /* Enter SEH for probing */
414 /* Check if we came from user mode */
415 if (KeGetPreviousMode() != KernelMode
)
417 /* Probe the Language ID */
418 ProbeForWriteLangid(LanguageId
);
421 if (NT_SUCCESS(Status
))
423 /* Success, return the language */
424 *LanguageId
= SafeLanguageId
;
428 /* Failed, use fallback value */
429 *LanguageId
= PsInstallUILanguageId
;
432 _SEH2_EXCEPT(ExSystemExceptionFilter())
434 /* Return exception code */
435 return _SEH2_GetExceptionCode();
440 return STATUS_SUCCESS
;
448 NtSetDefaultUILanguage(IN LANGID LanguageId
)
453 /* Check if the caller specified a language id */
456 /* Set the pending MUI language id */
457 Status
= ExpSetCurrentUserUILanguage(L
"MUILanguagePending", LanguageId
);
461 /* Otherwise get the pending MUI language id */
462 Status
= ExpGetCurrentUserUILanguage(L
"MUILanguagePending", &LanguageId
);
463 if (!NT_SUCCESS(Status
))
468 /* And apply it as actual */
469 Status
= ExpSetCurrentUserUILanguage(L
"MultiUILanguageId", LanguageId
);