[RAPPS]
[reactos.git] / reactos / base / setup / usetup / settings.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /* COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS text-mode setup
21 * FILE: base/setup/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 (!pValueInformation)
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 DPRINT1("GetCurrentListEntry() failed\n");
695 return FALSE;
696 }
697
698 if (!SetupFindFirstLineW(InfFile, L"Display", (WCHAR*)GetListEntryUserData(Entry), &Context))
699 {
700 DPRINT1("SetupFindFirstLineW() failed\n");
701 return FALSE;
702 }
703
704 /* Enable the right driver */
705 if (!INF_GetDataField(&Context, 3, &ServiceName))
706 {
707 DPRINT1("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 DPRINT1("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 DPRINT1("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 DPRINT1("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
746 return FALSE;
747 }
748
749 if (!INF_GetDataField(&Context, 5, &Buffer))
750 {
751 DPRINT1("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 DPRINT1("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
765 return FALSE;
766 }
767
768 if (!INF_GetDataField(&Context, 6, &Buffer))
769 {
770 DPRINT1("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 DPRINT1("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 DPRINT("LanguageId: %S\n", LanguageId);
815
816 /* Open the default users locale key */
817 RtlInitUnicodeString(&KeyName,
818 L"\\Registry\\User\\.DEFAULT\\Control Panel\\International");
819
820 InitializeObjectAttributes(&ObjectAttributes,
821 &KeyName,
822 OBJ_CASE_INSENSITIVE,
823 NULL,
824 NULL);
825
826 Status = NtOpenKey(&KeyHandle,
827 KEY_SET_VALUE,
828 &ObjectAttributes);
829 if (!NT_SUCCESS(Status))
830 {
831 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
832 return FALSE;
833 }
834
835 /* Set default user locale */
836 RtlInitUnicodeString(&ValueName,
837 L"Locale");
838 Status = NtSetValueKey(KeyHandle,
839 &ValueName,
840 0,
841 REG_SZ,
842 (PVOID)LanguageId,
843 (wcslen(LanguageId) + 1) * sizeof(WCHAR));
844 NtClose(KeyHandle);
845 if (!NT_SUCCESS(Status))
846 {
847 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
848 return FALSE;
849 }
850
851 /* Skip first 4 zeroes */
852 if (wcslen(LanguageId) >= 4)
853 LanguageId += 4;
854
855 /* Open the NLS language key */
856 RtlInitUnicodeString(&KeyName,
857 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language");
858
859 InitializeObjectAttributes(&ObjectAttributes,
860 &KeyName,
861 OBJ_CASE_INSENSITIVE,
862 NULL,
863 NULL);
864
865 Status = NtOpenKey(&KeyHandle,
866 KEY_SET_VALUE,
867 &ObjectAttributes);
868 if (!NT_SUCCESS(Status))
869 {
870 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
871 return FALSE;
872 }
873
874 /* Set default language */
875 RtlInitUnicodeString(&ValueName,
876 L"Default");
877 Status = NtSetValueKey(KeyHandle,
878 &ValueName,
879 0,
880 REG_SZ,
881 (PVOID)LanguageId,
882 (wcslen(LanguageId) + 1) * sizeof(WCHAR));
883 if (!NT_SUCCESS(Status))
884 {
885 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
886 NtClose(KeyHandle);
887 return FALSE;
888 }
889
890 /* Set install language */
891 RtlInitUnicodeString(&ValueName,
892 L"InstallLanguage");
893 Status = NtSetValueKey (KeyHandle,
894 &ValueName,
895 0,
896 REG_SZ,
897 (PVOID)LanguageId,
898 (wcslen(LanguageId) + 1) * sizeof(WCHAR));
899 NtClose(KeyHandle);
900 if (!NT_SUCCESS(Status))
901 {
902 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
903 return FALSE;
904 }
905
906 return TRUE;
907 }
908
909
910 PGENERIC_LIST
911 CreateKeyboardDriverList(
912 HINF InfFile)
913 {
914 CHAR Buffer[128];
915 PGENERIC_LIST List;
916 INFCONTEXT Context;
917 PWCHAR KeyName;
918 PWCHAR KeyValue;
919 PWCHAR UserData;
920
921 List = CreateGenericList();
922 if (List == NULL)
923 return NULL;
924
925 if (!SetupFindFirstLineW (InfFile, L"Keyboard", NULL, &Context))
926 {
927 DestroyGenericList(List, FALSE);
928 return NULL;
929 }
930
931 do
932 {
933 if (!INF_GetData (&Context, &KeyName, &KeyValue))
934 {
935 /* FIXME: Handle error! */
936 DPRINT("INF_GetData() failed\n");
937 break;
938 }
939
940 UserData = (WCHAR*)RtlAllocateHeap(ProcessHeap,
941 0,
942 (wcslen(KeyName) + 1) * sizeof(WCHAR));
943 if (UserData == NULL)
944 {
945 /* FIXME: Handle error! */
946 }
947
948 wcscpy(UserData, KeyName);
949
950 sprintf(Buffer, "%S", KeyValue);
951 AppendGenericListEntry(List, Buffer, UserData, FALSE);
952 } while (SetupFindNextLine(&Context, &Context));
953
954 return List;
955 }
956
957
958 ULONG
959 GetDefaultLanguageIndex(VOID)
960 {
961 return DefaultLanguageIndex;
962 }
963
964
965 PGENERIC_LIST
966 CreateLanguageList(
967 HINF InfFile,
968 WCHAR *DefaultLanguage)
969 {
970 CHAR Buffer[128];
971 PGENERIC_LIST List;
972 INFCONTEXT Context;
973 PWCHAR KeyName;
974 PWCHAR KeyValue;
975 PWCHAR UserData = NULL;
976 ULONG uIndex = 0;
977
978 /* Get default language id */
979 if (!SetupFindFirstLineW (InfFile, L"NLS", L"DefaultLanguage", &Context))
980 return NULL;
981
982 if (!INF_GetData (&Context, NULL, &KeyValue))
983 return NULL;
984
985 wcscpy(DefaultLanguage, KeyValue);
986
987 SelectedLanguageId = KeyValue;
988
989 List = CreateGenericList();
990 if (List == NULL)
991 return NULL;
992
993 if (!SetupFindFirstLineW (InfFile, L"Language", NULL, &Context))
994 {
995 DestroyGenericList(List, FALSE);
996 return NULL;
997 }
998
999 do
1000 {
1001 if (!INF_GetData (&Context, &KeyName, &KeyValue))
1002 {
1003 /* FIXME: Handle error! */
1004 DPRINT("INF_GetData() failed\n");
1005 break;
1006 }
1007
1008 if (IsLanguageAvailable(KeyName))
1009 {
1010
1011 UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap,
1012 0,
1013 (wcslen(KeyName) + 1) * sizeof(WCHAR));
1014 if (UserData == NULL)
1015 {
1016 /* FIXME: Handle error! */
1017 }
1018
1019 wcscpy(UserData, KeyName);
1020
1021 if (!_wcsicmp(KeyName, DefaultLanguage))
1022 DefaultLanguageIndex = uIndex;
1023
1024 sprintf(Buffer, "%S", KeyValue);
1025 AppendGenericListEntry(List,
1026 Buffer,
1027 UserData,
1028 FALSE);
1029 uIndex++;
1030 }
1031 } while (SetupFindNextLine(&Context, &Context));
1032
1033 /* Only one language available, make it the default one */
1034 if(uIndex == 1 && UserData != NULL)
1035 {
1036 DefaultLanguageIndex = 0;
1037 wcscpy(DefaultLanguage, UserData);
1038 }
1039
1040 return List;
1041 }
1042
1043
1044 PGENERIC_LIST
1045 CreateKeyboardLayoutList(
1046 HINF InfFile,
1047 WCHAR *DefaultKBLayout)
1048 {
1049 CHAR Buffer[128];
1050 PGENERIC_LIST List;
1051 INFCONTEXT Context;
1052 PWCHAR KeyName;
1053 PWCHAR KeyValue;
1054 PWCHAR UserData;
1055 const MUI_LAYOUTS * LayoutsList;
1056 ULONG uIndex = 0;
1057 BOOL KeyboardLayoutsFound = FALSE;
1058
1059 /* Get default layout id */
1060 if (!SetupFindFirstLineW (InfFile, L"NLS", L"DefaultLayout", &Context))
1061 return NULL;
1062
1063 if (!INF_GetData (&Context, NULL, &KeyValue))
1064 return NULL;
1065
1066 wcscpy(DefaultKBLayout, KeyValue);
1067
1068 List = CreateGenericList();
1069 if (List == NULL)
1070 return NULL;
1071
1072 LayoutsList = MUIGetLayoutsList();
1073
1074 do
1075 {
1076 if (!SetupFindFirstLineW(InfFile, L"KeyboardLayout", NULL, &Context))
1077 {
1078 DestroyGenericList(List, FALSE);
1079 return NULL;
1080 }
1081
1082 do
1083 {
1084 if (!INF_GetData (&Context, &KeyName, &KeyValue))
1085 {
1086 /* FIXME: Handle error! */
1087 DPRINT("INF_GetData() failed\n");
1088 DestroyGenericList(List, FALSE);
1089 return NULL;
1090 }
1091
1092 {
1093 UserData = (WCHAR*)RtlAllocateHeap(ProcessHeap,
1094 0,
1095 (wcslen(KeyName) + 1) * sizeof(WCHAR));
1096 if (UserData == NULL)
1097 {
1098 /* FIXME: Handle error! */
1099 DPRINT("RtlAllocateHeap() failed\n");
1100 DestroyGenericList(List, FALSE);
1101 return NULL;
1102 }
1103
1104 wcscpy(UserData, KeyName);
1105
1106 sprintf(Buffer, "%S", KeyValue);
1107 AppendGenericListEntry(List,
1108 Buffer,
1109 UserData,
1110 _wcsicmp(KeyName, DefaultKBLayout) ? FALSE : TRUE);
1111 KeyboardLayoutsFound = TRUE;
1112 }
1113
1114 } while (SetupFindNextLine(&Context, &Context));
1115
1116 uIndex++;
1117
1118 } while (LayoutsList[uIndex].LangID != NULL);
1119
1120 /* FIXME: Handle this case */
1121 if (!KeyboardLayoutsFound)
1122 {
1123 DPRINT1("No keyboard layouts have been found\n");
1124 DestroyGenericList(List, FALSE);
1125 return NULL;
1126 }
1127
1128 return List;
1129 }
1130
1131
1132 BOOLEAN
1133 ProcessKeyboardLayoutRegistry(
1134 PGENERIC_LIST List)
1135 {
1136 PGENERIC_LIST_ENTRY Entry;
1137 PWCHAR LayoutId;
1138 const MUI_LAYOUTS * LayoutsList;
1139 MUI_LAYOUTS NewLayoutsList[20];
1140 ULONG uIndex;
1141 ULONG uOldPos = 0;
1142
1143 Entry = GetCurrentListEntry(List);
1144 if (Entry == NULL)
1145 return FALSE;
1146
1147 LayoutId = (PWCHAR)GetListEntryUserData(Entry);
1148 if (LayoutId == NULL)
1149 return FALSE;
1150
1151 LayoutsList = MUIGetLayoutsList();
1152
1153 if (_wcsicmp(LayoutsList[0].LayoutID, LayoutId) != 0)
1154 {
1155 for (uIndex = 1; LayoutsList[uIndex].LangID != NULL; uIndex++)
1156 {
1157 if (_wcsicmp(LayoutsList[uIndex].LayoutID, LayoutId) == 0)
1158 {
1159 uOldPos = uIndex;
1160 continue;
1161 }
1162
1163 NewLayoutsList[uIndex].LangID = LayoutsList[uIndex].LangID;
1164 NewLayoutsList[uIndex].LayoutID = LayoutsList[uIndex].LayoutID;
1165 }
1166
1167 NewLayoutsList[uIndex].LangID = NULL;
1168 NewLayoutsList[uIndex].LayoutID = NULL;
1169 NewLayoutsList[uOldPos].LangID = LayoutsList[0].LangID;
1170 NewLayoutsList[uOldPos].LayoutID = LayoutsList[0].LayoutID;
1171 NewLayoutsList[0].LangID = LayoutsList[uOldPos].LangID;
1172 NewLayoutsList[0].LayoutID = LayoutsList[uOldPos].LayoutID;
1173
1174 return AddKbLayoutsToRegistry(NewLayoutsList);
1175 }
1176
1177 return TRUE;
1178 }
1179
1180
1181 #if 0
1182 BOOLEAN
1183 ProcessKeyboardLayoutFiles(
1184 PGENERIC_LIST List)
1185 {
1186 return TRUE;
1187 }
1188 #endif
1189
1190
1191 BOOLEAN
1192 SetGeoID(
1193 PWCHAR Id)
1194 {
1195 OBJECT_ATTRIBUTES ObjectAttributes;
1196 UNICODE_STRING KeyName;
1197 UNICODE_STRING ValueName;
1198 HANDLE KeyHandle;
1199 WCHAR szKeyName[] = L"\\Registry\\User\\.DEFAULT\\Control Panel\\International\\Geo";
1200 WCHAR szValueName[] = L"Nation";
1201 NTSTATUS Status;
1202
1203 RtlInitUnicodeString(&KeyName,
1204 szKeyName);
1205 InitializeObjectAttributes(&ObjectAttributes,
1206 &KeyName,
1207 OBJ_CASE_INSENSITIVE,
1208 NULL,
1209 NULL);
1210
1211 Status = NtOpenKey(&KeyHandle,
1212 KEY_SET_VALUE,
1213 &ObjectAttributes);
1214 if(!NT_SUCCESS(Status))
1215 {
1216 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
1217 return FALSE;
1218 }
1219
1220 RtlInitUnicodeString(&ValueName, szValueName);
1221 Status = NtSetValueKey(KeyHandle,
1222 &ValueName,
1223 0,
1224 REG_SZ,
1225 (PVOID)Id,
1226 (wcslen(Id) + 1) * sizeof(WCHAR));
1227 NtClose(KeyHandle);
1228 if (!NT_SUCCESS(Status))
1229 {
1230 DPRINT1("NtSetValueKey() failed (Status = %lx)\n", Status);
1231 return FALSE;
1232 }
1233
1234 return TRUE;
1235 }
1236
1237 /* EOF */