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