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 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 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 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 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 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