ReactOS 0.4.15-dev-5874-gc762234
locale.c
Go to the documentation of this file.
1/*
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)
7 * Eric Kohl
8 * Thomas Weidenmueller (w3seek@reactos.org
9 */
10
11/* INCLUDES ******************************************************************/
12
13#include <ntoskrnl.h>
14#define NDEBUG
15#include <debug.h>
16
17/* GLOBALS *******************************************************************/
18
19/* System IDs: EN_US */
22
23/* UI/Thread IDs: Same as system */
26
27/* PRIVATE FUNCTIONS *********************************************************/
28
32 OUT LANGID* LanguageId)
33{
34 UCHAR ValueBuffer[256];
38 RTL_CONSTANT_STRING(L"Control Panel\\Desktop");
40 UNICODE_STRING ValueString;
43 HANDLE UserKey;
46 PAGED_CODE();
47
48 /* Setup the key name */
50
51 /* Open the use key */
53 if (!NT_SUCCESS(Status)) return Status;
54
55 /* Initialize the attributes and open the key */
57 &KeyName,
59 UserKey,
60 NULL);
62 if (NT_SUCCESS(Status))
63 {
64 /* Set buffer and query the current value */
65 ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
66 Status = ZwQueryValueKey(KeyHandle,
67 &ValueName,
69 ValueBuffer,
70 sizeof(ValueBuffer),
72 if (NT_SUCCESS(Status))
73 {
74 /* Success, is the value the right type? */
75 if (ValueInfo->Type == REG_SZ)
76 {
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))
81 {
82 /* Return the language */
83 *LanguageId = (USHORT)Value;
84 }
85 }
86 else
87 {
88 /* Fail */
90 }
91 }
92
93 /* Close the key */
95 }
96
97 /* Close the user key and return */
98 ZwClose(UserKey);
99 return Status;
100}
101
103NTAPI
105 IN LANGID LanguageId)
106{
108 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"Control Panel\\Desktop");
110 WCHAR ValueBuffer[8];
112 HANDLE UserHandle;
115 PAGED_CODE();
116
117 /* Setup the key name */
119
120 /* Open the use key */
121 Status = RtlOpenCurrentUser(KEY_WRITE, &UserHandle);
122 if (!NT_SUCCESS(Status)) return Status;
123
124 /* Initialize the attributes */
126 &KeyName,
128 UserHandle,
129 NULL);
130
131 /* Open the key */
133 if (NT_SUCCESS(Status))
134 {
135 /* Setup the value name */
136 ValueLength = swprintf(ValueBuffer,
137 L"%04lX",
138 (ULONG)LanguageId);
139
140 /* Set the length for the call and set the value */
141 ValueLength = (ValueLength + 1) * sizeof(WCHAR);
142 Status = ZwSetValueKey(KeyHandle,
143 &ValueName,
144 0,
145 REG_SZ,
146 ValueBuffer,
148
149 /* Close the handle for this key */
151 }
152
153 /* Close the user key and return status */
154 ZwClose(UserHandle);
155 return Status;
156}
157
158/* PUBLIC FUNCTIONS **********************************************************/
159
161NTAPI
163 OUT PLCID DefaultLocaleId)
164{
166 PAGED_CODE();
167
168 /* Enter SEH for probing */
170 {
171 /* Check if we came from user mode */
173 {
174 /* Probe the language ID */
175 ProbeForWriteLangId(DefaultLocaleId);
176 }
177
178 /* Check if we have a user profile */
179 if (UserProfile)
180 {
181 /* Return session wide thread locale */
182 *DefaultLocaleId = MmGetSessionLocaleId();
183 }
184 else
185 {
186 /* Return system locale */
187 *DefaultLocaleId = PsDefaultSystemLocaleId;
188 }
189 }
191 {
192 /* Get exception code */
194 }
195 _SEH2_END;
196
197 /* Return status */
198 return Status;
199}
200
202NTAPI
204 IN LCID DefaultLocaleId)
205{
209 UNICODE_STRING LocaleString;
212 WCHAR ValueBuffer[20];
213 HANDLE UserKey;
215 UCHAR KeyValueBuffer[256];
216 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
217 PAGED_CODE();
218
219 /* Check if we have a profile */
220 if (UserProfile)
221 {
222 /* Open the user's key */
224 if (!NT_SUCCESS(Status)) return Status;
225
226 /* Initialize the registry location */
227 RtlInitUnicodeString(&KeyName, L"Control Panel\\International");
229 }
230 else
231 {
232 /* Initialize the system registry location */
234 L"\\Registry\\Machine\\System\\CurrentControlSet"
235 L"\\Control\\Nls\\Language");
236 RtlInitUnicodeString(&ValueName, L"Default");
237 UserKey = NULL;
238 }
239
240 /* Initialize the object attributes */
242 &KeyName,
244 UserKey,
245 NULL);
246
247 /* Check if we don't have a default locale yet */
248 if (!DefaultLocaleId)
249 {
250 /* Open the key for reading */
252 if (!NT_SUCCESS(Status))
253 {
254 KeyHandle = NULL;
255 goto Cleanup;
256 }
257
258 /* Query the key value */
259 KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
260 Status = ZwQueryValueKey(KeyHandle,
261 &ValueName,
263 KeyValueInformation,
264 sizeof(KeyValueBuffer),
265 &ValueLength);
266 if (!NT_SUCCESS(Status))
267 {
268 goto Cleanup;
269 }
270
271 /* Check if this is a REG_DWORD */
272 if ((KeyValueInformation->Type == REG_DWORD) &&
273 (KeyValueInformation->DataLength == sizeof(ULONG)))
274 {
275 /* It contains the LCID as a DWORD */
276 DefaultLocaleId = *((ULONG*)KeyValueInformation->Data);
277 }
278 /* Otherwise check for a REG_SZ */
279 else if (KeyValueInformation->Type == REG_SZ)
280 {
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;
285
286 /* Convert the hex string to a number */
287 RtlUnicodeStringToInteger(&LocaleString, 16, &DefaultLocaleId);
288 }
289 else
290 {
292 }
293 }
294 else
295 {
296 /* Otherwise, open the key */
298 if (NT_SUCCESS(Status))
299 {
300 /* Check if we had a profile */
301 if (UserProfile)
302 {
303 /* Fill in the buffer */
304 ValueLength = swprintf(ValueBuffer,
305 L"%08lx",
306 (ULONG)DefaultLocaleId);
307 }
308 else
309 {
310 /* Fill in the buffer */
311 ValueLength = swprintf(ValueBuffer,
312 L"%04lx",
313 (ULONG)DefaultLocaleId & 0xFFFF);
314 }
315
316 /* Set the length for the registry call */
317 ValueLength = (ValueLength + 1) * sizeof(WCHAR);
318
319 /* Now write the actual value */
320 Status = ZwSetValueKey(KeyHandle,
321 &ValueName,
322 0,
323 REG_SZ,
324 ValueBuffer,
326 }
327 }
328
329Cleanup:
330
331 /* Close the locale key */
332 if (KeyHandle)
333 {
335 }
336
337 /* Close the user key */
338 if (UserKey)
339 {
340 ObCloseHandle(UserKey, KernelMode);
341 }
342
343 /* Check for success */
344 if (NT_SUCCESS(Status))
345 {
346 /* Check if it was for a user */
347 if (UserProfile)
348 {
349 /* Set the session wide thread locale */
350 MmSetSessionLocaleId(DefaultLocaleId);
351 }
352 else
353 {
354 /* Set system locale */
355 PsDefaultSystemLocaleId = DefaultLocaleId;
356 }
357 }
358
359 /* Return status */
360 return Status;
361}
362
363/*
364 * @implemented
365 */
367NTAPI
369{
371 PAGED_CODE();
372
373 /* Enter SEH for probing */
375 {
376 /* Check if we came from user mode */
378 {
379 /* Probe the Language ID */
380 ProbeForWriteLangId(LanguageId);
381 }
382
383 /* Return it */
384 *LanguageId = PsInstallUILanguageId;
385 }
387 {
388 /* Get exception code */
390 }
391 _SEH2_END;
392
393 /* Return status */
394 return Status;
395}
396
397/*
398 * @implemented
399 */
401NTAPI
403{
405 LANGID SafeLanguageId;
406 PAGED_CODE();
407
408 /* Call the executive helper routine */
409 Status = ExpGetCurrentUserUILanguage(L"MultiUILanguageId", &SafeLanguageId);
410
411 /* Enter SEH for probing */
413 {
414 /* Check if we came from user mode */
416 {
417 /* Probe the Language ID */
418 ProbeForWriteLangId(LanguageId);
419 }
420
421 if (NT_SUCCESS(Status))
422 {
423 /* Success, return the language */
424 *LanguageId = SafeLanguageId;
425 }
426 else
427 {
428 /* Failed, use fallback value */
429 // NOTE: Windows doesn't use PsDefaultUILanguageId.
430 *LanguageId = PsInstallUILanguageId;
431 }
432 }
434 {
435 /* Return exception code */
437 }
438 _SEH2_END;
439
440 /* Return success */
441 return STATUS_SUCCESS;
442}
443
444/*
445 * @implemented
446 */
448NTAPI
450{
452 PAGED_CODE();
453
454 /* Check if the caller specified a language id */
455 if (LanguageId)
456 {
457 /* Set the pending MUI language id */
458 Status = ExpSetCurrentUserUILanguage(L"MUILanguagePending", LanguageId);
459 }
460 else
461 {
462 /* Otherwise get the pending MUI language id */
463 Status = ExpGetCurrentUserUILanguage(L"MUILanguagePending", &LanguageId);
464 if (!NT_SUCCESS(Status))
465 {
466 return Status;
467 }
468
469 /* And apply it as actual */
470 Status = ExpSetCurrentUserUILanguage(L"MultiUILanguageId", LanguageId);
471 }
472
473 return Status;
474}
475
476/* EOF */
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define swprintf
Definition: precomp.h:40
static const WCHAR Cleanup[]
Definition: register.c:80
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
Status
Definition: gdiplustypes.h:25
LONG NTAPI ExSystemExceptionFilter(VOID)
Definition: harderr.c:349
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define REG_SZ
Definition: layer.c:22
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
#define KernelMode
Definition: asm.h:34
#define KeGetPreviousMode()
Definition: ketypes.h:1108
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
NTSYSAPI NTSTATUS NTAPI RtlOpenCurrentUser(_In_ ACCESS_MASK DesiredAccess, _Out_ PHANDLE KeyHandle)
@ KeyValuePartialInformation
Definition: nt_native.h:1182
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToInteger(PUNICODE_STRING String, ULONG Base, PULONG Value)
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
struct _KEY_VALUE_PARTIAL_INFORMATION * PKEY_VALUE_PARTIAL_INFORMATION
#define KEY_WRITE
Definition: nt_native.h:1031
#define KEY_SET_VALUE
Definition: nt_native.h:1017
* PLCID
Definition: ntbasedef.h:509
NTSTATUS NTAPI NtQueryInstallUILanguage(OUT LANGID *LanguageId)
Definition: locale.c:368
LANGID PsDefaultUILanguageId
Definition: locale.c:25
LANGID PsInstallUILanguageId
Definition: locale.c:21
NTSTATUS NTAPI NtQueryDefaultLocale(IN BOOLEAN UserProfile, OUT PLCID DefaultLocaleId)
Definition: locale.c:162
LCID PsDefaultSystemLocaleId
Definition: locale.c:20
NTSTATUS NTAPI ExpSetCurrentUserUILanguage(IN PCWSTR MuiName, IN LANGID LanguageId)
Definition: locale.c:104
NTSTATUS NTAPI NtSetDefaultUILanguage(IN LANGID LanguageId)
Definition: locale.c:449
NTSTATUS NTAPI NtQueryDefaultUILanguage(OUT LANGID *LanguageId)
Definition: locale.c:402
LCID PsDefaultThreadLocaleId
Definition: locale.c:24
NTSTATUS NTAPI ExpGetCurrentUserUILanguage(IN PCWSTR MuiName, OUT LANGID *LanguageId)
Definition: locale.c:31
NTSTATUS NTAPI NtSetDefaultLocale(IN BOOLEAN UserProfile, IN LCID DefaultLocaleId)
Definition: locale.c:203
ULONG NTAPI MmGetSessionLocaleId(VOID)
Definition: session.c:56
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define REG_DWORD
Definition: sdbapi.c:596
#define LANGIDFROMLCID(l)
Definition: nls.h:18
DWORD LCID
Definition: nls.h:13
#define ProbeForWriteLangId(Ptr)
Definition: probe.h:44
#define STATUS_SUCCESS
Definition: shellext.h:65
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
uint16_t * PWSTR
Definition: typedefs.h:56
WORD LANGID
Definition: typedefs.h:81
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180