[CMAKE]
[reactos.git] / 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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 * PROGRAMMERS: Eric Kohl
24 * Colin Finck
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include "usetup.h"
30
31 #define NDEBUG
32 #include <debug.h>
33
34 /* FUNCTIONS ****************************************************************/
35
36 static BOOLEAN
37 GetComputerIdentifier(PWSTR Identifier,
38 ULONG IdentifierLength)
39 {
40 OBJECT_ATTRIBUTES ObjectAttributes;
41 UNICODE_STRING KeyName;
42 LPCWSTR ComputerIdentifier;
43 HANDLE ProcessorsKey;
44 PKEY_FULL_INFORMATION pFullInfo;
45 ULONG Size, SizeNeeded;
46 NTSTATUS Status;
47
48 DPRINT("GetComputerIdentifier() called\n");
49
50 Size = sizeof(KEY_FULL_INFORMATION);
51 pFullInfo = (PKEY_FULL_INFORMATION)RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
52 if (!pFullInfo)
53 {
54 DPRINT("RtlAllocateHeap() failed\n");
55 return FALSE;
56 }
57
58 /* Open the processors key */
59 RtlInitUnicodeString(&KeyName,
60 L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor");
61 InitializeObjectAttributes(&ObjectAttributes,
62 &KeyName,
63 OBJ_CASE_INSENSITIVE,
64 NULL,
65 NULL);
66
67 Status = NtOpenKey(&ProcessorsKey,
68 KEY_QUERY_VALUE ,
69 &ObjectAttributes);
70 if (!NT_SUCCESS(Status))
71 {
72 DPRINT("NtOpenKey() failed (Status 0x%lx)\n", Status);
73 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
74 return FALSE;
75 }
76
77 /* Get number of subkeys */
78 Status = NtQueryKey(
79 ProcessorsKey,
80 KeyFullInformation,
81 pFullInfo,
82 Size,
83 &Size);
84 NtClose(ProcessorsKey);
85
86 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
87 {
88 DPRINT("NtQueryKey() failed (Status 0x%lx)\n", Status);
89 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
90 return FALSE;
91 }
92
93 /* Find computer identifier */
94 if (pFullInfo->SubKeys == 0)
95 {
96 /* Something strange happened. No processor detected */
97 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
98 return FALSE;
99 }
100
101 if (pFullInfo->SubKeys == 1)
102 {
103 /* Computer is mono-CPU */
104 ComputerIdentifier = L"PC UP";
105 }
106 else
107 {
108 /* Computer is multi-CPUs */
109 ComputerIdentifier = L"PC MP";
110 }
111
112 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
113
114 /* Copy computer identifier to return buffer */
115 SizeNeeded = (wcslen(ComputerIdentifier) + 1) * sizeof(WCHAR);
116 if (SizeNeeded > IdentifierLength)
117 return FALSE;
118
119 RtlCopyMemory(Identifier, ComputerIdentifier, SizeNeeded);
120
121 return TRUE;
122 }
123
124
125 PGENERIC_LIST
126 CreateComputerTypeList(HINF InfFile)
127 {
128 CHAR Buffer[128];
129 PGENERIC_LIST List;
130 INFCONTEXT Context;
131 PWCHAR KeyName;
132 PWCHAR KeyValue;
133 PWCHAR UserData;
134 WCHAR ComputerIdentifier[128];
135 WCHAR ComputerKey[32];
136
137 /* Get the computer identification */
138 if (!GetComputerIdentifier(ComputerIdentifier, 128))
139 {
140 ComputerIdentifier[0] = 0;
141 }
142
143 DPRINT("Computer identifier: '%S'\n", ComputerIdentifier);
144
145 /* Search for matching device identifier */
146 if (!SetupFindFirstLineW(InfFile, L"Map.Computer", NULL, &Context))
147 {
148 /* FIXME: error message */
149 return NULL;
150 }
151
152 do
153 {
154 if (!INF_GetDataField(&Context, 1, &KeyValue))
155 {
156 /* FIXME: Handle error! */
157 DPRINT("INF_GetDataField() failed\n");
158 return NULL;
159 }
160
161 DPRINT("KeyValue: %S\n", KeyValue);
162 if (wcsstr(ComputerIdentifier, KeyValue))
163 {
164 if (!INF_GetDataField(&Context, 0, &KeyName))
165 {
166 /* FIXME: Handle error! */
167 DPRINT("INF_GetDataField() failed\n");
168 return NULL;
169 }
170
171 DPRINT("Computer key: %S\n", KeyName);
172 wcscpy(ComputerKey, KeyName);
173 }
174 } while (SetupFindNextLine(&Context, &Context));
175
176 List = CreateGenericList();
177 if (List == NULL)
178 return NULL;
179
180 if (!SetupFindFirstLineW (InfFile, L"Computer", NULL, &Context))
181 {
182 DestroyGenericList(List, FALSE);
183 return NULL;
184 }
185
186 do
187 {
188 if (!INF_GetData (&Context, &KeyName, &KeyValue))
189 {
190 /* FIXME: Handle error! */
191 DPRINT("INF_GetData() failed\n");
192 break;
193 }
194
195 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
196 0,
197 (wcslen(KeyName) + 1) * sizeof(WCHAR));
198 if (UserData == NULL)
199 {
200 /* FIXME: Handle error! */
201 }
202
203 wcscpy(UserData, KeyName);
204
205 sprintf(Buffer, "%S", KeyValue);
206 AppendGenericListEntry(List, Buffer, UserData,
207 _wcsicmp(KeyName, ComputerKey) ? FALSE : TRUE);
208 } while (SetupFindNextLine(&Context, &Context));
209
210 return List;
211 }
212
213
214 static BOOLEAN
215 GetDisplayIdentifier(PWSTR Identifier,
216 ULONG IdentifierLength)
217 {
218 OBJECT_ATTRIBUTES ObjectAttributes;
219 UNICODE_STRING KeyName;
220 WCHAR Buffer[32];
221 HANDLE BusKey;
222 HANDLE BusInstanceKey;
223 HANDLE ControllerKey;
224 HANDLE ControllerInstanceKey;
225 ULONG BusInstance;
226 ULONG ControllerInstance;
227 ULONG BufferLength;
228 ULONG ReturnedLength;
229 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
230 NTSTATUS Status;
231
232 DPRINT("GetDisplayIdentifier() called\n");
233
234 /* Open the bus key */
235 RtlInitUnicodeString(&KeyName,
236 L"\\Registry\\Machine\\HARDWARE\\Description\\System\\MultifunctionAdapter");
237 InitializeObjectAttributes(&ObjectAttributes,
238 &KeyName,
239 OBJ_CASE_INSENSITIVE,
240 NULL,
241 NULL);
242
243 Status = NtOpenKey(&BusKey,
244 KEY_ENUMERATE_SUB_KEYS,
245 &ObjectAttributes);
246 if (!NT_SUCCESS(Status))
247 {
248 DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
249 return FALSE;
250 }
251
252 BusInstance = 0;
253 while (TRUE)
254 {
255 swprintf(Buffer, L"%lu", BusInstance);
256 RtlInitUnicodeString(&KeyName,
257 Buffer);
258 InitializeObjectAttributes(&ObjectAttributes,
259 &KeyName,
260 OBJ_CASE_INSENSITIVE,
261 BusKey,
262 NULL);
263
264 Status = NtOpenKey(&BusInstanceKey,
265 KEY_ENUMERATE_SUB_KEYS,
266 &ObjectAttributes);
267 if (!NT_SUCCESS(Status))
268 {
269 DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
270 NtClose(BusKey);
271 return FALSE;
272 }
273
274 /* Open the controller type key */
275 RtlInitUnicodeString(&KeyName,
276 L"DisplayController");
277 InitializeObjectAttributes(&ObjectAttributes,
278 &KeyName,
279 OBJ_CASE_INSENSITIVE,
280 BusInstanceKey,
281 NULL);
282
283 Status = NtOpenKey(&ControllerKey,
284 KEY_ENUMERATE_SUB_KEYS,
285 &ObjectAttributes);
286 if (NT_SUCCESS(Status))
287 {
288 ControllerInstance = 0;
289
290 while (TRUE)
291 {
292 /* Open the pointer controller instance key */
293 swprintf(Buffer, L"%lu", ControllerInstance);
294 RtlInitUnicodeString(&KeyName,
295 Buffer);
296 InitializeObjectAttributes(&ObjectAttributes,
297 &KeyName,
298 OBJ_CASE_INSENSITIVE,
299 ControllerKey,
300 NULL);
301
302 Status = NtOpenKey(&ControllerInstanceKey,
303 KEY_QUERY_VALUE,
304 &ObjectAttributes);
305 if (!NT_SUCCESS(Status))
306 {
307 DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
308 NtClose(ControllerKey);
309 NtClose(BusInstanceKey);
310 NtClose(BusKey);
311 return FALSE;
312 }
313
314 /* Get controller identifier */
315 RtlInitUnicodeString(&KeyName,
316 L"Identifier");
317
318 BufferLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
319 256 * sizeof(WCHAR);
320 ValueInfo = (KEY_VALUE_PARTIAL_INFORMATION*) RtlAllocateHeap(RtlGetProcessHeap(),
321 0,
322 BufferLength);
323 if (ValueInfo == NULL)
324 {
325 DPRINT("RtlAllocateHeap() failed\n");
326 NtClose(ControllerInstanceKey);
327 NtClose(ControllerKey);
328 NtClose(BusInstanceKey);
329 NtClose(BusKey);
330 return FALSE;
331 }
332
333 Status = NtQueryValueKey(ControllerInstanceKey,
334 &KeyName,
335 KeyValuePartialInformation,
336 ValueInfo,
337 BufferLength,
338 &ReturnedLength);
339 if (NT_SUCCESS(Status))
340 {
341 DPRINT("Identifier: %S\n", (PWSTR)ValueInfo->Data);
342
343 BufferLength = min(ValueInfo->DataLength / sizeof(WCHAR), IdentifierLength);
344 RtlCopyMemory (Identifier,
345 ValueInfo->Data,
346 BufferLength * sizeof(WCHAR));
347 Identifier[BufferLength] = 0;
348
349 RtlFreeHeap(RtlGetProcessHeap(),
350 0,
351 ValueInfo);
352
353 NtClose(ControllerInstanceKey);
354 NtClose(ControllerKey);
355 NtClose(BusInstanceKey);
356 NtClose(BusKey);
357 return TRUE;
358 }
359
360 NtClose(ControllerInstanceKey);
361
362 ControllerInstance++;
363 }
364
365 NtClose(ControllerKey);
366 }
367
368 NtClose(BusInstanceKey);
369
370 BusInstance++;
371 }
372
373 NtClose(BusKey);
374
375 return FALSE;
376 }
377
378
379 PGENERIC_LIST
380 CreateDisplayDriverList(HINF InfFile)
381 {
382 CHAR Buffer[128];
383 PGENERIC_LIST List;
384 INFCONTEXT Context;
385 PWCHAR KeyName;
386 PWCHAR KeyValue;
387 PWCHAR UserData;
388 WCHAR DisplayIdentifier[128];
389 WCHAR DisplayKey[32];
390
391 /* Get the display identification */
392 if (!GetDisplayIdentifier(DisplayIdentifier, 128))
393 {
394 DisplayIdentifier[0] = 0;
395 }
396
397 DPRINT("Display identifier: '%S'\n", DisplayIdentifier);
398
399 /* Search for matching device identifier */
400 if (!SetupFindFirstLineW(InfFile, L"Map.Display", NULL, &Context))
401 {
402 /* FIXME: error message */
403 return NULL;
404 }
405
406 do
407 {
408 if (!INF_GetDataField(&Context, 1, &KeyValue))
409 {
410 /* FIXME: Handle error! */
411 DPRINT("INF_GetDataField() failed\n");
412 return NULL;
413 }
414
415 DPRINT("KeyValue: %S\n", KeyValue);
416 if (wcsstr(DisplayIdentifier, KeyValue))
417 {
418 if (!INF_GetDataField(&Context, 0, &KeyName))
419 {
420 /* FIXME: Handle error! */
421 DPRINT("INF_GetDataField() failed\n");
422 return NULL;
423 }
424
425 DPRINT("Display key: %S\n", KeyName);
426 wcscpy(DisplayKey, KeyName);
427 }
428 } while (SetupFindNextLine(&Context, &Context));
429
430 List = CreateGenericList();
431 if (List == NULL)
432 return NULL;
433
434 if (!SetupFindFirstLineW (InfFile, L"Display", NULL, &Context))
435 {
436 DestroyGenericList(List, FALSE);
437 return NULL;
438 }
439
440 do
441 {
442 if (!INF_GetDataField(&Context, 0, &KeyName))
443 {
444 DPRINT1("INF_GetDataField() failed\n");
445 break;
446 }
447
448 if (!INF_GetDataField(&Context, 1, &KeyValue))
449 {
450 DPRINT1("INF_GetDataField() failed\n");
451 break;
452 }
453
454 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
455 0,
456 (wcslen(KeyName) + 1) * sizeof(WCHAR));
457 if (UserData == NULL)
458 {
459 DPRINT1("RtlAllocateHeap() failed\n");
460 DestroyGenericList(List, TRUE);
461 return NULL;
462 }
463
464 wcscpy(UserData, KeyName);
465
466 sprintf(Buffer, "%S", KeyValue);
467 AppendGenericListEntry(List,
468 Buffer,
469 UserData,
470 _wcsicmp(KeyName, DisplayKey) ? FALSE : TRUE);
471 } while (SetupFindNextLine(&Context, &Context));
472
473 #if 0
474 AppendGenericListEntry(List, "Other display driver", NULL, TRUE);
475 #endif
476
477 return List;
478 }
479
480 BOOLEAN
481 ProcessComputerFiles(HINF InfFile, PGENERIC_LIST List, PWCHAR* AdditionalSectionName)
482 {
483 PGENERIC_LIST_ENTRY Entry;
484 static WCHAR SectionName[128];
485
486 DPRINT("ProcessComputerFiles() called\n");
487
488 Entry = GetCurrentListEntry(List);
489 if (Entry == NULL)
490 {
491 DPRINT("GetCurrentListEntry() failed\n");
492 return FALSE;
493 }
494
495 wcscpy(SectionName, L"Files.");
496 wcscat(SectionName, (const wchar_t*)GetListEntryUserData(Entry));
497 *AdditionalSectionName = SectionName;
498
499 return TRUE;
500 }
501
502
503 BOOLEAN
504 ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
505 {
506 PGENERIC_LIST_ENTRY Entry;
507 INFCONTEXT Context;
508 PWCHAR ServiceName;
509 ULONG StartValue;
510 NTSTATUS Status;
511 WCHAR RegPath [255];
512 PWCHAR Buffer;
513 ULONG Width, Height, Bpp;
514
515 DPRINT("ProcessDisplayRegistry() called\n");
516
517 Entry = GetCurrentListEntry(List);
518 if (Entry == NULL)
519 {
520 DPRINT("GetCurrentListEntry() failed\n");
521 return FALSE;
522 }
523
524 if (!SetupFindFirstLineW(InfFile, L"Display", (WCHAR*)GetListEntryUserData(Entry), &Context))
525 {
526 DPRINT("SetupFindFirstLineW() failed\n");
527 return FALSE;
528 }
529
530 /* Enable the right driver */
531 if (!INF_GetDataField(&Context, 3, &ServiceName))
532 {
533 DPRINT("INF_GetDataField() failed\n");
534 return FALSE;
535 }
536
537 ASSERT(wcslen(ServiceName) < 10);
538 DPRINT("Service name: %S\n", ServiceName);
539
540 StartValue = 1;
541 Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
542 ServiceName,
543 L"Start",
544 REG_DWORD,
545 &StartValue,
546 sizeof(ULONG));
547
548 if (!NT_SUCCESS(Status))
549 {
550 DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
551 return FALSE;
552 }
553
554 /* Set the resolution */
555 swprintf(RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\%s\\Device0", ServiceName);
556
557 if (!INF_GetDataField(&Context, 4, &Buffer))
558 {
559 DPRINT("INF_GetDataField() failed\n");
560 return FALSE;
561 }
562
563 Width = wcstoul(Buffer, NULL, 10);
564 Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
565 RegPath,
566 L"DefaultSettings.XResolution",
567 REG_DWORD,
568 &Width,
569 sizeof(ULONG));
570 if (!NT_SUCCESS(Status))
571 {
572 DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
573 return FALSE;
574 }
575
576 if (!INF_GetDataField(&Context, 5, &Buffer))
577 {
578 DPRINT("INF_GetDataField() failed\n");
579 return FALSE;
580 }
581
582 Height = wcstoul(Buffer, 0, 0);
583 Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
584 RegPath,
585 L"DefaultSettings.YResolution",
586 REG_DWORD,
587 &Height,
588 sizeof(ULONG));
589 if (!NT_SUCCESS(Status))
590 {
591 DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
592 return FALSE;
593 }
594
595 if (!INF_GetDataField(&Context, 6, &Buffer))
596 {
597 DPRINT("INF_GetDataField() failed\n");
598 return FALSE;
599 }
600
601 Bpp = wcstoul(Buffer, 0, 0);
602 Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
603 RegPath,
604 L"DefaultSettings.BitsPerPel",
605 REG_DWORD,
606 &Bpp,
607 sizeof(ULONG));
608 if (!NT_SUCCESS(Status))
609 {
610 DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
611 return FALSE;
612 }
613
614 DPRINT("ProcessDisplayRegistry() done\n");
615
616 return TRUE;
617 }
618
619
620 BOOLEAN
621 ProcessLocaleRegistry(PGENERIC_LIST List)
622 {
623 PGENERIC_LIST_ENTRY Entry;
624 PWCHAR LanguageId;
625 OBJECT_ATTRIBUTES ObjectAttributes;
626 UNICODE_STRING KeyName;
627 UNICODE_STRING ValueName;
628
629 HANDLE KeyHandle;
630 NTSTATUS Status;
631
632 Entry = GetCurrentListEntry(List);
633 if (Entry == NULL)
634 return FALSE;
635
636 LanguageId = (PWCHAR)GetListEntryUserData(Entry);
637 if (LanguageId == NULL)
638 return FALSE;
639
640 /* Open the NLS language key */
641 RtlInitUnicodeString(&KeyName,
642 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language");
643
644 InitializeObjectAttributes(&ObjectAttributes,
645 &KeyName,
646 OBJ_CASE_INSENSITIVE,
647 NULL,
648 NULL);
649
650 Status = NtOpenKey(&KeyHandle,
651 KEY_SET_VALUE,
652 &ObjectAttributes);
653
654 if (!NT_SUCCESS(Status))
655 {
656 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
657 return FALSE;
658 }
659
660 /* Set default language */
661 RtlInitUnicodeString(&ValueName,
662 L"Default");
663
664 Status = NtSetValueKey(KeyHandle,
665 &ValueName,
666 0,
667 REG_SZ,
668 (PVOID)(LanguageId + 4),
669 8 * sizeof(PWCHAR));
670 if (!NT_SUCCESS(Status))
671 {
672 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
673 NtClose(KeyHandle);
674 return FALSE;
675 }
676
677 /* Set install language */
678 RtlInitUnicodeString(&ValueName,
679 L"InstallLanguage");
680 Status = NtSetValueKey (KeyHandle,
681 &ValueName,
682 0,
683 REG_SZ,
684 (PVOID)(LanguageId + 4),
685 8 * sizeof(PWCHAR));
686 if (!NT_SUCCESS(Status))
687 {
688 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
689 NtClose(KeyHandle);
690 return FALSE;
691 }
692
693 NtClose(KeyHandle);
694
695 return TRUE;
696 }
697
698
699 PGENERIC_LIST
700 CreateKeyboardDriverList(HINF InfFile)
701 {
702 CHAR Buffer[128];
703 PGENERIC_LIST List;
704 INFCONTEXT Context;
705 PWCHAR KeyName;
706 PWCHAR KeyValue;
707 PWCHAR UserData;
708
709 List = CreateGenericList();
710 if (List == NULL)
711 return NULL;
712
713 if (!SetupFindFirstLineW (InfFile, L"Keyboard", NULL, &Context))
714 {
715 DestroyGenericList(List, FALSE);
716 return NULL;
717 }
718
719 do
720 {
721 if (!INF_GetData (&Context, &KeyName, &KeyValue))
722 {
723 /* FIXME: Handle error! */
724 DPRINT("INF_GetData() failed\n");
725 break;
726 }
727
728 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
729 0,
730 (wcslen(KeyName) + 1) * sizeof(WCHAR));
731 if (UserData == NULL)
732 {
733 /* FIXME: Handle error! */
734 }
735
736 wcscpy(UserData, KeyName);
737
738 sprintf(Buffer, "%S", KeyValue);
739 AppendGenericListEntry(List, Buffer, UserData, FALSE);
740 } while (SetupFindNextLine(&Context, &Context));
741
742 return List;
743 }
744
745 ULONG DefaultLanguageIndex = 0;
746
747 ULONG
748 GetDefaultLanguageIndex(VOID)
749 {
750 return DefaultLanguageIndex;
751 }
752
753 PGENERIC_LIST
754 CreateLanguageList(HINF InfFile, WCHAR * DefaultLanguage)
755 {
756 CHAR Buffer[128];
757 PGENERIC_LIST List;
758 INFCONTEXT Context;
759 PWCHAR KeyName;
760 PWCHAR KeyValue;
761 PWCHAR UserData;
762 ULONG uIndex = 0;
763
764 /* Get default language id */
765 if (!SetupFindFirstLineW (InfFile, L"NLS", L"DefaultLanguage", &Context))
766 return NULL;
767
768 if (!INF_GetData (&Context, NULL, &KeyValue))
769 return NULL;
770
771 wcscpy(DefaultLanguage, KeyValue);
772
773 SelectedLanguageId = KeyValue;
774
775 List = CreateGenericList();
776 if (List == NULL)
777 return NULL;
778
779 if (!SetupFindFirstLineW (InfFile, L"Language", NULL, &Context))
780 {
781 DestroyGenericList(List, FALSE);
782 return NULL;
783 }
784
785 do
786 {
787 if (!INF_GetData (&Context, &KeyName, &KeyValue))
788 {
789 /* FIXME: Handle error! */
790 DPRINT("INF_GetData() failed\n");
791 break;
792 }
793
794 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
795 0,
796 (wcslen(KeyName) + 1) * sizeof(WCHAR));
797 if (UserData == NULL)
798 {
799 /* FIXME: Handle error! */
800 }
801
802 wcscpy(UserData, KeyName);
803
804 if (!_wcsicmp(KeyName, DefaultLanguage)) DefaultLanguageIndex = uIndex;
805
806 sprintf(Buffer, "%S", KeyValue);
807 AppendGenericListEntry(List,
808 Buffer,
809 UserData,
810 FALSE);
811 uIndex++;
812 } while (SetupFindNextLine(&Context, &Context));
813
814 return List;
815 }
816
817 PGENERIC_LIST
818 CreateKeyboardLayoutList(HINF InfFile, WCHAR * DefaultKBLayout)
819 {
820 CHAR Buffer[128];
821 PGENERIC_LIST List;
822 INFCONTEXT Context;
823 PWCHAR KeyName;
824 PWCHAR KeyValue;
825 PWCHAR UserData;
826 const MUI_LAYOUTS * LayoutsList;
827 ULONG uIndex = 0;
828 BOOL KeyboardLayoutsFound = FALSE;
829
830 /* Get default layout id */
831 if (!SetupFindFirstLineW (InfFile, L"NLS", L"DefaultLayout", &Context))
832 return NULL;
833
834 if (!INF_GetData (&Context, NULL, &KeyValue))
835 return NULL;
836
837 wcscpy(DefaultKBLayout, KeyValue);
838
839 List = CreateGenericList();
840 if (List == NULL)
841 return NULL;
842
843 LayoutsList = MUIGetLayoutsList();
844
845 do
846 {
847 if (!SetupFindFirstLineW(InfFile, L"KeyboardLayout", NULL, &Context))
848 {
849 DestroyGenericList(List, FALSE);
850 return NULL;
851 }
852
853 do
854 {
855 if (!INF_GetData (&Context, &KeyName, &KeyValue))
856 {
857 /* FIXME: Handle error! */
858 DPRINT("INF_GetData() failed\n");
859 DestroyGenericList(List, FALSE);
860 return NULL;
861 }
862
863 if (_wcsicmp(LayoutsList[uIndex].LayoutID, KeyName) == 0)
864 {
865 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
866 0,
867 (wcslen(KeyName) + 1) * sizeof(WCHAR));
868
869 if (UserData == NULL)
870 {
871 /* FIXME: Handle error! */
872 DPRINT("RtlAllocateHeap() failed\n");
873 DestroyGenericList(List, FALSE);
874 return NULL;
875 }
876
877 wcscpy(UserData, KeyName);
878
879 sprintf(Buffer, "%S", KeyValue);
880 AppendGenericListEntry(List,
881 Buffer,
882 UserData,
883 _wcsicmp(KeyName, DefaultKBLayout) ? FALSE : TRUE);
884 KeyboardLayoutsFound = TRUE;
885 }
886
887 } while (SetupFindNextLine(&Context, &Context));
888
889 uIndex++;
890
891 } while (LayoutsList[uIndex].LangID != NULL);
892
893 /* FIXME: Handle this case */
894 if (!KeyboardLayoutsFound)
895 {
896 DPRINT1("No keyboard layouts have been found\n");
897 DestroyGenericList(List, FALSE);
898 return NULL;
899 }
900
901 return List;
902 }
903
904 BOOLEAN
905 ProcessKeyboardLayoutRegistry(PGENERIC_LIST List)
906 {
907 PGENERIC_LIST_ENTRY Entry;
908 PWCHAR LayoutId;
909 const MUI_LAYOUTS * LayoutsList;
910 MUI_LAYOUTS NewLayoutsList[20];
911 ULONG uIndex;
912 ULONG uOldPos = 0;
913
914 Entry = GetCurrentListEntry(List);
915 if (Entry == NULL)
916 return FALSE;
917
918 LayoutId = (PWCHAR)GetListEntryUserData(Entry);
919 if (LayoutId == NULL)
920 return FALSE;
921
922 LayoutsList = MUIGetLayoutsList();
923
924 if (_wcsicmp(LayoutsList[0].LayoutID, LayoutId) != 0)
925 {
926 for (uIndex = 1; LayoutsList[uIndex].LangID != NULL; uIndex++)
927 {
928 if (_wcsicmp(LayoutsList[uIndex].LayoutID, LayoutId) == 0)
929 {
930 uOldPos = uIndex;
931 continue;
932 }
933
934 NewLayoutsList[uIndex].LangID = LayoutsList[uIndex].LangID;
935 NewLayoutsList[uIndex].LayoutID = LayoutsList[uIndex].LayoutID;
936 }
937
938 NewLayoutsList[uIndex].LangID = NULL;
939 NewLayoutsList[uIndex].LayoutID = NULL;
940 NewLayoutsList[uOldPos].LangID = LayoutsList[0].LangID;
941 NewLayoutsList[uOldPos].LayoutID = LayoutsList[0].LayoutID;
942 NewLayoutsList[0].LangID = LayoutsList[uOldPos].LangID;
943 NewLayoutsList[0].LayoutID = LayoutsList[uOldPos].LayoutID;
944
945 return AddKbLayoutsToRegistry(NewLayoutsList);
946 }
947
948 return TRUE;
949 }
950
951
952 #if 0
953 BOOLEAN
954 ProcessKeyboardLayoutFiles(PGENERIC_LIST List)
955 {
956 return TRUE;
957 }
958 #endif
959
960 BOOLEAN
961 SetGeoID(PWCHAR Id)
962 {
963 OBJECT_ATTRIBUTES ObjectAttributes;
964 UNICODE_STRING KeyName;
965 UNICODE_STRING ValueName;
966 HANDLE KeyHandle;
967 WCHAR szKeyName[] = L"\\Registry\\User\\.DEFAULT\\Control Panel\\International\\Geo";
968 WCHAR szValueName[] = L"Nation";
969 NTSTATUS Status;
970 RtlInitUnicodeString(&KeyName,
971 szKeyName);
972 InitializeObjectAttributes(&ObjectAttributes,
973 &KeyName,
974 OBJ_CASE_INSENSITIVE,
975 NULL,
976 NULL);
977
978 Status = NtOpenKey(&KeyHandle,
979 KEY_SET_VALUE,
980 &ObjectAttributes);
981 if(!NT_SUCCESS(Status))
982 {
983 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
984 return FALSE;
985 }
986 RtlInitUnicodeString(&ValueName, szValueName);
987 Status = NtSetValueKey(KeyHandle,
988 &ValueName,
989 0,
990 REG_SZ,
991 (PVOID)Id,
992 (wcslen(Id) * sizeof(WCHAR)));
993 if (!NT_SUCCESS(Status))
994 {
995 DPRINT1("NtSetValueKey() failed (Status = %lx)\n", Status);
996 NtClose(KeyHandle);
997 return FALSE;
998 }
999
1000 return TRUE;
1001 }
1002
1003 /* EOF */