3 * Copyright (C) 2004 ReactOS Team
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.
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.
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.
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
27 /* INCLUDES *****************************************************************/
34 /* FUNCTIONS ****************************************************************/
37 GetComputerIdentifier(PWSTR Identifier
,
38 ULONG IdentifierLength
)
40 OBJECT_ATTRIBUTES ObjectAttributes
;
41 UNICODE_STRING KeyName
;
42 LPCWSTR ComputerIdentifier
;
44 PKEY_FULL_INFORMATION pFullInfo
;
45 ULONG Size
, SizeNeeded
;
48 DPRINT("GetComputerIdentifier() called\n");
50 Size
= sizeof(KEY_FULL_INFORMATION
);
51 pFullInfo
= (PKEY_FULL_INFORMATION
)RtlAllocateHeap(RtlGetProcessHeap(), 0, Size
);
54 DPRINT("RtlAllocateHeap() failed\n");
58 /* Open the processors key */
59 RtlInitUnicodeString(&KeyName
,
60 L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor");
61 InitializeObjectAttributes(&ObjectAttributes
,
67 Status
= NtOpenKey(&ProcessorsKey
,
70 if (!NT_SUCCESS(Status
))
72 DPRINT("NtOpenKey() failed (Status 0x%lx)\n", Status
);
73 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo
);
77 /* Get number of subkeys */
84 NtClose(ProcessorsKey
);
86 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_OVERFLOW
)
88 DPRINT("NtQueryKey() failed (Status 0x%lx)\n", Status
);
89 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo
);
93 /* Find computer identifier */
94 if (pFullInfo
->SubKeys
== 0)
96 /* Something strange happened. No processor detected */
97 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo
);
101 if (pFullInfo
->SubKeys
== 1)
103 /* Computer is mono-CPU */
104 ComputerIdentifier
= L
"PC UP";
108 /* Computer is multi-CPUs */
109 ComputerIdentifier
= L
"PC MP";
112 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo
);
114 /* Copy computer identifier to return buffer */
115 SizeNeeded
= (wcslen(ComputerIdentifier
) + 1) * sizeof(WCHAR
);
116 if (SizeNeeded
> IdentifierLength
)
119 RtlCopyMemory(Identifier
, ComputerIdentifier
, SizeNeeded
);
126 CreateComputerTypeList(HINF InfFile
)
134 WCHAR ComputerIdentifier
[128];
135 WCHAR ComputerKey
[32];
137 /* Get the computer identification */
138 if (!GetComputerIdentifier(ComputerIdentifier
, 128))
140 ComputerIdentifier
[0] = 0;
143 DPRINT("Computer identifier: '%S'\n", ComputerIdentifier
);
145 /* Search for matching device identifier */
146 if (!SetupFindFirstLineW(InfFile
, L
"Map.Computer", NULL
, &Context
))
148 /* FIXME: error message */
154 if (!INF_GetDataField(&Context
, 1, &KeyValue
))
156 /* FIXME: Handle error! */
157 DPRINT("INF_GetDataField() failed\n");
161 DPRINT("KeyValue: %S\n", KeyValue
);
162 if (wcsstr(ComputerIdentifier
, KeyValue
))
164 if (!INF_GetDataField(&Context
, 0, &KeyName
))
166 /* FIXME: Handle error! */
167 DPRINT("INF_GetDataField() failed\n");
171 DPRINT("Computer key: %S\n", KeyName
);
172 wcscpy(ComputerKey
, KeyName
);
174 } while (SetupFindNextLine(&Context
, &Context
));
176 List
= CreateGenericList();
180 if (!SetupFindFirstLineW (InfFile
, L
"Computer", NULL
, &Context
))
182 DestroyGenericList(List
, FALSE
);
188 if (!INF_GetData (&Context
, &KeyName
, &KeyValue
))
190 /* FIXME: Handle error! */
191 DPRINT("INF_GetData() failed\n");
195 UserData
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
197 (wcslen(KeyName
) + 1) * sizeof(WCHAR
));
198 if (UserData
== NULL
)
200 /* FIXME: Handle error! */
203 wcscpy(UserData
, KeyName
);
205 sprintf(Buffer
, "%S", KeyValue
);
206 AppendGenericListEntry(List
, Buffer
, UserData
,
207 _wcsicmp(KeyName
, ComputerKey
) ? FALSE
: TRUE
);
208 } while (SetupFindNextLine(&Context
, &Context
));
215 GetDisplayIdentifier(PWSTR Identifier
,
216 ULONG IdentifierLength
)
218 OBJECT_ATTRIBUTES ObjectAttributes
;
219 UNICODE_STRING KeyName
;
222 HANDLE BusInstanceKey
;
223 HANDLE ControllerKey
;
224 HANDLE ControllerInstanceKey
;
226 ULONG ControllerInstance
;
228 ULONG ReturnedLength
;
229 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
232 DPRINT("GetDisplayIdentifier() called\n");
234 /* Open the bus key */
235 RtlInitUnicodeString(&KeyName
,
236 L
"\\Registry\\Machine\\HARDWARE\\Description\\System\\MultifunctionAdapter");
237 InitializeObjectAttributes(&ObjectAttributes
,
239 OBJ_CASE_INSENSITIVE
,
243 Status
= NtOpenKey(&BusKey
,
246 if (!NT_SUCCESS(Status
))
248 DPRINT("NtOpenKey() failed (Status %lx)\n", Status
);
255 swprintf(Buffer
, L
"%lu", BusInstance
);
256 RtlInitUnicodeString(&KeyName
,
258 InitializeObjectAttributes(&ObjectAttributes
,
260 OBJ_CASE_INSENSITIVE
,
264 Status
= NtOpenKey(&BusInstanceKey
,
267 if (!NT_SUCCESS(Status
))
269 DPRINT("NtOpenKey() failed (Status %lx)\n", Status
);
274 /* Open the controller type key */
275 RtlInitUnicodeString(&KeyName
,
276 L
"DisplayController");
277 InitializeObjectAttributes(&ObjectAttributes
,
279 OBJ_CASE_INSENSITIVE
,
283 Status
= NtOpenKey(&ControllerKey
,
286 if (NT_SUCCESS(Status
))
288 ControllerInstance
= 0;
292 /* Open the pointer controller instance key */
293 swprintf(Buffer
, L
"%lu", ControllerInstance
);
294 RtlInitUnicodeString(&KeyName
,
296 InitializeObjectAttributes(&ObjectAttributes
,
298 OBJ_CASE_INSENSITIVE
,
302 Status
= NtOpenKey(&ControllerInstanceKey
,
305 if (!NT_SUCCESS(Status
))
307 DPRINT("NtOpenKey() failed (Status %lx)\n", Status
);
308 NtClose(ControllerKey
);
309 NtClose(BusInstanceKey
);
314 /* Get controller identifier */
315 RtlInitUnicodeString(&KeyName
,
318 BufferLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
320 ValueInfo
= (KEY_VALUE_PARTIAL_INFORMATION
*) RtlAllocateHeap(RtlGetProcessHeap(),
323 if (ValueInfo
== NULL
)
325 DPRINT("RtlAllocateHeap() failed\n");
326 NtClose(ControllerInstanceKey
);
327 NtClose(ControllerKey
);
328 NtClose(BusInstanceKey
);
333 Status
= NtQueryValueKey(ControllerInstanceKey
,
335 KeyValuePartialInformation
,
339 if (NT_SUCCESS(Status
))
341 DPRINT("Identifier: %S\n", (PWSTR
)ValueInfo
->Data
);
343 BufferLength
= min(ValueInfo
->DataLength
/ sizeof(WCHAR
), IdentifierLength
);
344 RtlCopyMemory (Identifier
,
346 BufferLength
* sizeof(WCHAR
));
347 Identifier
[BufferLength
] = 0;
349 RtlFreeHeap(RtlGetProcessHeap(),
353 NtClose(ControllerInstanceKey
);
354 NtClose(ControllerKey
);
355 NtClose(BusInstanceKey
);
360 NtClose(ControllerInstanceKey
);
362 ControllerInstance
++;
365 NtClose(ControllerKey
);
368 NtClose(BusInstanceKey
);
380 CreateDisplayDriverList(HINF InfFile
)
388 WCHAR DisplayIdentifier
[128];
389 WCHAR DisplayKey
[32];
391 /* Get the display identification */
392 if (!GetDisplayIdentifier(DisplayIdentifier
, 128))
394 DisplayIdentifier
[0] = 0;
397 DPRINT("Display identifier: '%S'\n", DisplayIdentifier
);
399 /* Search for matching device identifier */
400 if (!SetupFindFirstLineW(InfFile
, L
"Map.Display", NULL
, &Context
))
402 /* FIXME: error message */
408 if (!INF_GetDataField(&Context
, 1, &KeyValue
))
410 /* FIXME: Handle error! */
411 DPRINT("INF_GetDataField() failed\n");
415 DPRINT("KeyValue: %S\n", KeyValue
);
416 if (wcsstr(DisplayIdentifier
, KeyValue
))
418 if (!INF_GetDataField(&Context
, 0, &KeyName
))
420 /* FIXME: Handle error! */
421 DPRINT("INF_GetDataField() failed\n");
425 DPRINT("Display key: %S\n", KeyName
);
426 wcscpy(DisplayKey
, KeyName
);
428 } while (SetupFindNextLine(&Context
, &Context
));
430 List
= CreateGenericList();
434 if (!SetupFindFirstLineW (InfFile
, L
"Display", NULL
, &Context
))
436 DestroyGenericList(List
, FALSE
);
442 if (!INF_GetDataField(&Context
, 0, &KeyName
))
444 DPRINT1("INF_GetDataField() failed\n");
448 if (!INF_GetDataField(&Context
, 1, &KeyValue
))
450 DPRINT1("INF_GetDataField() failed\n");
454 UserData
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
456 (wcslen(KeyName
) + 1) * sizeof(WCHAR
));
457 if (UserData
== NULL
)
459 DPRINT1("RtlAllocateHeap() failed\n");
460 DestroyGenericList(List
, TRUE
);
464 wcscpy(UserData
, KeyName
);
466 sprintf(Buffer
, "%S", KeyValue
);
467 AppendGenericListEntry(List
,
470 _wcsicmp(KeyName
, DisplayKey
) ? FALSE
: TRUE
);
471 } while (SetupFindNextLine(&Context
, &Context
));
474 AppendGenericListEntry(List
, "Other display driver", NULL
, TRUE
);
481 ProcessComputerFiles(HINF InfFile
, PGENERIC_LIST List
, PWCHAR
* AdditionalSectionName
)
483 PGENERIC_LIST_ENTRY Entry
;
484 static WCHAR SectionName
[128];
486 DPRINT("ProcessComputerFiles() called\n");
488 Entry
= GetCurrentListEntry(List
);
491 DPRINT("GetCurrentListEntry() failed\n");
495 wcscpy(SectionName
, L
"Files.");
496 wcscat(SectionName
, (const wchar_t*)GetListEntryUserData(Entry
));
497 *AdditionalSectionName
= SectionName
;
504 ProcessDisplayRegistry(HINF InfFile
, PGENERIC_LIST List
)
506 PGENERIC_LIST_ENTRY Entry
;
513 ULONG Width
, Height
, Bpp
;
515 DPRINT("ProcessDisplayRegistry() called\n");
517 Entry
= GetCurrentListEntry(List
);
520 DPRINT("GetCurrentListEntry() failed\n");
524 if (!SetupFindFirstLineW(InfFile
, L
"Display", (WCHAR
*)GetListEntryUserData(Entry
), &Context
))
526 DPRINT("SetupFindFirstLineW() failed\n");
530 /* Enable the right driver */
531 if (!INF_GetDataField(&Context
, 3, &ServiceName
))
533 DPRINT("INF_GetDataField() failed\n");
537 ASSERT(wcslen(ServiceName
) < 10);
538 DPRINT("Service name: %S\n", ServiceName
);
541 Status
= RtlWriteRegistryValue(RTL_REGISTRY_SERVICES
,
548 if (!NT_SUCCESS(Status
))
550 DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status
);
554 /* Set the resolution */
555 swprintf(RegPath
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\%s\\Device0", ServiceName
);
557 if (!INF_GetDataField(&Context
, 4, &Buffer
))
559 DPRINT("INF_GetDataField() failed\n");
563 Width
= wcstoul(Buffer
, NULL
, 10);
564 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
566 L
"DefaultSettings.XResolution",
570 if (!NT_SUCCESS(Status
))
572 DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status
);
576 if (!INF_GetDataField(&Context
, 5, &Buffer
))
578 DPRINT("INF_GetDataField() failed\n");
582 Height
= wcstoul(Buffer
, 0, 0);
583 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
585 L
"DefaultSettings.YResolution",
589 if (!NT_SUCCESS(Status
))
591 DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status
);
595 if (!INF_GetDataField(&Context
, 6, &Buffer
))
597 DPRINT("INF_GetDataField() failed\n");
601 Bpp
= wcstoul(Buffer
, 0, 0);
602 Status
= RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE
,
604 L
"DefaultSettings.BitsPerPel",
608 if (!NT_SUCCESS(Status
))
610 DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status
);
614 DPRINT("ProcessDisplayRegistry() done\n");
621 ProcessLocaleRegistry(PGENERIC_LIST List
)
623 PGENERIC_LIST_ENTRY Entry
;
625 OBJECT_ATTRIBUTES ObjectAttributes
;
626 UNICODE_STRING KeyName
;
627 UNICODE_STRING ValueName
;
632 Entry
= GetCurrentListEntry(List
);
636 LanguageId
= (PWCHAR
)GetListEntryUserData(Entry
);
637 if (LanguageId
== NULL
)
640 /* Open the NLS language key */
641 RtlInitUnicodeString(&KeyName
,
642 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language");
644 InitializeObjectAttributes(&ObjectAttributes
,
646 OBJ_CASE_INSENSITIVE
,
650 Status
= NtOpenKey(&KeyHandle
,
654 if (!NT_SUCCESS(Status
))
656 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status
);
660 /* Set default language */
661 RtlInitUnicodeString(&ValueName
,
664 Status
= NtSetValueKey(KeyHandle
,
668 (PVOID
)(LanguageId
+ 4),
670 if (!NT_SUCCESS(Status
))
672 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
677 /* Set install language */
678 RtlInitUnicodeString(&ValueName
,
680 Status
= NtSetValueKey (KeyHandle
,
684 (PVOID
)(LanguageId
+ 4),
686 if (!NT_SUCCESS(Status
))
688 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
700 CreateKeyboardDriverList(HINF InfFile
)
709 List
= CreateGenericList();
713 if (!SetupFindFirstLineW (InfFile
, L
"Keyboard", NULL
, &Context
))
715 DestroyGenericList(List
, FALSE
);
721 if (!INF_GetData (&Context
, &KeyName
, &KeyValue
))
723 /* FIXME: Handle error! */
724 DPRINT("INF_GetData() failed\n");
728 UserData
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
730 (wcslen(KeyName
) + 1) * sizeof(WCHAR
));
731 if (UserData
== NULL
)
733 /* FIXME: Handle error! */
736 wcscpy(UserData
, KeyName
);
738 sprintf(Buffer
, "%S", KeyValue
);
739 AppendGenericListEntry(List
, Buffer
, UserData
, FALSE
);
740 } while (SetupFindNextLine(&Context
, &Context
));
745 ULONG DefaultLanguageIndex
= 0;
748 GetDefaultLanguageIndex(VOID
)
750 return DefaultLanguageIndex
;
754 CreateLanguageList(HINF InfFile
, WCHAR
* DefaultLanguage
)
764 /* Get default language id */
765 if (!SetupFindFirstLineW (InfFile
, L
"NLS", L
"DefaultLanguage", &Context
))
768 if (!INF_GetData (&Context
, NULL
, &KeyValue
))
771 wcscpy(DefaultLanguage
, KeyValue
);
773 SelectedLanguageId
= KeyValue
;
775 List
= CreateGenericList();
779 if (!SetupFindFirstLineW (InfFile
, L
"Language", NULL
, &Context
))
781 DestroyGenericList(List
, FALSE
);
787 if (!INF_GetData (&Context
, &KeyName
, &KeyValue
))
789 /* FIXME: Handle error! */
790 DPRINT("INF_GetData() failed\n");
794 UserData
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
796 (wcslen(KeyName
) + 1) * sizeof(WCHAR
));
797 if (UserData
== NULL
)
799 /* FIXME: Handle error! */
802 wcscpy(UserData
, KeyName
);
804 if (!_wcsicmp(KeyName
, DefaultLanguage
)) DefaultLanguageIndex
= uIndex
;
806 sprintf(Buffer
, "%S", KeyValue
);
807 AppendGenericListEntry(List
,
812 } while (SetupFindNextLine(&Context
, &Context
));
818 CreateKeyboardLayoutList(HINF InfFile
, WCHAR
* DefaultKBLayout
)
826 const MUI_LAYOUTS
* LayoutsList
;
828 BOOL KeyboardLayoutsFound
= FALSE
;
830 /* Get default layout id */
831 if (!SetupFindFirstLineW (InfFile
, L
"NLS", L
"DefaultLayout", &Context
))
834 if (!INF_GetData (&Context
, NULL
, &KeyValue
))
837 wcscpy(DefaultKBLayout
, KeyValue
);
839 List
= CreateGenericList();
843 LayoutsList
= MUIGetLayoutsList();
847 if (!SetupFindFirstLineW(InfFile
, L
"KeyboardLayout", NULL
, &Context
))
849 DestroyGenericList(List
, FALSE
);
855 if (!INF_GetData (&Context
, &KeyName
, &KeyValue
))
857 /* FIXME: Handle error! */
858 DPRINT("INF_GetData() failed\n");
859 DestroyGenericList(List
, FALSE
);
863 if (_wcsicmp(LayoutsList
[uIndex
].LayoutID
, KeyName
) == 0)
865 UserData
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
867 (wcslen(KeyName
) + 1) * sizeof(WCHAR
));
869 if (UserData
== NULL
)
871 /* FIXME: Handle error! */
872 DPRINT("RtlAllocateHeap() failed\n");
873 DestroyGenericList(List
, FALSE
);
877 wcscpy(UserData
, KeyName
);
879 sprintf(Buffer
, "%S", KeyValue
);
880 AppendGenericListEntry(List
,
883 _wcsicmp(KeyName
, DefaultKBLayout
) ? FALSE
: TRUE
);
884 KeyboardLayoutsFound
= TRUE
;
887 } while (SetupFindNextLine(&Context
, &Context
));
891 } while (LayoutsList
[uIndex
].LangID
!= NULL
);
893 /* FIXME: Handle this case */
894 if (!KeyboardLayoutsFound
)
896 DPRINT1("No keyboard layouts have been found\n");
897 DestroyGenericList(List
, FALSE
);
905 ProcessKeyboardLayoutRegistry(PGENERIC_LIST List
)
907 PGENERIC_LIST_ENTRY Entry
;
909 const MUI_LAYOUTS
* LayoutsList
;
910 MUI_LAYOUTS NewLayoutsList
[20];
914 Entry
= GetCurrentListEntry(List
);
918 LayoutId
= (PWCHAR
)GetListEntryUserData(Entry
);
919 if (LayoutId
== NULL
)
922 LayoutsList
= MUIGetLayoutsList();
924 if (_wcsicmp(LayoutsList
[0].LayoutID
, LayoutId
) != 0)
926 for (uIndex
= 1; LayoutsList
[uIndex
].LangID
!= NULL
; uIndex
++)
928 if (_wcsicmp(LayoutsList
[uIndex
].LayoutID
, LayoutId
) == 0)
934 NewLayoutsList
[uIndex
].LangID
= LayoutsList
[uIndex
].LangID
;
935 NewLayoutsList
[uIndex
].LayoutID
= LayoutsList
[uIndex
].LayoutID
;
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
;
945 return AddKbLayoutsToRegistry(NewLayoutsList
);
954 ProcessKeyboardLayoutFiles(PGENERIC_LIST List
)
963 OBJECT_ATTRIBUTES ObjectAttributes
;
964 UNICODE_STRING KeyName
;
965 UNICODE_STRING ValueName
;
967 WCHAR szKeyName
[] = L
"\\Registry\\User\\.DEFAULT\\Control Panel\\International\\Geo";
968 WCHAR szValueName
[] = L
"Nation";
970 RtlInitUnicodeString(&KeyName
,
972 InitializeObjectAttributes(&ObjectAttributes
,
974 OBJ_CASE_INSENSITIVE
,
978 Status
= NtOpenKey(&KeyHandle
,
981 if(!NT_SUCCESS(Status
))
983 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status
);
986 RtlInitUnicodeString(&ValueName
, szValueName
);
987 Status
= NtSetValueKey(KeyHandle
,
992 (wcslen(Id
) * sizeof(WCHAR
)));
993 if (!NT_SUCCESS(Status
))
995 DPRINT1("NtSetValueKey() failed (Status = %lx)\n", Status
);