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