1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: PnP manager Firmware Mapper functions
5 * COPYRIGHT: Copyright 2006-2007 Hervé Poussineau <hpoussin@reactos.org>
6 * Copyright 2008-2011 Cameron Gutman <cameron.gutman@reactos.org>
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* TYPES *********************************************************************/
16
17 typedef struct _PNP_MAPPER_DEVICE_ID
18 {
19 PCWSTR TypeName;
20 PWSTR PnPId;
21 } PNP_MAPPER_DEVICE_ID, *PPNP_MAPPER_DEVICE_ID;
22
23 typedef struct _PNP_DETECT_IDENTIFIER_MAP
24 {
25 PCWSTR DetectId;
26 PWSTR PnPId;
27 PPNP_MAPPER_DEVICE_ID PeripheralMap;
28 ULONG Counter;
29 } PNP_DETECT_IDENTIFIER_MAP;
30
31 /* DATA **********************************************************************/
32
33 static UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier");
34 static UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID");
35 static UNICODE_STRING ConfigurationDataU = RTL_CONSTANT_STRING(L"Configuration Data");
36 static UNICODE_STRING BootConfigU = RTL_CONSTANT_STRING(L"BootConfig");
37 static UNICODE_STRING LogConfU = RTL_CONSTANT_STRING(L"LogConf");
38
39 /* FIXME: Trailing \0 in structures below are hacks, should be removed.
40 * Hardware identifiers also can be mapped using "LegacyXlate" sections
41 * of driver INF files. */
42
43 DATA_SEG("INITDATA")
44 static
45 PNP_MAPPER_DEVICE_ID KeyboardMap[] =
46 {
47 { L"XT_83KEY", L"*PNP0300\0" },
48 { L"PCAT_86KEY", L"*PNP0301\0" },
49 { L"PCXT_84KEY", L"*PNP0302\0" },
50 { L"XT_84KEY", L"*PNP0302\0" },
51 { L"101-KEY", L"*PNP0303\0" },
52 { L"OLI_83KEY", L"*PNP0304\0" },
53 { L"ATT_301", L"*PNP0304\0" },
54 { L"OLI_102KEY", L"*PNP0305\0" },
55 { L"OLI_86KEY", L"*PNP0306\0" },
56 { L"OLI_A101_102KEY", L"*PNP0309\0" },
57 { L"ATT_302", L"*PNP030a\0" },
58 { L"PCAT_ENHANCED", L"*PNP030b\0" },
59 { L"PC98_106KEY", L"*nEC1300\0" },
60 { L"PC98_LaptopKEY", L"*nEC1300\0" },
61 { L"PC98_N106KEY", L"*PNP0303\0" },
62 { NULL, NULL }
63 };
64
65 DATA_SEG("INITDATA")
66 static
67 PNP_MAPPER_DEVICE_ID PointerMap[] =
68 {
69 { L"PS2 MOUSE", L"*PNP0F0E\0" },
70 { L"SERIAL MOUSE", L"*PNP0F0C\0" },
71 { L"MICROSOFT PS2 MOUSE", L"*PNP0F03\0" },
72 { L"LOGITECH PS2 MOUSE", L"*PNP0F12\0" },
73 { L"MICROSOFT INPORT MOUSE", L"*PNP0F02\0" },
74 { L"MICROSOFT SERIAL MOUSE", L"*PNP0F01\0" },
75 { L"MICROSOFT BALLPOINT SERIAL MOUSE", L"*PNP0F09\0" },
76 { L"LOGITECH SERIAL MOUSE", L"*PNP0F08\0" },
77 { L"MICROSOFT BUS MOUSE", L"*PNP0F00\0" },
78 { L"NEC PC-9800 BUS MOUSE", L"*nEC1F00\0" },
79 { NULL, NULL }
80 };
81
82 DATA_SEG("INITDATA")
83 static
84 PNP_DETECT_IDENTIFIER_MAP PnPMap[] =
85 {
86 { L"SerialController", L"*PNP0501\0", NULL, 0 },
87 //{ L"KeyboardController", L"*PNP0303\0", NULL, 0 },
88 //{ L"PointerController", L"*PNP0F13\0", NULL, 0 },
89 { L"KeyboardPeripheral", NULL, KeyboardMap, 0 },
90 { L"PointerPeripheral", NULL, PointerMap, 0 },
91 { L"ParallelController", L"*PNP0400\0", NULL, 0 },
92 { L"FloppyDiskPeripheral", L"*PNP0700\0", NULL, 0 },
93 { NULL, NULL, NULL, 0 }
94 };
95
96 /* FUNCTIONS *****************************************************************/
97
98 static
99 CODE_SEG("INIT")
100 PWSTR
IopMapPeripheralId(_In_ PCUNICODE_STRING Value,_In_ PPNP_MAPPER_DEVICE_ID DeviceList)101 IopMapPeripheralId(
102 _In_ PCUNICODE_STRING Value,
103 _In_ PPNP_MAPPER_DEVICE_ID DeviceList)
104 {
105 ULONG i;
106 UNICODE_STRING CmpId;
107
108 for (i = 0; DeviceList[i].TypeName; i++)
109 {
110 RtlInitUnicodeString(&CmpId, DeviceList[i].TypeName);
111
112 if (RtlCompareUnicodeString(Value, &CmpId, FALSE) == 0)
113 break;
114 }
115
116 return DeviceList[i].PnPId;
117 }
118
119 static
120 CODE_SEG("INIT")
121 PWSTR
IopMapDetectedDeviceId(_In_ PUNICODE_STRING DetectId,_In_ PUNICODE_STRING Value,_Out_ PULONG DeviceIndex)122 IopMapDetectedDeviceId(
123 _In_ PUNICODE_STRING DetectId,
124 _In_ PUNICODE_STRING Value,
125 _Out_ PULONG DeviceIndex)
126 {
127 ULONG i;
128 UNICODE_STRING CmpId;
129
130 if (!DetectId)
131 return NULL;
132
133 for (i = 0; PnPMap[i].DetectId; i++)
134 {
135 RtlInitUnicodeString(&CmpId, PnPMap[i].DetectId);
136
137 if (RtlCompareUnicodeString(DetectId, &CmpId, FALSE) == 0)
138 {
139 *DeviceIndex = PnPMap[i].Counter++;
140
141 if (PnPMap[i].PeripheralMap)
142 return IopMapPeripheralId(Value, PnPMap[i].PeripheralMap);
143 break;
144 }
145 }
146
147 return PnPMap[i].PnPId;
148 }
149
150 static
151 CODE_SEG("INIT")
152 NTSTATUS
IopEnumerateDetectedDevices(_In_ HANDLE hBaseKey,_In_opt_ PUNICODE_STRING RelativePath,_In_ HANDLE hRootKey,_In_ BOOLEAN EnumerateSubKeys,_In_opt_ PCM_FULL_RESOURCE_DESCRIPTOR BootResources,_In_opt_ ULONG BootResourcesLength,_In_ PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources,_In_ ULONG ParentBootResourcesLength)153 IopEnumerateDetectedDevices(
154 _In_ HANDLE hBaseKey,
155 _In_opt_ PUNICODE_STRING RelativePath,
156 _In_ HANDLE hRootKey,
157 _In_ BOOLEAN EnumerateSubKeys,
158 _In_opt_ PCM_FULL_RESOURCE_DESCRIPTOR BootResources,
159 _In_opt_ ULONG BootResourcesLength,
160 _In_ PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources,
161 _In_ ULONG ParentBootResourcesLength)
162 {
163 HANDLE hDevicesKey = NULL;
164 ULONG KeyIndex = 0;
165 PKEY_BASIC_INFORMATION pDeviceInformation = NULL;
166 ULONG DeviceInfoLength = sizeof(KEY_BASIC_INFORMATION) + 50 * sizeof(WCHAR);
167 NTSTATUS Status;
168
169 if (!BootResources && RelativePath)
170 {
171 Status = IopOpenRegistryKeyEx(&hDevicesKey, hBaseKey, RelativePath, KEY_ENUMERATE_SUB_KEYS);
172
173 if (!NT_SUCCESS(Status))
174 {
175 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
176 goto cleanup;
177 }
178 }
179 else
180 hDevicesKey = hBaseKey;
181
182 pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength);
183 if (!pDeviceInformation)
184 {
185 DPRINT("ExAllocatePool() failed\n");
186 Status = STATUS_NO_MEMORY;
187 goto cleanup;
188 }
189
190 while (TRUE)
191 {
192 OBJECT_ATTRIBUTES ObjectAttributes;
193 HANDLE hDeviceKey = NULL;
194 HANDLE hLevel1Key, hLevel2Key = NULL, hLogConf;
195 UNICODE_STRING Level2NameU;
196 WCHAR Level2Name[5];
197 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation = NULL;
198 ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR);
199 UNICODE_STRING DeviceName, ValueName;
200 ULONG RequiredSize;
201
202 UNICODE_STRING HardwareIdKey;
203 PWSTR pHardwareId;
204 ULONG DeviceIndex = 0;
205
206 Status = ZwEnumerateKey(hDevicesKey,
207 KeyIndex,
208 KeyBasicInformation,
209 pDeviceInformation,
210 DeviceInfoLength,
211 &RequiredSize);
212
213 if (Status == STATUS_NO_MORE_ENTRIES)
214 break;
215 else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
216 {
217 ExFreePool(pDeviceInformation);
218 DeviceInfoLength = RequiredSize;
219 pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength);
220
221 if (!pDeviceInformation)
222 {
223 DPRINT("ExAllocatePool() failed\n");
224 Status = STATUS_NO_MEMORY;
225 goto cleanup;
226 }
227
228 Status = ZwEnumerateKey(hDevicesKey,
229 KeyIndex,
230 KeyBasicInformation,
231 pDeviceInformation,
232 DeviceInfoLength,
233 &RequiredSize);
234 }
235
236 if (!NT_SUCCESS(Status))
237 {
238 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
239 goto cleanup;
240 }
241 KeyIndex++;
242
243 /* Open device key */
244 DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength;
245 DeviceName.Buffer = pDeviceInformation->Name;
246
247 if (BootResources)
248 {
249 Status = IopEnumerateDetectedDevices(
250 hDevicesKey,
251 &DeviceName,
252 hRootKey,
253 TRUE,
254 NULL,
255 0,
256 BootResources,
257 BootResourcesLength);
258
259 if (!NT_SUCCESS(Status))
260 goto cleanup;
261
262 continue;
263 }
264
265 pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength);
266 if (!pValueInformation)
267 {
268 DPRINT("ExAllocatePool() failed\n");
269 Status = STATUS_NO_MEMORY;
270 goto cleanup;
271 }
272
273 Status = IopOpenRegistryKeyEx(&hDeviceKey, hDevicesKey, &DeviceName,
274 KEY_QUERY_VALUE + (EnumerateSubKeys ? KEY_ENUMERATE_SUB_KEYS : 0));
275
276 if (!NT_SUCCESS(Status))
277 {
278 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
279 goto cleanup;
280 }
281
282 /* Read boot resources, and add then to parent ones */
283 Status = ZwQueryValueKey(hDeviceKey,
284 &ConfigurationDataU,
285 KeyValuePartialInformation,
286 pValueInformation,
287 ValueInfoLength,
288 &RequiredSize);
289
290 if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
291 {
292 ExFreePool(pValueInformation);
293 ValueInfoLength = RequiredSize;
294 pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength);
295
296 if (!pValueInformation)
297 {
298 DPRINT("ExAllocatePool() failed\n");
299 ZwDeleteKey(hLevel2Key);
300 Status = STATUS_NO_MEMORY;
301 goto cleanup;
302 }
303
304 Status = ZwQueryValueKey(hDeviceKey,
305 &ConfigurationDataU,
306 KeyValuePartialInformation,
307 pValueInformation,
308 ValueInfoLength,
309 &RequiredSize);
310 }
311
312 if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
313 {
314 BootResources = ParentBootResources;
315 BootResourcesLength = ParentBootResourcesLength;
316 }
317 else if (!NT_SUCCESS(Status))
318 {
319 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
320 goto nextdevice;
321 }
322 else if (pValueInformation->Type != REG_FULL_RESOURCE_DESCRIPTOR)
323 {
324 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_FULL_RESOURCE_DESCRIPTOR);
325 goto nextdevice;
326 }
327 else
328 {
329 static const ULONG Header = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors);
330
331 /* Concatenate current resources and parent ones */
332 if (ParentBootResourcesLength == 0)
333 BootResourcesLength = pValueInformation->DataLength;
334 else
335 BootResourcesLength = ParentBootResourcesLength
336 + pValueInformation->DataLength
337 - Header;
338
339 BootResources = ExAllocatePool(PagedPool, BootResourcesLength);
340 if (!BootResources)
341 {
342 DPRINT("ExAllocatePool() failed\n");
343 goto nextdevice;
344 }
345
346 if (ParentBootResourcesLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
347 {
348 RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength);
349 }
350 else if (ParentBootResources->PartialResourceList.PartialDescriptors[ParentBootResources->PartialResourceList.Count - 1].Type == CmResourceTypeDeviceSpecific)
351 {
352 RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength);
353 RtlCopyMemory(
354 (PVOID)((ULONG_PTR)BootResources + pValueInformation->DataLength),
355 (PVOID)((ULONG_PTR)ParentBootResources + Header),
356 ParentBootResourcesLength - Header);
357 BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count;
358 }
359 else
360 {
361 RtlCopyMemory(BootResources, pValueInformation->Data, Header);
362 RtlCopyMemory(
363 (PVOID)((ULONG_PTR)BootResources + Header),
364 (PVOID)((ULONG_PTR)ParentBootResources + Header),
365 ParentBootResourcesLength - Header);
366 RtlCopyMemory(
367 (PVOID)((ULONG_PTR)BootResources + ParentBootResourcesLength),
368 pValueInformation->Data + Header,
369 pValueInformation->DataLength - Header);
370 BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count;
371 }
372 }
373
374 if (EnumerateSubKeys)
375 {
376 Status = IopEnumerateDetectedDevices(
377 hDeviceKey,
378 RelativePath,
379 hRootKey,
380 TRUE,
381 BootResources,
382 BootResourcesLength,
383 ParentBootResources,
384 ParentBootResourcesLength);
385
386 if (!NT_SUCCESS(Status))
387 goto cleanup;
388 }
389
390 /* Read identifier */
391 Status = ZwQueryValueKey(hDeviceKey,
392 &IdentifierU,
393 KeyValuePartialInformation,
394 pValueInformation,
395 ValueInfoLength,
396 &RequiredSize);
397
398 if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
399 {
400 ExFreePool(pValueInformation);
401 ValueInfoLength = RequiredSize;
402 pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength);
403
404 if (!pValueInformation)
405 {
406 DPRINT("ExAllocatePool() failed\n");
407 Status = STATUS_NO_MEMORY;
408 goto cleanup;
409 }
410
411 Status = ZwQueryValueKey(hDeviceKey,
412 &IdentifierU,
413 KeyValuePartialInformation,
414 pValueInformation,
415 ValueInfoLength,
416 &RequiredSize);
417 }
418
419 if (!NT_SUCCESS(Status))
420 {
421 if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
422 {
423 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
424 goto nextdevice;
425 }
426 ValueName.Length = ValueName.MaximumLength = 0;
427 }
428 else if (pValueInformation->Type != REG_SZ)
429 {
430 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_SZ);
431 goto nextdevice;
432 }
433 else
434 {
435 /* Assign hardware id to this device */
436 ValueName.Length = ValueName.MaximumLength = (USHORT)pValueInformation->DataLength;
437 ValueName.Buffer = (PWCHAR)pValueInformation->Data;
438 if (ValueName.Length >= sizeof(WCHAR) && ValueName.Buffer[ValueName.Length / sizeof(WCHAR) - 1] == UNICODE_NULL)
439 ValueName.Length -= sizeof(WCHAR);
440 }
441
442 pHardwareId = IopMapDetectedDeviceId(RelativePath, &ValueName, &DeviceIndex);
443 if (!pHardwareId)
444 {
445 /* Unknown key path */
446 DPRINT("Unknown key path '%wZ' value '%wZ'\n", RelativePath, &ValueName);
447 goto nextdevice;
448 }
449
450 /* Prepare hardware id key (hardware id value without final \0) */
451 HardwareIdKey.Length = (USHORT)wcslen(pHardwareId) * sizeof(WCHAR);
452 HardwareIdKey.MaximumLength = HardwareIdKey.Length + sizeof(UNICODE_NULL) * 2;
453 HardwareIdKey.Buffer = pHardwareId;
454
455 /* Add the detected device to Root key */
456 InitializeObjectAttributes(&ObjectAttributes, &HardwareIdKey, OBJ_KERNEL_HANDLE, hRootKey, NULL);
457
458 Status = ZwCreateKey(
459 &hLevel1Key,
460 KEY_CREATE_SUB_KEY,
461 &ObjectAttributes,
462 0,
463 NULL,
464 REG_OPTION_NON_VOLATILE,
465 NULL);
466
467 if (!NT_SUCCESS(Status))
468 {
469 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
470 goto nextdevice;
471 }
472
473 swprintf(Level2Name, L"%04lu", DeviceIndex);
474 RtlInitUnicodeString(&Level2NameU, Level2Name);
475 InitializeObjectAttributes(&ObjectAttributes, &Level2NameU, OBJ_KERNEL_HANDLE, hLevel1Key, NULL);
476
477 Status = ZwCreateKey(
478 &hLevel2Key,
479 KEY_SET_VALUE | KEY_CREATE_SUB_KEY,
480 &ObjectAttributes,
481 0,
482 NULL,
483 REG_OPTION_NON_VOLATILE,
484 NULL);
485
486 ZwClose(hLevel1Key);
487 if (!NT_SUCCESS(Status))
488 {
489 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
490 goto nextdevice;
491 }
492
493 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName, DeviceIndex, &HardwareIdKey);
494 Status = ZwSetValueKey(hLevel2Key, &HardwareIDU, 0, REG_MULTI_SZ, HardwareIdKey.Buffer, HardwareIdKey.MaximumLength);
495
496 if (!NT_SUCCESS(Status))
497 {
498 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status);
499 ZwDeleteKey(hLevel2Key);
500 goto nextdevice;
501 }
502
503 /* Create 'LogConf' subkey */
504 InitializeObjectAttributes(&ObjectAttributes, &LogConfU, OBJ_KERNEL_HANDLE, hLevel2Key, NULL);
505
506 Status = ZwCreateKey(
507 &hLogConf,
508 KEY_SET_VALUE,
509 &ObjectAttributes,
510 0,
511 NULL,
512 REG_OPTION_VOLATILE,
513 NULL);
514
515 if (!NT_SUCCESS(Status))
516 {
517 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
518 ZwDeleteKey(hLevel2Key);
519 goto nextdevice;
520 }
521
522 if (BootResourcesLength >= sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
523 {
524 PUCHAR CmResourceList;
525 ULONG ListCount;
526
527 CmResourceList = ExAllocatePool(PagedPool, BootResourcesLength + sizeof(ULONG));
528 if (!CmResourceList)
529 {
530 ZwClose(hLogConf);
531 ZwDeleteKey(hLevel2Key);
532 goto nextdevice;
533 }
534
535 /* Add the list count (1st member of CM_RESOURCE_LIST) */
536 ListCount = 1;
537 RtlCopyMemory(CmResourceList,
538 &ListCount,
539 sizeof(ULONG));
540
541 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
542 RtlCopyMemory(CmResourceList + sizeof(ULONG),
543 BootResources,
544 BootResourcesLength);
545
546 /* Save boot resources to 'LogConf\BootConfig' */
547 Status = ZwSetValueKey(hLogConf,
548 &BootConfigU,
549 0,
550 REG_RESOURCE_LIST,
551 CmResourceList,
552 BootResourcesLength + sizeof(ULONG));
553
554 ExFreePool(CmResourceList);
555
556 if (!NT_SUCCESS(Status))
557 {
558 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status);
559 ZwClose(hLogConf);
560 ZwDeleteKey(hLevel2Key);
561 goto nextdevice;
562 }
563 }
564 ZwClose(hLogConf);
565
566 nextdevice:
567 if (BootResources && BootResources != ParentBootResources)
568 {
569 ExFreePool(BootResources);
570 BootResources = NULL;
571 }
572 if (hLevel2Key)
573 {
574 ZwClose(hLevel2Key);
575 hLevel2Key = NULL;
576 }
577 if (hDeviceKey)
578 {
579 ZwClose(hDeviceKey);
580 hDeviceKey = NULL;
581 }
582 if (pValueInformation)
583 ExFreePool(pValueInformation);
584 }
585
586 Status = STATUS_SUCCESS;
587
588 cleanup:
589 if (hDevicesKey && hDevicesKey != hBaseKey)
590 ZwClose(hDevicesKey);
591 if (pDeviceInformation)
592 ExFreePool(pDeviceInformation);
593
594 return Status;
595 }
596
597 static
598 CODE_SEG("INIT")
599 BOOLEAN
IopIsFirmwareMapperDisabled(VOID)600 IopIsFirmwareMapperDisabled(VOID)
601 {
602 UNICODE_STRING KeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CURRENTCONTROLSET\\Control\\Pnp");
603 UNICODE_STRING KeyNameU = RTL_CONSTANT_STRING(L"DisableFirmwareMapper");
604 OBJECT_ATTRIBUTES ObjectAttributes;
605 HANDLE hPnpKey;
606 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation;
607 ULONG DesiredLength, Length;
608 ULONG KeyValue = 0;
609 NTSTATUS Status;
610
611 InitializeObjectAttributes(&ObjectAttributes, &KeyPathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
612 Status = ZwOpenKey(&hPnpKey, KEY_QUERY_VALUE, &ObjectAttributes);
613 if (NT_SUCCESS(Status))
614 {
615 Status = ZwQueryValueKey(hPnpKey,
616 &KeyNameU,
617 KeyValuePartialInformation,
618 NULL,
619 0,
620 &DesiredLength);
621 if ((Status == STATUS_BUFFER_TOO_SMALL) ||
622 (Status == STATUS_BUFFER_OVERFLOW))
623 {
624 Length = DesiredLength;
625 KeyInformation = ExAllocatePool(PagedPool, Length);
626 if (KeyInformation)
627 {
628 Status = ZwQueryValueKey(hPnpKey,
629 &KeyNameU,
630 KeyValuePartialInformation,
631 KeyInformation,
632 Length,
633 &DesiredLength);
634 if (NT_SUCCESS(Status) && KeyInformation->DataLength == sizeof(ULONG))
635 {
636 KeyValue = (ULONG)(*KeyInformation->Data);
637 }
638 else
639 {
640 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed\n", &KeyPathU, &KeyNameU);
641 }
642
643 ExFreePool(KeyInformation);
644 }
645 else
646 {
647 DPRINT1("Failed to allocate memory for registry query\n");
648 }
649 }
650 else
651 {
652 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed with status 0x%08lx\n", &KeyPathU, &KeyNameU, Status);
653 }
654
655 ZwClose(hPnpKey);
656 }
657 else
658 {
659 DPRINT1("ZwOpenKey(%wZ) failed with status 0x%08lx\n", &KeyPathU, Status);
660 }
661
662 DPRINT("Firmware mapper is %s\n", KeyValue != 0 ? "disabled" : "enabled");
663
664 return (KeyValue != 0) ? TRUE : FALSE;
665 }
666
667 CODE_SEG("INIT")
668 NTSTATUS
669 NTAPI
IopUpdateRootKey(VOID)670 IopUpdateRootKey(VOID)
671 {
672 UNICODE_STRING EnumU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
673 UNICODE_STRING RootPathU = RTL_CONSTANT_STRING(L"Root");
674 UNICODE_STRING MultiKeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
675 OBJECT_ATTRIBUTES ObjectAttributes;
676 HANDLE hEnum, hRoot;
677 NTSTATUS Status;
678
679 InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
680 Status = ZwCreateKey(&hEnum, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
681 if (!NT_SUCCESS(Status))
682 {
683 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status);
684 return Status;
685 }
686
687 InitializeObjectAttributes(&ObjectAttributes, &RootPathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hEnum, NULL);
688 Status = ZwCreateKey(&hRoot, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
689 ZwClose(hEnum);
690 if (!NT_SUCCESS(Status))
691 {
692 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
693 return Status;
694 }
695
696 if (!IopIsFirmwareMapperDisabled())
697 {
698 Status = IopOpenRegistryKeyEx(&hEnum, NULL, &MultiKeyPathU, KEY_ENUMERATE_SUB_KEYS);
699 if (!NT_SUCCESS(Status))
700 {
701 /* Nothing to do, don't return with an error status */
702 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
703 ZwClose(hRoot);
704 return STATUS_SUCCESS;
705 }
706 Status = IopEnumerateDetectedDevices(
707 hEnum,
708 NULL,
709 hRoot,
710 TRUE,
711 NULL,
712 0,
713 NULL,
714 0);
715 ZwClose(hEnum);
716 }
717 else
718 {
719 /* Enumeration is disabled */
720 Status = STATUS_SUCCESS;
721 }
722
723 ZwClose(hRoot);
724
725 return Status;
726 }
727