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