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 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.
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
,
244 KEY_ENUMERATE_SUB_KEYS
,
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
,
265 KEY_ENUMERATE_SUB_KEYS
,
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
,
284 KEY_ENUMERATE_SUB_KEYS
,
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 /* Skip first 4 zeroes */
641 if (wcslen(LanguageId
) >= 4)
644 /* Open the NLS language key */
645 RtlInitUnicodeString(&KeyName
,
646 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language");
648 InitializeObjectAttributes(&ObjectAttributes
,
650 OBJ_CASE_INSENSITIVE
,
654 Status
= NtOpenKey(&KeyHandle
,
658 if (!NT_SUCCESS(Status
))
660 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status
);
664 /* Set default language */
665 RtlInitUnicodeString(&ValueName
,
667 Status
= NtSetValueKey(KeyHandle
,
672 (wcslen(LanguageId
) + 1) * sizeof(WCHAR
));
673 if (!NT_SUCCESS(Status
))
675 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
680 /* Set install language */
681 RtlInitUnicodeString(&ValueName
,
683 Status
= NtSetValueKey (KeyHandle
,
688 (wcslen(LanguageId
) + 1) * sizeof(WCHAR
));
690 if (!NT_SUCCESS(Status
))
692 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
701 CreateKeyboardDriverList(HINF InfFile
)
710 List
= CreateGenericList();
714 if (!SetupFindFirstLineW (InfFile
, L
"Keyboard", NULL
, &Context
))
716 DestroyGenericList(List
, FALSE
);
722 if (!INF_GetData (&Context
, &KeyName
, &KeyValue
))
724 /* FIXME: Handle error! */
725 DPRINT("INF_GetData() failed\n");
729 UserData
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
731 (wcslen(KeyName
) + 1) * sizeof(WCHAR
));
732 if (UserData
== NULL
)
734 /* FIXME: Handle error! */
737 wcscpy(UserData
, KeyName
);
739 sprintf(Buffer
, "%S", KeyValue
);
740 AppendGenericListEntry(List
, Buffer
, UserData
, FALSE
);
741 } while (SetupFindNextLine(&Context
, &Context
));
746 ULONG DefaultLanguageIndex
= 0;
749 GetDefaultLanguageIndex(VOID
)
751 return DefaultLanguageIndex
;
755 CreateLanguageList(HINF InfFile
, WCHAR
* DefaultLanguage
)
765 /* Get default language id */
766 if (!SetupFindFirstLineW (InfFile
, L
"NLS", L
"DefaultLanguage", &Context
))
769 if (!INF_GetData (&Context
, NULL
, &KeyValue
))
772 wcscpy(DefaultLanguage
, KeyValue
);
774 SelectedLanguageId
= KeyValue
;
776 List
= CreateGenericList();
780 if (!SetupFindFirstLineW (InfFile
, L
"Language", NULL
, &Context
))
782 DestroyGenericList(List
, FALSE
);
788 if (!INF_GetData (&Context
, &KeyName
, &KeyValue
))
790 /* FIXME: Handle error! */
791 DPRINT("INF_GetData() failed\n");
795 UserData
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
797 (wcslen(KeyName
) + 1) * sizeof(WCHAR
));
798 if (UserData
== NULL
)
800 /* FIXME: Handle error! */
803 wcscpy(UserData
, KeyName
);
805 if (!_wcsicmp(KeyName
, DefaultLanguage
)) DefaultLanguageIndex
= uIndex
;
807 sprintf(Buffer
, "%S", KeyValue
);
808 AppendGenericListEntry(List
,
813 } while (SetupFindNextLine(&Context
, &Context
));
819 CreateKeyboardLayoutList(HINF InfFile
, WCHAR
* DefaultKBLayout
)
827 const MUI_LAYOUTS
* LayoutsList
;
829 BOOL KeyboardLayoutsFound
= FALSE
;
831 /* Get default layout id */
832 if (!SetupFindFirstLineW (InfFile
, L
"NLS", L
"DefaultLayout", &Context
))
835 if (!INF_GetData (&Context
, NULL
, &KeyValue
))
838 wcscpy(DefaultKBLayout
, KeyValue
);
840 List
= CreateGenericList();
844 LayoutsList
= MUIGetLayoutsList();
848 if (!SetupFindFirstLineW(InfFile
, L
"KeyboardLayout", NULL
, &Context
))
850 DestroyGenericList(List
, FALSE
);
856 if (!INF_GetData (&Context
, &KeyName
, &KeyValue
))
858 /* FIXME: Handle error! */
859 DPRINT("INF_GetData() failed\n");
860 DestroyGenericList(List
, FALSE
);
864 if (_wcsicmp(LayoutsList
[uIndex
].LayoutID
, KeyName
) == 0)
866 UserData
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
868 (wcslen(KeyName
) + 1) * sizeof(WCHAR
));
870 if (UserData
== NULL
)
872 /* FIXME: Handle error! */
873 DPRINT("RtlAllocateHeap() failed\n");
874 DestroyGenericList(List
, FALSE
);
878 wcscpy(UserData
, KeyName
);
880 sprintf(Buffer
, "%S", KeyValue
);
881 AppendGenericListEntry(List
,
884 _wcsicmp(KeyName
, DefaultKBLayout
) ? FALSE
: TRUE
);
885 KeyboardLayoutsFound
= TRUE
;
888 } while (SetupFindNextLine(&Context
, &Context
));
892 } while (LayoutsList
[uIndex
].LangID
!= NULL
);
894 /* FIXME: Handle this case */
895 if (!KeyboardLayoutsFound
)
897 DPRINT1("No keyboard layouts have been found\n");
898 DestroyGenericList(List
, FALSE
);
906 ProcessKeyboardLayoutRegistry(PGENERIC_LIST List
)
908 PGENERIC_LIST_ENTRY Entry
;
910 const MUI_LAYOUTS
* LayoutsList
;
911 MUI_LAYOUTS NewLayoutsList
[20];
915 Entry
= GetCurrentListEntry(List
);
919 LayoutId
= (PWCHAR
)GetListEntryUserData(Entry
);
920 if (LayoutId
== NULL
)
923 LayoutsList
= MUIGetLayoutsList();
925 if (_wcsicmp(LayoutsList
[0].LayoutID
, LayoutId
) != 0)
927 for (uIndex
= 1; LayoutsList
[uIndex
].LangID
!= NULL
; uIndex
++)
929 if (_wcsicmp(LayoutsList
[uIndex
].LayoutID
, LayoutId
) == 0)
935 NewLayoutsList
[uIndex
].LangID
= LayoutsList
[uIndex
].LangID
;
936 NewLayoutsList
[uIndex
].LayoutID
= LayoutsList
[uIndex
].LayoutID
;
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
;
946 return AddKbLayoutsToRegistry(NewLayoutsList
);
955 ProcessKeyboardLayoutFiles(PGENERIC_LIST List
)
964 OBJECT_ATTRIBUTES ObjectAttributes
;
965 UNICODE_STRING KeyName
;
966 UNICODE_STRING ValueName
;
968 WCHAR szKeyName
[] = L
"\\Registry\\User\\.DEFAULT\\Control Panel\\International\\Geo";
969 WCHAR szValueName
[] = L
"Nation";
971 RtlInitUnicodeString(&KeyName
,
973 InitializeObjectAttributes(&ObjectAttributes
,
975 OBJ_CASE_INSENSITIVE
,
979 Status
= NtOpenKey(&KeyHandle
,
982 if(!NT_SUCCESS(Status
))
984 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status
);
987 RtlInitUnicodeString(&ValueName
, szValueName
);
988 Status
= NtSetValueKey(KeyHandle
,
993 (wcslen(Id
) + 1) * sizeof(WCHAR
));
995 if (!NT_SUCCESS(Status
))
997 DPRINT1("NtSetValueKey() failed (Status = %lx)\n", Status
);