- Added ACP, OEMCP and MACCP keys to registry
[reactos.git] / reactos / base / setup / usetup / settings.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS text-mode setup
21 * FILE: subsys/system/usetup/settings.c
22 * PURPOSE: Device settings support functions
23 * PROGRAMMER: Eric Kohl
24 */
25
26 /* INCLUDES *****************************************************************/
27
28 #include "usetup.h"
29
30 #define NDEBUG
31 #include <debug.h>
32
33 /* FUNCTIONS ****************************************************************/
34
35 static BOOLEAN
36 GetComputerIdentifier(PWSTR Identifier,
37 ULONG IdentifierLength)
38 {
39 OBJECT_ATTRIBUTES ObjectAttributes;
40 UNICODE_STRING KeyName;
41 LPCWSTR ComputerIdentifier;
42 HANDLE ProcessorsKey;
43 PKEY_FULL_INFORMATION pFullInfo;
44 ULONG Size, SizeNeeded;
45 NTSTATUS Status;
46
47 DPRINT("GetComputerIdentifier() called\n");
48
49 Size = sizeof(KEY_FULL_INFORMATION);
50 pFullInfo = (PKEY_FULL_INFORMATION)RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
51 if (!pFullInfo)
52 {
53 DPRINT("RtlAllocateHeap() failed\n");
54 return FALSE;
55 }
56
57 /* Open the processors key */
58 RtlInitUnicodeString(&KeyName,
59 L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor");
60 InitializeObjectAttributes(&ObjectAttributes,
61 &KeyName,
62 OBJ_CASE_INSENSITIVE,
63 NULL,
64 NULL);
65 Status = NtOpenKey(&ProcessorsKey,
66 KEY_QUERY_VALUE ,
67 &ObjectAttributes);
68 if (!NT_SUCCESS(Status))
69 {
70 DPRINT("NtOpenKey() failed (Status 0x%lx)\n", Status);
71 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
72 return FALSE;
73 }
74
75 /* Get number of subkeys */
76 Status = NtQueryKey(
77 ProcessorsKey,
78 KeyFullInformation,
79 pFullInfo,
80 Size,
81 &Size);
82 NtClose(ProcessorsKey);
83 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
84 {
85 DPRINT("NtQueryKey() failed (Status 0x%lx)\n", Status);
86 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
87 return FALSE;
88 }
89
90 /* Find computer identifier */
91 if (pFullInfo->SubKeys == 0)
92 {
93 /* Something strange happened. No processor detected */
94 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
95 return FALSE;
96 }
97
98 if (pFullInfo->SubKeys == 1)
99 {
100 /* Computer is mono-CPU */
101 ComputerIdentifier = L"PC UP";
102 }
103 else
104 {
105 /* Computer is multi-CPUs */
106 ComputerIdentifier = L"PC MP";
107 }
108 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
109
110 /* Copy computer identifier to return buffer */
111 SizeNeeded = (wcslen(ComputerIdentifier) + 1) * sizeof(WCHAR);
112 if (SizeNeeded > IdentifierLength)
113 return FALSE;
114 RtlCopyMemory(Identifier, ComputerIdentifier, SizeNeeded);
115 return TRUE;
116 }
117
118
119 PGENERIC_LIST
120 CreateComputerTypeList(HINF InfFile)
121 {
122 CHAR Buffer[128];
123 PGENERIC_LIST List;
124 INFCONTEXT Context;
125 PWCHAR KeyName;
126 PWCHAR KeyValue;
127 PWCHAR UserData;
128 WCHAR ComputerIdentifier[128];
129 WCHAR ComputerKey[32];
130
131 /* Get the computer identification */
132 if (!GetComputerIdentifier(ComputerIdentifier, 128))
133 {
134 ComputerIdentifier[0] = 0;
135 }
136
137 DPRINT("Computer identifier: '%S'\n", ComputerIdentifier);
138
139 /* Search for matching device identifier */
140 if (!SetupFindFirstLineW(InfFile, L"Map.Computer", NULL, &Context))
141 {
142 /* FIXME: error message */
143 return NULL;
144 }
145
146 do
147 {
148 if (!INF_GetDataField(&Context, 1, &KeyValue))
149 {
150 /* FIXME: Handle error! */
151 DPRINT("INF_GetDataField() failed\n");
152 return NULL;
153 }
154
155 DPRINT("KeyValue: %S\n", KeyValue);
156 if (wcsstr(ComputerIdentifier, KeyValue))
157 {
158 if (!INF_GetDataField(&Context, 0, &KeyName))
159 {
160 /* FIXME: Handle error! */
161 DPRINT("INF_GetDataField() failed\n");
162 return NULL;
163 }
164
165 DPRINT("Computer key: %S\n", KeyName);
166 wcscpy(ComputerKey, KeyName);
167 }
168 }
169 while (SetupFindNextLine(&Context, &Context));
170
171 List = CreateGenericList();
172 if (List == NULL)
173 return NULL;
174
175 if (!SetupFindFirstLineW (InfFile, L"Computer", NULL, &Context))
176 {
177 DestroyGenericList(List, FALSE);
178 return NULL;
179 }
180
181 do
182 {
183 if (!INF_GetData (&Context, &KeyName, &KeyValue))
184 {
185 /* FIXME: Handle error! */
186 DPRINT("INF_GetData() failed\n");
187 break;
188 }
189
190 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
191 0,
192 (wcslen(KeyName) + 1) * sizeof(WCHAR));
193 if (UserData == NULL)
194 {
195 /* FIXME: Handle error! */
196 }
197
198 wcscpy(UserData, KeyName);
199
200 sprintf(Buffer, "%S", KeyValue);
201 AppendGenericListEntry(List, Buffer, UserData,
202 _wcsicmp(KeyName, ComputerKey) ? FALSE : TRUE);
203 }
204 while (SetupFindNextLine(&Context, &Context));
205
206 return List;
207 }
208
209
210 static BOOLEAN
211 GetDisplayIdentifier(PWSTR Identifier,
212 ULONG IdentifierLength)
213 {
214 OBJECT_ATTRIBUTES ObjectAttributes;
215 UNICODE_STRING KeyName;
216 WCHAR Buffer[32];
217 HANDLE BusKey;
218 HANDLE BusInstanceKey;
219 HANDLE ControllerKey;
220 HANDLE ControllerInstanceKey;
221 ULONG BusInstance;
222 ULONG ControllerInstance;
223 ULONG BufferLength;
224 ULONG ReturnedLength;
225 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
226 NTSTATUS Status;
227
228 DPRINT("GetDisplayIdentifier() called\n");
229
230 /* Open the bus key */
231 RtlInitUnicodeString(&KeyName,
232 L"\\Registry\\Machine\\HARDWARE\\Description\\System\\MultifunctionAdapter");
233 InitializeObjectAttributes(&ObjectAttributes,
234 &KeyName,
235 OBJ_CASE_INSENSITIVE,
236 NULL,
237 NULL);
238 Status = NtOpenKey(&BusKey,
239 KEY_ALL_ACCESS,
240 &ObjectAttributes);
241 if (!NT_SUCCESS(Status))
242 {
243 DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
244 return FALSE;
245 }
246
247 BusInstance = 0;
248 while (TRUE)
249 {
250 swprintf(Buffer, L"%lu", BusInstance);
251 RtlInitUnicodeString(&KeyName,
252 Buffer);
253 InitializeObjectAttributes(&ObjectAttributes,
254 &KeyName,
255 OBJ_CASE_INSENSITIVE,
256 BusKey,
257 NULL);
258 Status = NtOpenKey(&BusInstanceKey,
259 KEY_ALL_ACCESS,
260 &ObjectAttributes);
261 if (!NT_SUCCESS(Status))
262 {
263 DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
264 NtClose(BusKey);
265 return FALSE;
266 }
267
268 /* Open the controller type key */
269 RtlInitUnicodeString(&KeyName,
270 L"DisplayController");
271 InitializeObjectAttributes(&ObjectAttributes,
272 &KeyName,
273 OBJ_CASE_INSENSITIVE,
274 BusInstanceKey,
275 NULL);
276 Status = NtOpenKey(&ControllerKey,
277 KEY_ALL_ACCESS,
278 &ObjectAttributes);
279 if (NT_SUCCESS(Status))
280 {
281 ControllerInstance = 0;
282 while (TRUE)
283 {
284 /* Open the pointer controller instance key */
285 swprintf(Buffer, L"%lu", ControllerInstance);
286 RtlInitUnicodeString(&KeyName,
287 Buffer);
288 InitializeObjectAttributes(&ObjectAttributes,
289 &KeyName,
290 OBJ_CASE_INSENSITIVE,
291 ControllerKey,
292 NULL);
293 Status = NtOpenKey(&ControllerInstanceKey,
294 KEY_ALL_ACCESS,
295 &ObjectAttributes);
296 if (!NT_SUCCESS(Status))
297 {
298 DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
299 NtClose(ControllerKey);
300 NtClose(BusInstanceKey);
301 NtClose(BusKey);
302 return FALSE;
303 }
304
305 /* Get controller identifier */
306 RtlInitUnicodeString(&KeyName,
307 L"Identifier");
308
309 BufferLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
310 256 * sizeof(WCHAR);
311 ValueInfo = (KEY_VALUE_PARTIAL_INFORMATION*) RtlAllocateHeap(RtlGetProcessHeap(),
312 0,
313 BufferLength);
314 if (ValueInfo == NULL)
315 {
316 DPRINT("RtlAllocateHeap() failed\n");
317 NtClose(ControllerInstanceKey);
318 NtClose(ControllerKey);
319 NtClose(BusInstanceKey);
320 NtClose(BusKey);
321 return FALSE;
322 }
323
324 Status = NtQueryValueKey(ControllerInstanceKey,
325 &KeyName,
326 KeyValuePartialInformation,
327 ValueInfo,
328 BufferLength,
329 &ReturnedLength);
330 if (NT_SUCCESS(Status))
331 {
332 DPRINT("Identifier: %S\n", (PWSTR)ValueInfo->Data);
333
334 BufferLength = min(ValueInfo->DataLength / sizeof(WCHAR), IdentifierLength);
335 RtlCopyMemory (Identifier,
336 ValueInfo->Data,
337 BufferLength * sizeof(WCHAR));
338 Identifier[BufferLength] = 0;
339
340 RtlFreeHeap(RtlGetProcessHeap(),
341 0,
342 ValueInfo);
343 NtClose(ControllerInstanceKey);
344 NtClose(ControllerKey);
345 NtClose(BusInstanceKey);
346 NtClose(BusKey);
347 return TRUE;
348 }
349
350 NtClose(ControllerInstanceKey);
351
352 ControllerInstance++;
353 }
354
355 NtClose(ControllerKey);
356 }
357
358 NtClose(BusInstanceKey);
359
360 BusInstance++;
361 }
362
363 NtClose(BusKey);
364
365 return FALSE;
366 }
367
368
369 PGENERIC_LIST
370 CreateDisplayDriverList(HINF InfFile)
371 {
372 CHAR Buffer[128];
373 PGENERIC_LIST List;
374 INFCONTEXT Context;
375 PWCHAR KeyName;
376 PWCHAR KeyValue;
377 PWCHAR UserData;
378 WCHAR DisplayIdentifier[128];
379 WCHAR DisplayKey[32];
380
381 /* Get the display identification */
382 if (!GetDisplayIdentifier(DisplayIdentifier, 128))
383 {
384 DisplayIdentifier[0] = 0;
385 }
386
387 DPRINT("Display identifier: '%S'\n", DisplayIdentifier);
388
389 /* Search for matching device identifier */
390 if (!SetupFindFirstLineW(InfFile, L"Map.Display", NULL, &Context))
391 {
392 /* FIXME: error message */
393 return NULL;
394 }
395
396 do
397 {
398 if (!INF_GetDataField(&Context, 1, &KeyValue))
399 {
400 /* FIXME: Handle error! */
401 DPRINT("INF_GetDataField() failed\n");
402 return NULL;
403 }
404
405 DPRINT("KeyValue: %S\n", KeyValue);
406 if (wcsstr(DisplayIdentifier, KeyValue))
407 {
408 if (!INF_GetDataField(&Context, 0, &KeyName))
409 {
410 /* FIXME: Handle error! */
411 DPRINT("INF_GetDataField() failed\n");
412 return NULL;
413 }
414
415 DPRINT("Display key: %S\n", KeyName);
416 wcscpy(DisplayKey, KeyName);
417 }
418 }
419 while (SetupFindNextLine(&Context, &Context));
420
421
422 List = CreateGenericList();
423 if (List == NULL)
424 return NULL;
425
426 if (!SetupFindFirstLineW (InfFile, L"Display", NULL, &Context))
427 {
428 DestroyGenericList(List, FALSE);
429 return NULL;
430 }
431
432 do
433 {
434 if (!INF_GetDataField(&Context, 0, &KeyName))
435 {
436 DPRINT1("INF_GetDataField() failed\n");
437 break;
438 }
439
440 if (!INF_GetDataField(&Context, 1, &KeyValue))
441 {
442 DPRINT1("INF_GetDataField() failed\n");
443 break;
444 }
445
446 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
447 0,
448 (wcslen(KeyName) + 1) * sizeof(WCHAR));
449 if (UserData == NULL)
450 {
451 DPRINT1("RtlAllocateHeap() failed\n");
452 DestroyGenericList(List, TRUE);
453 return NULL;
454 }
455
456 wcscpy(UserData, KeyName);
457
458 sprintf(Buffer, "%S", KeyValue);
459 AppendGenericListEntry(List,
460 Buffer,
461 UserData,
462 _wcsicmp(KeyName, DisplayKey) ? FALSE : TRUE);
463 }
464 while (SetupFindNextLine(&Context, &Context));
465
466 #if 0
467 AppendGenericListEntry(List, "Other display driver", NULL, TRUE);
468 #endif
469
470 return List;
471 }
472
473 BOOLEAN
474 ProcessComputerFiles(HINF InfFile, PGENERIC_LIST List, PWCHAR* AdditionalSectionName)
475 {
476 PGENERIC_LIST_ENTRY Entry;
477 static WCHAR SectionName[128];
478
479 DPRINT("ProcessComputerFiles() called\n");
480
481 Entry = GetGenericListEntry(List);
482 if (Entry == NULL)
483 {
484 DPRINT("GetGenericListEntry() failed\n");
485 return FALSE;
486 }
487
488 wcscpy(SectionName, L"Files.");
489 wcscat(SectionName, (const wchar_t*) Entry->UserData);
490 *AdditionalSectionName = SectionName;
491
492 return TRUE;
493 }
494
495
496 BOOLEAN
497 ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
498 {
499 PGENERIC_LIST_ENTRY Entry;
500 INFCONTEXT Context;
501 PWCHAR ServiceName;
502 ULONG StartValue;
503 NTSTATUS Status;
504 WCHAR RegPath [255];
505 PWCHAR Buffer;
506 ULONG Width, Hight, Bpp;
507
508 DPRINT("ProcessDisplayRegistry() called\n");
509
510 Entry = GetGenericListEntry(List);
511 if (Entry == NULL)
512 {
513 DPRINT("GetGenericListEntry() failed\n");
514 return FALSE;
515 }
516
517 if (!SetupFindFirstLineW(InfFile, L"Display", (WCHAR*) Entry->UserData, &Context))
518 {
519 DPRINT("SetupFindFirstLineW() failed\n");
520 return FALSE;
521 }
522
523 /* Enable the right driver */
524 if (!INF_GetDataField(&Context, 3, &ServiceName))
525 {
526 DPRINT("INF_GetDataField() failed\n");
527 return FALSE;
528 }
529
530 ASSERT(wcslen(ServiceName) < 10);
531 DPRINT("Service name: %S\n", ServiceName);
532
533 StartValue = 1;
534 Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
535 ServiceName,
536 L"Start",
537 REG_DWORD,
538 &StartValue,
539 sizeof(ULONG));
540
541 if (!NT_SUCCESS(Status))
542 {
543 DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
544 return FALSE;
545 }
546
547 /* Set the resolution */
548 swprintf(RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\%s\\Device0", ServiceName);
549
550 if (!INF_GetDataField(&Context, 4, &Buffer))
551 {
552 DPRINT("INF_GetDataField() failed\n");
553 return FALSE;
554 }
555 Width = wcstoul(Buffer, NULL, 10);
556 Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
557 RegPath,
558 L"DefaultSettings.XResolution",
559 REG_DWORD,
560 &Width,
561 sizeof(ULONG));
562 if (!NT_SUCCESS(Status))
563 {
564 DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
565 return FALSE;
566 }
567
568
569 if (!INF_GetDataField(&Context, 5, &Buffer))
570 {
571 DPRINT("INF_GetDataField() failed\n");
572 return FALSE;
573 }
574 Hight = wcstoul(Buffer, 0, 0);
575 Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
576 RegPath,
577 L"DefaultSettings.YResolution",
578 REG_DWORD,
579 &Hight,
580 sizeof(ULONG));
581 if (!NT_SUCCESS(Status))
582 {
583 DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
584 return FALSE;
585 }
586
587 if (!INF_GetDataField(&Context, 6, &Buffer))
588 {
589 DPRINT("INF_GetDataField() failed\n");
590 return FALSE;
591 }
592 Bpp = wcstoul(Buffer, 0, 0);
593 Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
594 RegPath,
595 L"DefaultSettings.BitsPerPel",
596 REG_DWORD,
597 &Bpp,
598 sizeof(ULONG));
599 if (!NT_SUCCESS(Status))
600 {
601 DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
602 return FALSE;
603 }
604
605 DPRINT("ProcessDisplayRegistry() done\n");
606
607 return TRUE;
608 }
609
610
611 PGENERIC_LIST
612 CreateKeyboardDriverList(HINF InfFile)
613 {
614 CHAR Buffer[128];
615 PGENERIC_LIST List;
616 INFCONTEXT Context;
617 PWCHAR KeyName;
618 PWCHAR KeyValue;
619 PWCHAR UserData;
620
621 List = CreateGenericList();
622 if (List == NULL)
623 return NULL;
624
625 if (!SetupFindFirstLineW (InfFile, L"Keyboard", NULL, &Context))
626 {
627 DestroyGenericList(List, FALSE);
628 return NULL;
629 }
630
631 do
632 {
633 if (!INF_GetData (&Context, &KeyName, &KeyValue))
634 {
635 /* FIXME: Handle error! */
636 DPRINT("INF_GetData() failed\n");
637 break;
638 }
639
640 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
641 0,
642 (wcslen(KeyName) + 1) * sizeof(WCHAR));
643 if (UserData == NULL)
644 {
645 /* FIXME: Handle error! */
646 }
647
648 wcscpy(UserData, KeyName);
649
650 sprintf(Buffer, "%S", KeyValue);
651 AppendGenericListEntry(List, Buffer, UserData, FALSE);
652 }
653 while (SetupFindNextLine(&Context, &Context));
654
655 return List;
656 }
657
658 PGENERIC_LIST
659 CreateLanguageList(HINF InfFile, WCHAR * DefaultLanguage)
660 {
661 CHAR Buffer[128];
662 PGENERIC_LIST List;
663 INFCONTEXT Context;
664 PWCHAR KeyName;
665 PWCHAR KeyValue;
666 PWCHAR UserData;
667
668 /* Get default language id */
669 if (!SetupFindFirstLineW (InfFile, L"NLS", L"DefaultLanguage", &Context))
670 return NULL;
671
672 if (!INF_GetData (&Context, NULL, &KeyValue))
673 return NULL;
674
675 wcscpy(DefaultLanguage, KeyValue);
676
677 SelectedLanguageId = KeyValue;
678
679 List = CreateGenericList();
680 if (List == NULL)
681 return NULL;
682
683 if (!SetupFindFirstLineW (InfFile, L"Language", NULL, &Context))
684 {
685 DestroyGenericList(List, FALSE);
686 return NULL;
687 }
688
689 do
690 {
691 if (!INF_GetData (&Context, &KeyName, &KeyValue))
692 {
693 /* FIXME: Handle error! */
694 DPRINT("INF_GetData() failed\n");
695 break;
696 }
697
698 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
699 0,
700 (wcslen(KeyName) + 1) * sizeof(WCHAR));
701 if (UserData == NULL)
702 {
703 /* FIXME: Handle error! */
704 }
705
706 wcscpy(UserData, KeyName);
707
708 sprintf(Buffer, "%S", KeyValue);
709 AppendGenericListEntry(List,
710 Buffer,
711 UserData,
712 _wcsicmp(KeyName, DefaultLanguage) ? FALSE : TRUE);
713 }
714 while (SetupFindNextLine(&Context, &Context));
715
716 return List;
717 }
718
719 PGENERIC_LIST
720 CreateKeyboardLayoutList(HINF InfFile, WCHAR * DefaultKBLayout)
721 {
722 CHAR Buffer[128];
723 PGENERIC_LIST List;
724 INFCONTEXT Context;
725 PWCHAR KeyName;
726 PWCHAR KeyValue;
727 PWCHAR UserData;
728
729 /* Get default layout id */
730 if (!SetupFindFirstLineW (InfFile, L"NLS", L"DefaultLayout", &Context))
731 return NULL;
732
733 if (!INF_GetData (&Context, NULL, &KeyValue))
734 return NULL;
735
736 wcscpy(DefaultKBLayout, KeyValue);
737
738 List = CreateGenericList();
739 if (List == NULL)
740 return NULL;
741
742 if (!SetupFindFirstLineW (InfFile, L"KeyboardLayout", NULL, &Context))
743 {
744 DestroyGenericList(List, FALSE);
745 return NULL;
746 }
747
748 do
749 {
750 if (!INF_GetData (&Context, &KeyName, &KeyValue))
751 {
752 /* FIXME: Handle error! */
753 DPRINT("INF_GetData() failed\n");
754 DestroyGenericList(List, FALSE);
755 break;
756 }
757
758 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
759 0,
760 (wcslen(KeyName) + 1) * sizeof(WCHAR));
761 if (UserData == NULL)
762 {
763 /* FIXME: Handle error! */
764 }
765
766 wcscpy(UserData, KeyName);
767
768 sprintf(Buffer, "%S", KeyValue);
769 AppendGenericListEntry(List,
770 Buffer,
771 UserData,
772 _wcsicmp(KeyName, DefaultKBLayout) ? FALSE : TRUE);
773 }
774 while (SetupFindNextLine(&Context, &Context));
775
776 return List;
777 }
778
779
780 BOOLEAN
781 ProcessKeyboardLayoutRegistry(PGENERIC_LIST List)
782 {
783 PGENERIC_LIST_ENTRY Entry;
784 PWCHAR LanguageId;
785 OBJECT_ATTRIBUTES ObjectAttributes;
786 UNICODE_STRING KeyName;
787 UNICODE_STRING ValueName;
788 HANDLE KeyHandle;
789 NTSTATUS Status;
790
791 Entry = GetGenericListEntry(List);
792 if (Entry == NULL)
793 return FALSE;
794
795 LanguageId = (PWCHAR)Entry->UserData;
796 if (LanguageId == NULL)
797 return FALSE;
798
799 /* Open the nls language key */
800 RtlInitUnicodeString(&KeyName,
801 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language");
802 InitializeObjectAttributes(&ObjectAttributes,
803 &KeyName,
804 OBJ_CASE_INSENSITIVE,
805 NULL,
806 NULL);
807 Status = NtOpenKey(&KeyHandle,
808 KEY_ALL_ACCESS,
809 &ObjectAttributes);
810 if (!NT_SUCCESS(Status))
811 {
812 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
813 return FALSE;
814 }
815
816 /* Set default language */
817 RtlInitUnicodeString(&ValueName,
818 L"Default");
819 Status = NtSetValueKey (KeyHandle,
820 &ValueName,
821 0,
822 REG_SZ,
823 (PVOID)(LanguageId + 4),
824 8 * sizeof(PWCHAR));
825 if (!NT_SUCCESS(Status))
826 {
827 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
828 NtClose(KeyHandle);
829 return FALSE;
830 }
831
832 /* Set install language */
833 RtlInitUnicodeString(&ValueName,
834 L"InstallLanguage");
835 Status = NtSetValueKey (KeyHandle,
836 &ValueName,
837 0,
838 REG_SZ,
839 (PVOID)(LanguageId + 4),
840 8 * sizeof(PWCHAR));
841 if (!NT_SUCCESS(Status))
842 {
843 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
844 NtClose(KeyHandle);
845 return FALSE;
846 }
847
848 NtClose(KeyHandle);
849
850 return TRUE;
851 }
852
853
854 #if 0
855 BOOLEAN
856 ProcessKeyboardLayoutFiles(PGENERIC_LIST List)
857 {
858 return TRUE;
859 }
860 #endif
861
862 /* EOF */