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