ffc20ac286a44d99e95333ac858bc993555bb62a
[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 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 NtClose(KeyHandle);
687 if (!NT_SUCCESS(Status))
688 {
689 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
690 return FALSE;
691 }
692
693 return TRUE;
694 }
695
696
697 PGENERIC_LIST
698 CreateKeyboardDriverList(HINF InfFile)
699 {
700 CHAR Buffer[128];
701 PGENERIC_LIST List;
702 INFCONTEXT Context;
703 PWCHAR KeyName;
704 PWCHAR KeyValue;
705 PWCHAR UserData;
706
707 List = CreateGenericList();
708 if (List == NULL)
709 return NULL;
710
711 if (!SetupFindFirstLineW (InfFile, L"Keyboard", NULL, &Context))
712 {
713 DestroyGenericList(List, FALSE);
714 return NULL;
715 }
716
717 do
718 {
719 if (!INF_GetData (&Context, &KeyName, &KeyValue))
720 {
721 /* FIXME: Handle error! */
722 DPRINT("INF_GetData() failed\n");
723 break;
724 }
725
726 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
727 0,
728 (wcslen(KeyName) + 1) * sizeof(WCHAR));
729 if (UserData == NULL)
730 {
731 /* FIXME: Handle error! */
732 }
733
734 wcscpy(UserData, KeyName);
735
736 sprintf(Buffer, "%S", KeyValue);
737 AppendGenericListEntry(List, Buffer, UserData, FALSE);
738 } while (SetupFindNextLine(&Context, &Context));
739
740 return List;
741 }
742
743 ULONG DefaultLanguageIndex = 0;
744
745 ULONG
746 GetDefaultLanguageIndex(VOID)
747 {
748 return DefaultLanguageIndex;
749 }
750
751 PGENERIC_LIST
752 CreateLanguageList(HINF InfFile, WCHAR * DefaultLanguage)
753 {
754 CHAR Buffer[128];
755 PGENERIC_LIST List;
756 INFCONTEXT Context;
757 PWCHAR KeyName;
758 PWCHAR KeyValue;
759 PWCHAR UserData;
760 ULONG uIndex = 0;
761
762 /* Get default language id */
763 if (!SetupFindFirstLineW (InfFile, L"NLS", L"DefaultLanguage", &Context))
764 return NULL;
765
766 if (!INF_GetData (&Context, NULL, &KeyValue))
767 return NULL;
768
769 wcscpy(DefaultLanguage, KeyValue);
770
771 SelectedLanguageId = KeyValue;
772
773 List = CreateGenericList();
774 if (List == NULL)
775 return NULL;
776
777 if (!SetupFindFirstLineW (InfFile, L"Language", NULL, &Context))
778 {
779 DestroyGenericList(List, FALSE);
780 return NULL;
781 }
782
783 do
784 {
785 if (!INF_GetData (&Context, &KeyName, &KeyValue))
786 {
787 /* FIXME: Handle error! */
788 DPRINT("INF_GetData() failed\n");
789 break;
790 }
791
792 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
793 0,
794 (wcslen(KeyName) + 1) * sizeof(WCHAR));
795 if (UserData == NULL)
796 {
797 /* FIXME: Handle error! */
798 }
799
800 wcscpy(UserData, KeyName);
801
802 if (!_wcsicmp(KeyName, DefaultLanguage)) DefaultLanguageIndex = uIndex;
803
804 sprintf(Buffer, "%S", KeyValue);
805 AppendGenericListEntry(List,
806 Buffer,
807 UserData,
808 FALSE);
809 uIndex++;
810 } while (SetupFindNextLine(&Context, &Context));
811
812 return List;
813 }
814
815 PGENERIC_LIST
816 CreateKeyboardLayoutList(HINF InfFile, WCHAR * DefaultKBLayout)
817 {
818 CHAR Buffer[128];
819 PGENERIC_LIST List;
820 INFCONTEXT Context;
821 PWCHAR KeyName;
822 PWCHAR KeyValue;
823 PWCHAR UserData;
824 const MUI_LAYOUTS * LayoutsList;
825 ULONG uIndex = 0;
826 BOOL KeyboardLayoutsFound = FALSE;
827
828 /* Get default layout id */
829 if (!SetupFindFirstLineW (InfFile, L"NLS", L"DefaultLayout", &Context))
830 return NULL;
831
832 if (!INF_GetData (&Context, NULL, &KeyValue))
833 return NULL;
834
835 wcscpy(DefaultKBLayout, KeyValue);
836
837 List = CreateGenericList();
838 if (List == NULL)
839 return NULL;
840
841 LayoutsList = MUIGetLayoutsList();
842
843 do
844 {
845 if (!SetupFindFirstLineW(InfFile, L"KeyboardLayout", NULL, &Context))
846 {
847 DestroyGenericList(List, FALSE);
848 return NULL;
849 }
850
851 do
852 {
853 if (!INF_GetData (&Context, &KeyName, &KeyValue))
854 {
855 /* FIXME: Handle error! */
856 DPRINT("INF_GetData() failed\n");
857 DestroyGenericList(List, FALSE);
858 return NULL;
859 }
860
861 if (_wcsicmp(LayoutsList[uIndex].LayoutID, KeyName) == 0)
862 {
863 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
864 0,
865 (wcslen(KeyName) + 1) * sizeof(WCHAR));
866
867 if (UserData == NULL)
868 {
869 /* FIXME: Handle error! */
870 DPRINT("RtlAllocateHeap() failed\n");
871 DestroyGenericList(List, FALSE);
872 return NULL;
873 }
874
875 wcscpy(UserData, KeyName);
876
877 sprintf(Buffer, "%S", KeyValue);
878 AppendGenericListEntry(List,
879 Buffer,
880 UserData,
881 _wcsicmp(KeyName, DefaultKBLayout) ? FALSE : TRUE);
882 KeyboardLayoutsFound = TRUE;
883 }
884
885 } while (SetupFindNextLine(&Context, &Context));
886
887 uIndex++;
888
889 } while (LayoutsList[uIndex].LangID != NULL);
890
891 /* FIXME: Handle this case */
892 if (!KeyboardLayoutsFound)
893 {
894 DPRINT1("No keyboard layouts have been found\n");
895 DestroyGenericList(List, FALSE);
896 return NULL;
897 }
898
899 return List;
900 }
901
902 BOOLEAN
903 ProcessKeyboardLayoutRegistry(PGENERIC_LIST List)
904 {
905 PGENERIC_LIST_ENTRY Entry;
906 PWCHAR LayoutId;
907 const MUI_LAYOUTS * LayoutsList;
908 MUI_LAYOUTS NewLayoutsList[20];
909 ULONG uIndex;
910 ULONG uOldPos = 0;
911
912 Entry = GetCurrentListEntry(List);
913 if (Entry == NULL)
914 return FALSE;
915
916 LayoutId = (PWCHAR)GetListEntryUserData(Entry);
917 if (LayoutId == NULL)
918 return FALSE;
919
920 LayoutsList = MUIGetLayoutsList();
921
922 if (_wcsicmp(LayoutsList[0].LayoutID, LayoutId) != 0)
923 {
924 for (uIndex = 1; LayoutsList[uIndex].LangID != NULL; uIndex++)
925 {
926 if (_wcsicmp(LayoutsList[uIndex].LayoutID, LayoutId) == 0)
927 {
928 uOldPos = uIndex;
929 continue;
930 }
931
932 NewLayoutsList[uIndex].LangID = LayoutsList[uIndex].LangID;
933 NewLayoutsList[uIndex].LayoutID = LayoutsList[uIndex].LayoutID;
934 }
935
936 NewLayoutsList[uIndex].LangID = NULL;
937 NewLayoutsList[uIndex].LayoutID = NULL;
938 NewLayoutsList[uOldPos].LangID = LayoutsList[0].LangID;
939 NewLayoutsList[uOldPos].LayoutID = LayoutsList[0].LayoutID;
940 NewLayoutsList[0].LangID = LayoutsList[uOldPos].LangID;
941 NewLayoutsList[0].LayoutID = LayoutsList[uOldPos].LayoutID;
942
943 return AddKbLayoutsToRegistry(NewLayoutsList);
944 }
945
946 return TRUE;
947 }
948
949
950 #if 0
951 BOOLEAN
952 ProcessKeyboardLayoutFiles(PGENERIC_LIST List)
953 {
954 return TRUE;
955 }
956 #endif
957
958 BOOLEAN
959 SetGeoID(PWCHAR Id)
960 {
961 OBJECT_ATTRIBUTES ObjectAttributes;
962 UNICODE_STRING KeyName;
963 UNICODE_STRING ValueName;
964 HANDLE KeyHandle;
965 WCHAR szKeyName[] = L"\\Registry\\User\\.DEFAULT\\Control Panel\\International\\Geo";
966 WCHAR szValueName[] = L"Nation";
967 NTSTATUS Status;
968 RtlInitUnicodeString(&KeyName,
969 szKeyName);
970 InitializeObjectAttributes(&ObjectAttributes,
971 &KeyName,
972 OBJ_CASE_INSENSITIVE,
973 NULL,
974 NULL);
975
976 Status = NtOpenKey(&KeyHandle,
977 KEY_SET_VALUE,
978 &ObjectAttributes);
979 if(!NT_SUCCESS(Status))
980 {
981 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
982 return FALSE;
983 }
984 RtlInitUnicodeString(&ValueName, szValueName);
985 Status = NtSetValueKey(KeyHandle,
986 &ValueName,
987 0,
988 REG_SZ,
989 (PVOID)Id,
990 (wcslen(Id) + 1) * sizeof(WCHAR));
991 NtClose(KeyHandle);
992 if (!NT_SUCCESS(Status))
993 {
994 DPRINT1("NtSetValueKey() failed (Status = %lx)\n", Status);
995 return FALSE;
996 }
997
998 return TRUE;
999 }
1000
1001 /* EOF */