Use inflib
[reactos.git] / reactos / subsys / system / 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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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 * PROGRAMMER: Eric Kohl
24 */
25
26 /* INCLUDES *****************************************************************/
27
28 #include <usetup.h>
29
30 #define NDEBUG
31 #include <debug.h>
32
33 /* FUNCTIONS ****************************************************************/
34
35 static BOOLEAN
36 GetComputerIdentifier(PWSTR Identifier,
37 ULONG IdentifierLength)
38 {
39 OBJECT_ATTRIBUTES ObjectAttributes;
40 UNICODE_STRING KeyName;
41 LPCWSTR ComputerIdentifier;
42 HANDLE ProcessorsKey;
43 PKEY_FULL_INFORMATION pFullInfo;
44 ULONG Size, SizeNeeded;
45 NTSTATUS Status;
46
47 DPRINT("GetComputerIdentifier() called\n");
48
49 Size = sizeof(KEY_FULL_INFORMATION);
50 pFullInfo = (PKEY_FULL_INFORMATION)RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
51 if (!pFullInfo)
52 {
53 DPRINT("RtlAllocateHeap() failed\n");
54 return FALSE;
55 }
56
57 /* Open the processors key */
58 RtlInitUnicodeString(&KeyName,
59 L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor");
60 InitializeObjectAttributes(&ObjectAttributes,
61 &KeyName,
62 OBJ_CASE_INSENSITIVE,
63 NULL,
64 NULL);
65 Status = NtOpenKey(&ProcessorsKey,
66 KEY_QUERY_VALUE ,
67 &ObjectAttributes);
68 if (!NT_SUCCESS(Status))
69 {
70 DPRINT("NtOpenKey() failed (Status 0x%lx)\n", Status);
71 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
72 return FALSE;
73 }
74
75 /* Get number of subkeys */
76 Status = NtQueryKey(
77 ProcessorsKey,
78 KeyFullInformation,
79 pFullInfo,
80 Size,
81 &Size);
82 NtClose(ProcessorsKey);
83 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
84 {
85 DPRINT("NtQueryKey() failed (Status 0x%lx)\n", Status);
86 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
87 return FALSE;
88 }
89
90 /* Find computer identifier */
91 if (pFullInfo->SubKeys == 0)
92 {
93 /* Something strange happened. No processor detected */
94 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
95 return FALSE;
96 }
97
98 if (pFullInfo->SubKeys == 1)
99 {
100 /* Computer is mono-CPU */
101 ComputerIdentifier = L"PC UP";
102 }
103 else
104 {
105 /* Computer is multi-CPUs */
106 ComputerIdentifier = L"PC MP";
107 }
108 RtlFreeHeap(RtlGetProcessHeap(), 0, pFullInfo);
109
110 /* Copy computer identifier to return buffer */
111 SizeNeeded = (wcslen(ComputerIdentifier) + 1) * sizeof(WCHAR);
112 if (SizeNeeded > IdentifierLength)
113 return FALSE;
114 RtlCopyMemory(Identifier, ComputerIdentifier, SizeNeeded);
115 return TRUE;
116 }
117
118
119 PGENERIC_LIST
120 CreateComputerTypeList(HINF InfFile)
121 {
122 CHAR Buffer[128];
123 PGENERIC_LIST List;
124 PINFCONTEXT Context;
125 PWCHAR KeyName;
126 PWCHAR KeyValue;
127 PWCHAR UserData;
128 WCHAR ComputerIdentifier[128];
129 WCHAR ComputerKey[32];
130
131 /* Get the computer identification */
132 if (!GetComputerIdentifier(ComputerIdentifier, 128))
133 {
134 ComputerIdentifier[0] = 0;
135 }
136
137 DPRINT("Computer identifier: '%S'\n", ComputerIdentifier);
138
139 /* Search for matching device identifier */
140 if (!InfFindFirstLine(InfFile, L"Map.Computer", NULL, &Context))
141 {
142 /* FIXME: error message */
143 return NULL;
144 }
145
146 do
147 {
148 if (!InfGetDataField(Context, 1, &KeyValue))
149 {
150 /* FIXME: Handle error! */
151 DPRINT("InfGetDataField() failed\n");
152 return NULL;
153 }
154
155 DPRINT("KeyValue: %S\n", KeyValue);
156 if (wcsstr(ComputerIdentifier, KeyValue))
157 {
158 if (!InfGetDataField(Context, 0, &KeyName))
159 {
160 /* FIXME: Handle error! */
161 DPRINT("InfGetDataField() failed\n");
162 return NULL;
163 }
164
165 DPRINT("Computer key: %S\n", KeyName);
166 wcscpy(ComputerKey, KeyName);
167 }
168 }
169 while (InfFindNextLine(Context, Context));
170 InfFreeContext(Context);
171
172 List = CreateGenericList();
173 if (List == NULL)
174 return NULL;
175
176 if (!InfFindFirstLine (InfFile, L"Computer", NULL, &Context))
177 {
178 DestroyGenericList(List, FALSE);
179 return NULL;
180 }
181
182 do
183 {
184 if (!InfGetData (Context, &KeyName, &KeyValue))
185 {
186 /* FIXME: Handle error! */
187 DPRINT("InfGetData() failed\n");
188 break;
189 }
190
191 UserData = RtlAllocateHeap(ProcessHeap,
192 0,
193 (wcslen(KeyName) + 1) * sizeof(WCHAR));
194 if (UserData == NULL)
195 {
196 /* FIXME: Handle error! */
197 }
198
199 wcscpy(UserData, KeyName);
200
201 sprintf(Buffer, "%S", KeyValue);
202 AppendGenericListEntry(List, Buffer, UserData,
203 _wcsicmp(KeyName, ComputerKey) ? FALSE : TRUE);
204 }
205 while (InfFindNextLine(Context, Context));
206 InfFreeContext(Context);
207
208 return List;
209 }
210
211
212 static BOOLEAN
213 GetDisplayIdentifier(PWSTR Identifier,
214 ULONG IdentifierLength)
215 {
216 OBJECT_ATTRIBUTES ObjectAttributes;
217 UNICODE_STRING KeyName;
218 WCHAR Buffer[32];
219 HANDLE BusKey;
220 HANDLE BusInstanceKey;
221 HANDLE ControllerKey;
222 HANDLE ControllerInstanceKey;
223 ULONG BusInstance;
224 ULONG ControllerInstance;
225 ULONG BufferLength;
226 ULONG ReturnedLength;
227 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
228 NTSTATUS Status;
229
230 DPRINT("GetDisplayIdentifier() called\n");
231
232 /* Open the bus key */
233 RtlInitUnicodeString(&KeyName,
234 L"\\Registry\\Machine\\HARDWARE\\Description\\System\\MultifunctionAdapter");
235 InitializeObjectAttributes(&ObjectAttributes,
236 &KeyName,
237 OBJ_CASE_INSENSITIVE,
238 NULL,
239 NULL);
240 Status = NtOpenKey(&BusKey,
241 KEY_ALL_ACCESS,
242 &ObjectAttributes);
243 if (!NT_SUCCESS(Status))
244 {
245 DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
246 return FALSE;
247 }
248
249 BusInstance = 0;
250 while (TRUE)
251 {
252 swprintf(Buffer, L"%lu", BusInstance);
253 RtlInitUnicodeString(&KeyName,
254 Buffer);
255 InitializeObjectAttributes(&ObjectAttributes,
256 &KeyName,
257 OBJ_CASE_INSENSITIVE,
258 BusKey,
259 NULL);
260 Status = NtOpenKey(&BusInstanceKey,
261 KEY_ALL_ACCESS,
262 &ObjectAttributes);
263 if (!NT_SUCCESS(Status))
264 {
265 DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
266 NtClose(BusKey);
267 return FALSE;
268 }
269
270 /* Open the controller type key */
271 RtlInitUnicodeString(&KeyName,
272 L"DisplayController");
273 InitializeObjectAttributes(&ObjectAttributes,
274 &KeyName,
275 OBJ_CASE_INSENSITIVE,
276 BusInstanceKey,
277 NULL);
278 Status = NtOpenKey(&ControllerKey,
279 KEY_ALL_ACCESS,
280 &ObjectAttributes);
281 if (NT_SUCCESS(Status))
282 {
283 ControllerInstance = 0;
284 while (TRUE)
285 {
286 /* Open the pointer controller instance key */
287 swprintf(Buffer, L"%lu", ControllerInstance);
288 RtlInitUnicodeString(&KeyName,
289 Buffer);
290 InitializeObjectAttributes(&ObjectAttributes,
291 &KeyName,
292 OBJ_CASE_INSENSITIVE,
293 ControllerKey,
294 NULL);
295 Status = NtOpenKey(&ControllerInstanceKey,
296 KEY_ALL_ACCESS,
297 &ObjectAttributes);
298 if (!NT_SUCCESS(Status))
299 {
300 DPRINT("NtOpenKey() failed (Status %lx)\n", Status);
301 NtClose(ControllerKey);
302 NtClose(BusInstanceKey);
303 NtClose(BusKey);
304 return FALSE;
305 }
306
307 /* Get controller identifier */
308 RtlInitUnicodeString(&KeyName,
309 L"Identifier");
310
311 BufferLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
312 256 * sizeof(WCHAR);
313 ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(),
314 0,
315 BufferLength);
316 if (ValueInfo == NULL)
317 {
318 DPRINT("RtlAllocateHeap() failed\n");
319 NtClose(ControllerInstanceKey);
320 NtClose(ControllerKey);
321 NtClose(BusInstanceKey);
322 NtClose(BusKey);
323 return FALSE;
324 }
325
326 Status = NtQueryValueKey(ControllerInstanceKey,
327 &KeyName,
328 KeyValuePartialInformation,
329 ValueInfo,
330 BufferLength,
331 &ReturnedLength);
332 if (NT_SUCCESS(Status))
333 {
334 DPRINT("Identifier: %S\n", (PWSTR)ValueInfo->Data);
335
336 BufferLength = min(ValueInfo->DataLength / sizeof(WCHAR), IdentifierLength);
337 RtlCopyMemory (Identifier,
338 ValueInfo->Data,
339 BufferLength * sizeof(WCHAR));
340 Identifier[BufferLength] = 0;
341
342 RtlFreeHeap(RtlGetProcessHeap(),
343 0,
344 ValueInfo);
345 NtClose(ControllerInstanceKey);
346 NtClose(ControllerKey);
347 NtClose(BusInstanceKey);
348 NtClose(BusKey);
349 return TRUE;
350 }
351
352 NtClose(ControllerInstanceKey);
353
354 ControllerInstance++;
355 }
356
357 NtClose(ControllerKey);
358 }
359
360 NtClose(BusInstanceKey);
361
362 BusInstance++;
363 }
364
365 NtClose(BusKey);
366
367 return FALSE;
368 }
369
370
371 PGENERIC_LIST
372 CreateDisplayDriverList(HINF InfFile)
373 {
374 CHAR Buffer[128];
375 PGENERIC_LIST List;
376 PINFCONTEXT Context;
377 PWCHAR KeyName;
378 PWCHAR KeyValue;
379 PWCHAR UserData;
380 WCHAR DisplayIdentifier[128];
381 WCHAR DisplayKey[32];
382
383 /* Get the display identification */
384 if (!GetDisplayIdentifier(DisplayIdentifier, 128))
385 {
386 DisplayIdentifier[0] = 0;
387 }
388
389 DPRINT("Display identifier: '%S'\n", DisplayIdentifier);
390
391 /* Search for matching device identifier */
392 if (!InfFindFirstLine(InfFile, L"Map.Display", NULL, &Context))
393 {
394 /* FIXME: error message */
395 return NULL;
396 }
397
398 do
399 {
400 if (!InfGetDataField(Context, 1, &KeyValue))
401 {
402 /* FIXME: Handle error! */
403 DPRINT("InfGetDataField() failed\n");
404 return NULL;
405 }
406
407 DPRINT("KeyValue: %S\n", KeyValue);
408 if (wcsstr(DisplayIdentifier, KeyValue))
409 {
410 if (!InfGetDataField(Context, 0, &KeyName))
411 {
412 /* FIXME: Handle error! */
413 DPRINT("InfGetDataField() failed\n");
414 return NULL;
415 }
416
417 DPRINT("Display key: %S\n", KeyName);
418 wcscpy(DisplayKey, KeyName);
419 }
420 }
421 while (InfFindNextLine(Context, Context));
422 InfFreeContext(Context);
423
424
425 List = CreateGenericList();
426 if (List == NULL)
427 return NULL;
428
429 if (!InfFindFirstLine (InfFile, L"Display", NULL, &Context))
430 {
431 DestroyGenericList(List, FALSE);
432 return NULL;
433 }
434
435 do
436 {
437 if (!InfGetDataField(Context, 0, &KeyName))
438 {
439 DPRINT1("InfGetDataField() failed\n");
440 break;
441 }
442
443 if (!InfGetDataField(Context, 1, &KeyValue))
444 {
445 DPRINT1("InfGetDataField() failed\n");
446 break;
447 }
448
449 UserData = RtlAllocateHeap(ProcessHeap,
450 0,
451 (wcslen(KeyName) + 1) * sizeof(WCHAR));
452 if (UserData == NULL)
453 {
454 DPRINT1("RtlAllocateHeap() failed\n");
455 DestroyGenericList(List, TRUE);
456 return NULL;
457 }
458
459 wcscpy(UserData, KeyName);
460
461 sprintf(Buffer, "%S", KeyValue);
462 AppendGenericListEntry(List,
463 Buffer,
464 UserData,
465 _wcsicmp(KeyName, DisplayKey) ? FALSE : TRUE);
466 }
467 while (InfFindNextLine(Context, Context));
468 InfFreeContext(Context);
469
470 #if 0
471 AppendGenericListEntry(List, "Other display driver", NULL, TRUE);
472 #endif
473
474 return List;
475 }
476
477 BOOLEAN
478 ProcessComputerFiles(HINF InfFile, PGENERIC_LIST List, PWCHAR* AdditionalSectionName)
479 {
480 PGENERIC_LIST_ENTRY Entry;
481 static WCHAR SectionName[128];
482
483 DPRINT("ProcessComputerFiles() called\n");
484
485 Entry = GetGenericListEntry(List);
486 if (Entry == NULL)
487 {
488 DPRINT("GetGenericListEntry() failed\n");
489 return FALSE;
490 }
491
492 wcscpy(SectionName, L"Files.");
493 wcscat(SectionName, Entry->UserData);
494 *AdditionalSectionName = SectionName;
495
496 return TRUE;
497 }
498
499
500 BOOLEAN
501 ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List)
502 {
503 PGENERIC_LIST_ENTRY Entry;
504 PINFCONTEXT Context;
505 PWCHAR ServiceName;
506 ULONG StartValue;
507 NTSTATUS Status;
508
509 DPRINT("ProcessDisplayRegistry() called\n");
510
511 Entry = GetGenericListEntry(List);
512 if (Entry == NULL)
513 {
514 DPRINT("GetGenericListEntry() failed\n");
515 return FALSE;
516 }
517
518 if (!InfFindFirstLine(InfFile, L"Display", Entry->UserData, &Context))
519 {
520 DPRINT("InfFindFirstLine() failed\n");
521 return FALSE;
522 }
523
524 if (!InfGetDataField(Context, 3, &ServiceName))
525 {
526 DPRINT("InfGetDataField() failed\n");
527 return FALSE;
528 }
529
530 DPRINT("Service name: %S\n", ServiceName);
531
532 StartValue = 1;
533 Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
534 ServiceName,
535 L"Start",
536 REG_DWORD,
537 &StartValue,
538 sizeof(ULONG));
539 InfFreeContext(Context);
540 if (!NT_SUCCESS(Status))
541 {
542 DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status);
543 return FALSE;
544 }
545
546 DPRINT("ProcessDisplayRegistry() done\n");
547
548 return TRUE;
549 }
550
551
552 PGENERIC_LIST
553 CreateKeyboardDriverList(HINF InfFile)
554 {
555 CHAR Buffer[128];
556 PGENERIC_LIST List;
557 PINFCONTEXT Context;
558 PWCHAR KeyName;
559 PWCHAR KeyValue;
560 PWCHAR UserData;
561
562 List = CreateGenericList();
563 if (List == NULL)
564 return NULL;
565
566 if (!InfFindFirstLine (InfFile, L"Keyboard", NULL, &Context))
567 {
568 DestroyGenericList(List, FALSE);
569 return NULL;
570 }
571
572 do
573 {
574 if (!InfGetData (Context, &KeyName, &KeyValue))
575 {
576 /* FIXME: Handle error! */
577 DPRINT("InfGetData() failed\n");
578 break;
579 }
580
581 UserData = RtlAllocateHeap(ProcessHeap,
582 0,
583 (wcslen(KeyName) + 1) * sizeof(WCHAR));
584 if (UserData == NULL)
585 {
586 /* FIXME: Handle error! */
587 }
588
589 wcscpy(UserData, KeyName);
590
591 sprintf(Buffer, "%S", KeyValue);
592 AppendGenericListEntry(List, Buffer, UserData, FALSE);
593 }
594 while (InfFindNextLine(Context, Context));
595 InfFreeContext(Context);
596
597 return List;
598 }
599
600
601 PGENERIC_LIST
602 CreateKeyboardLayoutList(HINF InfFile)
603 {
604 CHAR Buffer[128];
605 PGENERIC_LIST List;
606 PINFCONTEXT Context;
607 PWCHAR KeyName;
608 PWCHAR KeyValue;
609 PWCHAR UserData;
610 WCHAR DefaultLayout[20];
611
612 /* Get default layout id */
613 if (!InfFindFirstLine (InfFile, L"NLS", L"DefaultLayout", &Context))
614 return NULL;
615
616 if (!InfGetData (Context, NULL, &KeyValue))
617 {
618 InfFreeContext(Context);
619 return NULL;
620 }
621
622 wcscpy(DefaultLayout, KeyValue);
623 InfFreeContext(Context);
624
625 List = CreateGenericList();
626 if (List == NULL)
627 return NULL;
628
629 if (!InfFindFirstLine (InfFile, L"KeyboardLayout", NULL, &Context))
630 {
631 DestroyGenericList(List, FALSE);
632 InfFreeContext(Context);
633 return NULL;
634 }
635
636 do
637 {
638 if (!InfGetData (Context, &KeyName, &KeyValue))
639 {
640 /* FIXME: Handle error! */
641 DPRINT("InfGetData() failed\n");
642 break;
643 }
644
645 UserData = RtlAllocateHeap(ProcessHeap,
646 0,
647 (wcslen(KeyName) + 1) * sizeof(WCHAR));
648 if (UserData == NULL)
649 {
650 /* FIXME: Handle error! */
651 }
652
653 wcscpy(UserData, KeyName);
654
655 sprintf(Buffer, "%S", KeyValue);
656 AppendGenericListEntry(List,
657 Buffer,
658 UserData,
659 _wcsicmp(KeyName, DefaultLayout) ? FALSE : TRUE);
660 }
661 while (InfFindNextLine(Context, Context));
662 InfFreeContext(Context);
663
664 return List;
665 }
666
667
668 BOOLEAN
669 ProcessKeyboardLayoutRegistry(PGENERIC_LIST List)
670 {
671 PGENERIC_LIST_ENTRY Entry;
672 PWCHAR LanguageId;
673 OBJECT_ATTRIBUTES ObjectAttributes;
674 UNICODE_STRING KeyName;
675 UNICODE_STRING ValueName;
676 HANDLE KeyHandle;
677 NTSTATUS Status;
678
679 Entry = GetGenericListEntry(List);
680 if (Entry == NULL)
681 return FALSE;
682
683 LanguageId = (PWCHAR)Entry->UserData;
684 if (LanguageId == NULL)
685 return FALSE;
686
687 /* Open the nls language key */
688 RtlInitUnicodeString(&KeyName,
689 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language");
690 InitializeObjectAttributes(&ObjectAttributes,
691 &KeyName,
692 OBJ_CASE_INSENSITIVE,
693 NULL,
694 NULL);
695 Status = NtOpenKey(&KeyHandle,
696 KEY_ALL_ACCESS,
697 &ObjectAttributes);
698 if (!NT_SUCCESS(Status))
699 {
700 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status);
701 return FALSE;
702 }
703
704 /* Set default language */
705 RtlInitUnicodeString(&ValueName,
706 L"Default");
707 Status = NtSetValueKey (KeyHandle,
708 &ValueName,
709 0,
710 REG_SZ,
711 (PVOID)(LanguageId + 4),
712 8);
713 if (!NT_SUCCESS(Status))
714 {
715 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
716 NtClose(KeyHandle);
717 return FALSE;
718 }
719
720 /* Set install language */
721 RtlInitUnicodeString(&ValueName,
722 L"InstallLanguage");
723 Status = NtSetValueKey (KeyHandle,
724 &ValueName,
725 0,
726 REG_SZ,
727 (PVOID)(LanguageId + 4),
728 8);
729 if (!NT_SUCCESS(Status))
730 {
731 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
732 NtClose(KeyHandle);
733 return FALSE;
734 }
735
736 NtClose(KeyHandle);
737
738 return TRUE;
739 }
740
741
742 #if 0
743 BOOLEAN
744 ProcessKeyboardLayoutFiles(PGENERIC_LIST List)
745 {
746 return TRUE;
747 }
748 #endif
749
750 /* EOF */