Standardize comment headers. Patch by Trevor McCort
[reactos.git] / reactos / ntoskrnl / ps / locale.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/locale.c
6 * PURPOSE: Locale support
7 *
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14
15 #define NDEBUG
16 #include <internal/debug.h>
17
18
19 /* GLOBALS *******************************************************************/
20
21 /*
22 * Default setting: LANG_NEUTRAL, SUBLANG_NEUTRAL, SORT_DEFAULT
23 */
24 LCID PsDefaultThreadLocaleId = 0;
25 LCID PsDefaultSystemLocaleId = 0;
26 BOOL PsDefaultThreadLocaleInitialized = FALSE;
27
28 static LANGID PsInstallUILanguageId = 0;
29
30 #define VALUE_BUFFER_SIZE 256
31
32 /* FUNCTIONS *****************************************************************/
33
34 /*
35 * FUNCTION:
36 * Initializes the default locale.
37 * Reads default locale from registry, if available
38 * ARGUMENTS:
39 * None.
40 * Returns:
41 * None.
42 */
43 VOID INIT_FUNCTION
44 PiInitDefaultLocale(VOID)
45 {
46 OBJECT_ATTRIBUTES ObjectAttributes;
47 UNICODE_STRING KeyName;
48 UNICODE_STRING ValueName;
49 HANDLE KeyHandle;
50 ULONG ValueLength;
51 UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
52 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
53 UNICODE_STRING ValueString;
54 ULONG Value;
55 NTSTATUS Status;
56
57 ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
58
59 RtlRosInitUnicodeStringFromLiteral(&KeyName,
60 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language");
61
62 InitializeObjectAttributes(&ObjectAttributes,
63 &KeyName,
64 OBJ_CASE_INSENSITIVE,
65 NULL,
66 NULL);
67 Status = ZwOpenKey(&KeyHandle,
68 KEY_QUERY_VALUE,
69 &ObjectAttributes);
70 if (NT_SUCCESS(Status))
71 {
72 /* Read system locale */
73 RtlRosInitUnicodeStringFromLiteral(&ValueName,
74 L"Default");
75 Status = ZwQueryValueKey(KeyHandle,
76 &ValueName,
77 KeyValuePartialInformation,
78 ValueBuffer,
79 VALUE_BUFFER_SIZE,
80 &ValueLength);
81 if ((NT_SUCCESS(Status)) && (ValueInfo->Type == REG_SZ))
82 {
83 ValueString.Length = ValueInfo->DataLength;
84 ValueString.MaximumLength = ValueInfo->DataLength;
85 ValueString.Buffer = (PWSTR)ValueInfo->Data;
86
87 Status = RtlUnicodeStringToInteger(&ValueString,
88 16,
89 &Value);
90 if (NT_SUCCESS(Status))
91 {
92 DPRINT("System locale: %08lx\n", Value);
93 PsDefaultSystemLocaleId = (LCID)Value;
94 }
95 }
96
97 /* Read install language id */
98 RtlRosInitUnicodeStringFromLiteral(&ValueName,
99 L"InstallLanguage");
100 Status = ZwQueryValueKey(KeyHandle,
101 &ValueName,
102 KeyValuePartialInformation,
103 ValueBuffer,
104 VALUE_BUFFER_SIZE,
105 &ValueLength);
106 if ((NT_SUCCESS(Status)) && (ValueInfo->Type == REG_SZ))
107 {
108 ValueString.Length = ValueInfo->DataLength;
109 ValueString.MaximumLength = ValueInfo->DataLength;
110 ValueString.Buffer = (PWSTR)ValueInfo->Data;
111
112 Status = RtlUnicodeStringToInteger(&ValueString,
113 16,
114 &Value);
115 if (NT_SUCCESS(Status))
116 {
117 DPRINT("Install language id: %04lx\n", Value);
118 PsInstallUILanguageId = (LANGID)Value;
119 }
120 }
121
122 ZwClose(KeyHandle);
123 }
124 }
125
126
127 /*
128 * FUNCTION:
129 * Initializes the default thread locale.
130 * Reads default locale from registry, if available
131 * ARGUMENTS:
132 * None.
133 * Returns:
134 * None.
135 */
136 VOID STDCALL
137 PiInitThreadLocale(VOID)
138 {
139 OBJECT_ATTRIBUTES ObjectAttributes;
140 UNICODE_STRING KeyName;
141 UNICODE_STRING ValueName;
142 HANDLE KeyHandle;
143 ULONG ValueLength;
144 UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
145 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
146 UNICODE_STRING ValueString;
147 ULONG LocaleValue;
148 NTSTATUS Status;
149
150 ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
151
152 /* read default thread locale */
153 RtlRosInitUnicodeStringFromLiteral(&KeyName,
154 L"\\Registry\\User\\.Default\\Control Panel\\International");
155 RtlRosInitUnicodeStringFromLiteral(&ValueName,
156 L"Locale");
157
158 InitializeObjectAttributes(&ObjectAttributes,
159 &KeyName,
160 OBJ_CASE_INSENSITIVE,
161 NULL,
162 NULL);
163 Status = ZwOpenKey(&KeyHandle,
164 KEY_QUERY_VALUE,
165 &ObjectAttributes);
166 if (NT_SUCCESS(Status))
167 {
168 Status = ZwQueryValueKey(KeyHandle,
169 &ValueName,
170 KeyValuePartialInformation,
171 ValueBuffer,
172 VALUE_BUFFER_SIZE,
173 &ValueLength);
174 if ((NT_SUCCESS(Status)) && (ValueInfo->Type == REG_SZ))
175 {
176 ValueString.Length = ValueInfo->DataLength;
177 ValueString.MaximumLength = ValueInfo->DataLength;
178 ValueString.Buffer = (PWSTR)ValueInfo->Data;
179
180 Status = RtlUnicodeStringToInteger(&ValueString,
181 16,
182 &LocaleValue);
183 if (NT_SUCCESS(Status))
184 {
185 DPRINT("Thread locale: %08lu\n", LocaleValue);
186 PsDefaultThreadLocaleId = (LCID)LocaleValue;
187 }
188 }
189 ZwClose(KeyHandle);
190 }
191
192 PsDefaultThreadLocaleInitialized = TRUE;
193 }
194
195
196 /*
197 * FUNCTION:
198 * Returns the default locale.
199 * ARGUMENTS:
200 * UserProfile = If TRUE then the locale for this thread is returned,
201 * otherwise the locale for the system is returned.
202 * DefaultLocaleId = Points to a variable that receives the locale id.
203 * Returns:
204 * Status.
205 */
206 NTSTATUS STDCALL
207 NtQueryDefaultLocale(IN BOOLEAN UserProfile,
208 OUT PLCID DefaultLocaleId)
209 {
210 if (DefaultLocaleId == NULL)
211 return STATUS_UNSUCCESSFUL;
212
213 if (UserProfile)
214 {
215 if (!PsDefaultThreadLocaleInitialized)
216 {
217 PiInitThreadLocale();
218 }
219
220 /* set thread locale */
221 *DefaultLocaleId = PsDefaultThreadLocaleId;
222 }
223 else
224 {
225 /* set system locale */
226 *DefaultLocaleId = PsDefaultSystemLocaleId;
227 }
228
229 return STATUS_SUCCESS;
230 }
231
232
233 /*
234 * FUNCTION:
235 * Sets the default locale.
236 * ARGUMENTS:
237 * ThreadOrSystem = If TRUE then the locale for this thread is set,
238 * otherwise the locale for the system is set.
239 * DefaultLocaleId = The locale id to be set.
240 * Returns:
241 * Status.
242 */
243 NTSTATUS STDCALL
244 NtSetDefaultLocale(IN BOOLEAN UserProfile,
245 IN LCID DefaultLocaleId)
246 {
247 OBJECT_ATTRIBUTES ObjectAttributes;
248 UNICODE_STRING KeyName;
249 UNICODE_STRING ValueName;
250 HANDLE KeyHandle;
251 ULONG ValueLength;
252 WCHAR ValueBuffer[20];
253 HANDLE UserKey = NULL;
254 NTSTATUS Status;
255
256 if (UserProfile)
257 {
258 /* thread locale */
259 Status = RtlOpenCurrentUser(KEY_WRITE,
260 &UserKey);
261 if (!NT_SUCCESS(Status))
262 return(Status);
263 RtlRosInitUnicodeStringFromLiteral(&KeyName,
264 L"Control Panel\\International");
265 RtlRosInitUnicodeStringFromLiteral(&ValueName,
266 L"Locale");
267 }
268 else
269 {
270 /* system locale */
271 RtlRosInitUnicodeStringFromLiteral(&KeyName,
272 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language");
273 RtlRosInitUnicodeStringFromLiteral(&ValueName,
274 L"Default");
275 }
276
277 InitializeObjectAttributes(&ObjectAttributes,
278 &KeyName,
279 OBJ_CASE_INSENSITIVE,
280 UserKey,
281 NULL);
282 Status = ZwOpenKey(&KeyHandle,
283 KEY_SET_VALUE,
284 &ObjectAttributes);
285 if (!NT_SUCCESS(Status))
286 {
287 if (UserKey != NULL)
288 {
289 ZwClose(UserKey);
290 }
291 return(Status);
292 }
293
294 if (UserProfile)
295 {
296 ValueLength = swprintf(ValueBuffer,
297 L"%08lx",
298 (ULONG)DefaultLocaleId);
299 }
300 else
301 {
302 ValueLength = swprintf(ValueBuffer,
303 L"%04lx",
304 (ULONG)DefaultLocaleId & 0xFFFF);
305 }
306 ValueLength = (ValueLength + 1) * sizeof(WCHAR);
307
308 Status = ZwSetValueKey(KeyHandle,
309 &ValueName,
310 0,
311 REG_SZ,
312 ValueBuffer,
313 ValueLength);
314
315 ZwClose(KeyHandle);
316 if (UserKey != NULL)
317 {
318 ZwClose(UserKey);
319 }
320
321 if (!NT_SUCCESS(Status))
322 {
323 return(Status);
324 }
325
326 if (UserProfile)
327 {
328 /* set thread locale */
329 DPRINT("Thread locale: %08lu\n", DefaultLocaleId);
330 PsDefaultThreadLocaleId = DefaultLocaleId;
331 PsDefaultThreadLocaleInitialized = TRUE;
332 }
333 else
334 {
335 /* set system locale */
336 DPRINT("System locale: %08lu\n", DefaultLocaleId);
337 PsDefaultSystemLocaleId = DefaultLocaleId;
338 }
339
340 return STATUS_SUCCESS;
341 }
342
343
344 /*
345 * @implemented
346 */
347 NTSTATUS STDCALL
348 NtQueryDefaultUILanguage(OUT PLANGID LanguageId)
349 {
350 UCHAR ValueBuffer[VALUE_BUFFER_SIZE];
351 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
352 OBJECT_ATTRIBUTES ObjectAttributes;
353 UNICODE_STRING KeyName;
354 UNICODE_STRING ValueName;
355 UNICODE_STRING ValueString;
356 ULONG ValueLength;
357 ULONG Value;
358 HANDLE UserKey;
359 HANDLE KeyHandle;
360 NTSTATUS Status;
361
362 Status = RtlOpenCurrentUser(KEY_READ,
363 &UserKey);
364 if (!NT_SUCCESS(Status))
365 {
366 *LanguageId = PsInstallUILanguageId;
367 return STATUS_SUCCESS;
368 }
369
370 RtlRosInitUnicodeStringFromLiteral(&KeyName,
371 L"Control Panel\\International");
372 RtlRosInitUnicodeStringFromLiteral(&ValueName,
373 L"MultiUILanguageId");
374
375 InitializeObjectAttributes(&ObjectAttributes,
376 &KeyName,
377 OBJ_CASE_INSENSITIVE,
378 UserKey,
379 NULL);
380 Status = ZwOpenKey(&KeyHandle,
381 KEY_QUERY_VALUE,
382 &ObjectAttributes);
383 if (!NT_SUCCESS(Status))
384 {
385 *LanguageId = PsInstallUILanguageId;
386 return STATUS_SUCCESS;
387 }
388
389 ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
390
391 Status = ZwQueryValueKey(KeyHandle,
392 &ValueName,
393 KeyValuePartialInformation,
394 ValueBuffer,
395 VALUE_BUFFER_SIZE,
396 &ValueLength);
397
398 ZwClose(KeyHandle);
399 ZwClose(UserKey);
400
401 if (!NT_SUCCESS(Status) || ValueInfo->Type != REG_SZ)
402 {
403 *LanguageId = PsInstallUILanguageId;
404 return STATUS_SUCCESS;
405 }
406
407 ValueString.Length = ValueInfo->DataLength;
408 ValueString.MaximumLength = ValueInfo->DataLength;
409 ValueString.Buffer = (PWSTR)ValueInfo->Data;
410
411 Status = RtlUnicodeStringToInteger(&ValueString,
412 16,
413 &Value);
414 if (!NT_SUCCESS(Status))
415 {
416 *LanguageId = PsInstallUILanguageId;
417 return STATUS_SUCCESS;
418 }
419
420 DPRINT("Default language id: %04lx\n", Value);
421
422 *LanguageId = Value;
423
424 return STATUS_SUCCESS;
425 }
426
427
428 /*
429 * @implemented
430 */
431 NTSTATUS STDCALL
432 NtQueryInstallUILanguage(OUT PLANGID LanguageId)
433 {
434 *LanguageId = PsInstallUILanguageId;
435
436 return STATUS_SUCCESS;
437 }
438
439
440 /*
441 * @implemented
442 */
443 NTSTATUS STDCALL
444 NtSetDefaultUILanguage(IN LANGID LanguageId)
445 {
446 OBJECT_ATTRIBUTES ObjectAttributes;
447 UNICODE_STRING KeyName;
448 UNICODE_STRING ValueName;
449 WCHAR ValueBuffer[8];
450 ULONG ValueLength;
451 HANDLE UserHandle;
452 HANDLE KeyHandle;
453 NTSTATUS Status;
454
455 Status = RtlOpenCurrentUser(KEY_WRITE,
456 &UserHandle);
457 if (!NT_SUCCESS(Status))
458 {
459 return Status;
460 }
461
462 RtlRosInitUnicodeStringFromLiteral(&KeyName,
463 L"Control Panel\\Desktop");
464 RtlRosInitUnicodeStringFromLiteral(&ValueName,
465 L"MultiUILanguageId");
466
467 InitializeObjectAttributes(&ObjectAttributes,
468 &KeyName,
469 OBJ_CASE_INSENSITIVE,
470 UserHandle,
471 NULL);
472
473 Status = ZwOpenKey(&KeyHandle,
474 KEY_SET_VALUE,
475 &ObjectAttributes);
476 if (!NT_SUCCESS(Status))
477 {
478 ZwClose(UserHandle);
479 return Status;
480 }
481
482 ValueLength = swprintf(ValueBuffer,
483 L"%04lX",
484 (ULONG)LanguageId);
485 ValueLength = (ValueLength + 1) * sizeof(WCHAR);
486
487 Status = ZwSetValueKey(KeyHandle,
488 &ValueName,
489 0,
490 REG_SZ,
491 ValueBuffer,
492 ValueLength);
493
494 ZwClose(KeyHandle);
495 ZwClose(UserHandle);
496
497 return Status;
498 }
499
500 /* EOF */