[HEADERS]
[reactos.git] / reactos / ntoskrnl / ex / locale.c
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 */
20 LCID PsDefaultSystemLocaleId = 0x00000409;
21 LANGID PsInstallUILanguageId = LANGIDFROMLCID(0x00000409);
22
23 /* UI/Thread IDs: Same as system */
24 LANGID PsDefaultUILanguageId = 0x00000409;
25 LCID PsDefaultThreadLocaleId = LANGIDFROMLCID(0x00000409);
26
27 /* PRIVATE FUNCTIONS *********************************************************/
28
29 NTSTATUS
30 NTAPI
31 ExpGetCurrentUserUILanguage(IN PWSTR MuiName,
32 OUT LANGID* LanguageId)
33 {
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;
41 ULONG ValueLength;
42 ULONG Value;
43 HANDLE UserKey;
44 HANDLE KeyHandle;
45 NTSTATUS Status;
46 PAGED_CODE();
47
48 /* Setup the key name */
49 RtlInitUnicodeString(&ValueName, MuiName);
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 */
56 InitializeObjectAttributes(&ObjectAttributes,
57 &KeyName,
58 OBJ_CASE_INSENSITIVE,
59 UserKey,
60 NULL);
61 Status = ZwOpenKey(&KeyHandle, KEY_QUERY_VALUE,&ObjectAttributes);
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,
68 KeyValuePartialInformation,
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 */
89 Status = STATUS_UNSUCCESSFUL;
90 }
91
92 /* Close the key */
93 ZwClose(KeyHandle);
94 }
95 }
96
97 /* Close the user key and return */
98 ZwClose(UserKey);
99 return Status;
100 }
101
102 NTSTATUS
103 NTAPI
104 ExpSetCurrentUserUILanguage(IN PWSTR MuiName,
105 IN LANGID LanguageId)
106 {
107 OBJECT_ATTRIBUTES ObjectAttributes;
108 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"Control Panel\\Desktop");
109 UNICODE_STRING ValueName;
110 WCHAR ValueBuffer[8];
111 ULONG ValueLength;
112 HANDLE UserHandle;
113 HANDLE KeyHandle;
114 NTSTATUS Status;
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 */
125 InitializeObjectAttributes(&ObjectAttributes,
126 &KeyName,
127 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
128 UserHandle,
129 NULL);
130
131 /* Open the key */
132 Status = ZwOpenKey(&KeyHandle, KEY_SET_VALUE, &ObjectAttributes);
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 */
150 ZwClose(KeyHandle);
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
162 NtQueryDefaultLocale(IN BOOLEAN UserProfile,
163 OUT PLCID DefaultLocaleId)
164 {
165 NTSTATUS Status = STATUS_SUCCESS;
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 thread locale */
182 *DefaultLocaleId = PsDefaultThreadLocaleId;
183 }
184 else
185 {
186 /* Return system locale */
187 *DefaultLocaleId = PsDefaultSystemLocaleId;
188 }
189 }
190 _SEH2_EXCEPT(ExSystemExceptionFilter())
191 {
192 /* Get exception code */
193 Status = _SEH2_GetExceptionCode();
194 }
195 _SEH2_END;
196
197 /* Return status */
198 return Status;
199 }
200
201 NTSTATUS
202 NTAPI
203 NtSetDefaultLocale(IN BOOLEAN UserProfile,
204 IN LCID DefaultLocaleId)
205 {
206 OBJECT_ATTRIBUTES ObjectAttributes;
207 UNICODE_STRING KeyName;
208 UNICODE_STRING ValueName;
209 HANDLE KeyHandle;
210 ULONG ValueLength;
211 WCHAR ValueBuffer[20];
212 HANDLE UserKey = NULL;
213 NTSTATUS Status;
214 PAGED_CODE();
215
216 /* Check if we have a profile */
217 if (UserProfile)
218 {
219 /* Open the user's key */
220 Status = RtlOpenCurrentUser(KEY_WRITE, &UserKey);
221 if (!NT_SUCCESS(Status)) return(Status);
222
223 /* Initialize the registry location */
224 RtlInitUnicodeString(&KeyName, L"Control Panel\\International");
225 RtlInitUnicodeString(&ValueName, L"Locale");
226 }
227 else
228 {
229 /* Initialize the system registry location */
230 RtlInitUnicodeString(&KeyName,
231 L"\\Registry\\Machine\\System\\CurrentControlSet"
232 L"\\Control\\Nls\\Language");
233 RtlInitUnicodeString(&ValueName, L"Default");
234 }
235
236 /* Initailize the object attributes */
237 InitializeObjectAttributes(&ObjectAttributes,
238 &KeyName,
239 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
240 UserKey,
241 NULL);
242
243 /* Check if we don' thave a default locale yet */
244 if (!DefaultLocaleId)
245 {
246 DPRINT1("TODO\n");
247 Status = STATUS_SUCCESS;
248 ASSERT(FALSE);
249 }
250 else
251 {
252 /* Otherwise, open the key */
253 Status = ZwOpenKey(&KeyHandle, KEY_SET_VALUE, &ObjectAttributes);
254 if (NT_SUCCESS(Status))
255 {
256 /* Check if we had a profile */
257 if (UserProfile)
258 {
259 /* Fill in the buffer */
260 ValueLength = swprintf(ValueBuffer,
261 L"%08lx",
262 (ULONG)DefaultLocaleId);
263 }
264 else
265 {
266 /* Fill in the buffer */
267 ValueLength = swprintf(ValueBuffer,
268 L"%04lx",
269 (ULONG)DefaultLocaleId & 0xFFFF);
270 }
271
272 /* Set the length for the registry call */
273 ValueLength = (ValueLength + 1) * sizeof(WCHAR);
274
275 /* Now write the actual value */
276 Status = ZwSetValueKey(KeyHandle,
277 &ValueName,
278 0,
279 REG_SZ,
280 ValueBuffer,
281 ValueLength);
282
283 /* And close the key */
284 ZwClose(KeyHandle);
285 }
286 }
287
288 /* Close the user key */
289 ZwClose(UserKey);
290
291 /* Check for success */
292 if (NT_SUCCESS(Status))
293 {
294 /* Check if it was for a user */
295 if (UserProfile)
296 {
297 /* Set thread locale */
298 PsDefaultThreadLocaleId = DefaultLocaleId;
299 }
300 else
301 {
302 /* Set system locale */
303 PsDefaultSystemLocaleId = DefaultLocaleId;
304 }
305 }
306
307 /* Return status */
308 return Status;
309 }
310
311 /*
312 * @implemented
313 */
314 NTSTATUS
315 NTAPI
316 NtQueryInstallUILanguage(OUT LANGID* LanguageId)
317 {
318 NTSTATUS Status = STATUS_SUCCESS;
319 PAGED_CODE();
320
321 /* Enter SEH for probing */
322 _SEH2_TRY
323 {
324 /* Check if we came from user mode */
325 if (KeGetPreviousMode() != KernelMode)
326 {
327 /* Probe the Language ID */
328 ProbeForWriteLangid(LanguageId);
329 }
330
331 /* Return it */
332 *LanguageId = PsInstallUILanguageId;
333 }
334 _SEH2_EXCEPT(ExSystemExceptionFilter())
335 {
336 /* Get exception code */
337 Status = _SEH2_GetExceptionCode();
338 }
339 _SEH2_END;
340
341 /* Return status */
342 return Status;
343 }
344
345 /*
346 * @implemented
347 */
348 NTSTATUS
349 NTAPI
350 NtQueryDefaultUILanguage(OUT LANGID* LanguageId)
351 {
352 NTSTATUS Status = STATUS_SUCCESS;
353 PAGED_CODE();
354
355 /* Enter SEH for probing */
356 _SEH2_TRY
357 {
358 /* Check if we came from user mode */
359 if (KeGetPreviousMode() != KernelMode)
360 {
361 /* Probe the Language ID */
362 ProbeForWriteLangid(LanguageId);
363 }
364
365 /* Call the executive helper routine */
366 Status = ExpGetCurrentUserUILanguage(L"MultiUILanguageId", LanguageId);
367 if (NT_SUCCESS(Status))
368 {
369 /* Success, return the language */
370 *LanguageId = PsInstallUILanguageId;
371 }
372 }
373 _SEH2_EXCEPT(ExSystemExceptionFilter())
374 {
375 /* Get exception code */
376 Status = _SEH2_GetExceptionCode();
377 }
378 _SEH2_END;
379
380 /* Return status */
381 return Status;
382 }
383
384 /*
385 * @implemented
386 */
387 NTSTATUS
388 NTAPI
389 NtSetDefaultUILanguage(IN LANGID LanguageId)
390 {
391 PAGED_CODE();
392
393 /* Check if we don't have a default yet */
394 if (!LanguageId)
395 {
396 /* FIXME */
397 DPRINT1("TODO\n");
398 ASSERT(FALSE);
399 }
400
401 /* Otherwise, call the internal routine */
402 return ExpSetCurrentUserUILanguage(L"MUILanguagePending", LanguageId);
403 }
404
405 /* EOF */