ReactOS  0.4.13-dev-455-g28ed234
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 
30 NTAPI
32  OUT LANGID* LanguageId)
33 {
34  UCHAR ValueBuffer[256];
38  RTL_CONSTANT_STRING(L"Control Panel\\Desktop");
40  UNICODE_STRING ValueString;
42  ULONG Value;
43  HANDLE UserKey;
46  PAGED_CODE();
47 
48  /* Setup the key name */
50 
51  /* Open the use key */
52  Status = RtlOpenCurrentUser(KEY_READ, &UserKey);
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),
71  &ValueLength);
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 
102 NTSTATUS
103 NTAPI
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 */
118  RtlInitUnicodeString(&ValueName, MuiName);
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,
147  ValueLength);
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 
160 NTSTATUS
161 NTAPI
163  OUT PLCID DefaultLocaleId)
164 {
166  PAGED_CODE();
167 
168  /* Enter SEH for probing */
169  _SEH2_TRY
170  {
171  /* Check if we came from user mode */
172  if (KeGetPreviousMode() != KernelMode)
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 
201 NTSTATUS
202 NTAPI
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 */
223  Status = RtlOpenCurrentUser(KEY_WRITE, &UserKey);
224  if (!NT_SUCCESS(Status)) return Status;
225 
226  /* Initialize the registry location */
227  RtlInitUnicodeString(&KeyName, L"Control Panel\\International");
228  RtlInitUnicodeString(&ValueName, L"Locale");
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,
325  ValueLength);
326  }
327  }
328 
329 Cleanup:
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  */
366 NTSTATUS
367 NTAPI
369 {
371  PAGED_CODE();
372 
373  /* Enter SEH for probing */
374  _SEH2_TRY
375  {
376  /* Check if we came from user mode */
377  if (KeGetPreviousMode() != KernelMode)
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  */
400 NTSTATUS
401 NTAPI
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 */
412  _SEH2_TRY
413  {
414  /* Check if we came from user mode */
415  if (KeGetPreviousMode() != KernelMode)
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  *LanguageId = PsInstallUILanguageId;
430  }
431  }
433  {
434  /* Return exception code */
436  }
437  _SEH2_END;
438 
439  /* Return success */
440  return STATUS_SUCCESS;
441 }
442 
443 /*
444  * @implemented
445  */
446 NTSTATUS
447 NTAPI
449 {
451  PAGED_CODE();
452 
453  /* Check if the caller specified a language id */
454  if (LanguageId)
455  {
456  /* Set the pending MUI language id */
457  Status = ExpSetCurrentUserUILanguage(L"MUILanguagePending", LanguageId);
458  }
459  else
460  {
461  /* Otherwise get the pending MUI language id */
462  Status = ExpGetCurrentUserUILanguage(L"MUILanguagePending", &LanguageId);
463  if (!NT_SUCCESS(Status))
464  {
465  return Status;
466  }
467 
468  /* And apply it as actual */
469  Status = ExpSetCurrentUserUILanguage(L"MultiUILanguageId", LanguageId);
470  }
471 
472  return Status;
473 }
474 
475 /* EOF */
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2327
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
LANGID PsDefaultUILanguageId
Definition: locale.c:24
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING KeyName
Definition: ndis.h:4711
#define IN
Definition: typedefs.h:38
#define KEY_SET_VALUE
Definition: nt_native.h:1017
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4711
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define KEY_READ
Definition: nt_native.h:1023
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:54
#define KeGetPreviousMode()
Definition: ketypes.h:1081
LONG NTSTATUS
Definition: precomp.h:26
LCID PsDefaultSystemLocaleId
Definition: locale.c:20
DWORD LCID
Definition: nls.h:13
WORD LANGID
Definition: typedefs.h:79
uint16_t * PWCHAR
Definition: typedefs.h:54
LCID PsDefaultThreadLocaleId
Definition: locale.c:25
LANGID PsInstallUILanguageId
Definition: locale.c:21
#define PAGED_CODE()
Definition: video.h:57
_SEH2_TRY
Definition: create.c:4250
_In_ PUNICODE_STRING ValueName
Definition: cmfuncs.h:264
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
ULONG NTAPI MmGetSessionLocaleId(VOID)
Definition: session.c:57
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS NTAPI ExpSetCurrentUserUILanguage(IN PWSTR MuiName, IN LANGID LanguageId)
Definition: locale.c:104
#define KEY_WRITE
Definition: nt_native.h:1031
#define ProbeForWriteLangid(Ptr)
Definition: probe.h:44
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
struct _KEY_VALUE_PARTIAL_INFORMATION * PKEY_VALUE_PARTIAL_INFORMATION
NTSTATUS NTAPI NtSetDefaultUILanguage(IN LANGID LanguageId)
Definition: locale.c:448
NTSTATUS NTAPI NtSetDefaultLocale(IN BOOLEAN UserProfile, IN LCID DefaultLocaleId)
Definition: locale.c:203
NTSTATUS NTAPI NtQueryInstallUILanguage(OUT LANGID *LanguageId)
Definition: locale.c:368
#define swprintf(buf, format,...)
Definition: sprintf.c:56
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSTATUS NTAPI NtQueryDefaultUILanguage(OUT LANGID *LanguageId)
Definition: locale.c:402
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
unsigned char UCHAR
Definition: xmlstorage.h:181
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3376
static const WCHAR L[]
Definition: oid.c:1250
_In_ GUID _In_ PVOID _In_ ULONG ValueLength
Definition: hubbusif.h:311
#define LANGIDFROMLCID(l)
Definition: nls.h:18
NTSYSAPI NTSTATUS NTAPI RtlOpenCurrentUser(_In_ ACCESS_MASK DesiredAccess, _Out_ PHANDLE KeyHandle)
static const WCHAR Cleanup[]
Definition: register.c:80
NTSTATUS NTAPI ExpGetCurrentUserUILanguage(IN PWSTR MuiName, OUT LANGID *LanguageId)
Definition: locale.c:31
Status
Definition: gdiplustypes.h:24
_SEH2_END
Definition: create.c:4424
LONG NTAPI ExSystemExceptionFilter(VOID)
Definition: harderr.c:351
unsigned short USHORT
Definition: pedump.c:61
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
NTSTATUS NTAPI NtQueryDefaultLocale(IN BOOLEAN UserProfile, OUT PLCID DefaultLocaleId)
Definition: locale.c:162
#define OUT
Definition: typedefs.h:39
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToInteger(PUNICODE_STRING String, ULONG Base, PULONG Value)
* PLCID
Definition: ntbasedef.h:516
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
return STATUS_SUCCESS
Definition: btrfs.c:2777
#define REG_DWORD
Definition: sdbapi.c:596
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define REG_SZ
Definition: layer.c:22