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