1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Hardware resource management 5 * COPYRIGHT: Copyright 1998 David Welch <welch@mcmail.com> 6 * Copyright 2001 Eric Kohl <eric.kohl@reactos.org> 7 * Copyright 2004-2013 Alex Ionescu <alex.ionescu@reactos.org> 8 * Copyright 2010 Cameron Gutman <cameron.gutman@reactos.org> 9 * Copyright 2010 Pierre Schweitzer <pierre@reactos.org> 10 */ 11 12 /* INCLUDES *****************************************************************/ 13 14 #include <ntoskrnl.h> 15 #define NDEBUG 16 #include <debug.h> 17 18 #ifndef NDEBUG 19 #define IORSRCTRACE(...) DbgPrint(__VA_ARGS__) 20 #else 21 #if defined(_MSC_VER) 22 #define IORSRCTRACE __noop 23 #else 24 #define IORSRCTRACE(...) do { if(0) { DbgPrint(__VA_ARGS__); } } while(0) 25 #endif 26 #endif 27 28 /* GLOBALS *******************************************************************/ 29 30 static CONFIGURATION_INFORMATION 31 _SystemConfigurationInformation = { 0, 0, 0, 0, 0, 0, 0, FALSE, FALSE, 0, 0 }; 32 33 /* API parameters to pass to IopQueryBusDescription() */ 34 typedef struct _IO_QUERY 35 { 36 PINTERFACE_TYPE BusType; 37 PULONG BusNumber; 38 PCONFIGURATION_TYPE ControllerType; 39 PULONG ControllerNumber; 40 PCONFIGURATION_TYPE PeripheralType; 41 PULONG PeripheralNumber; 42 PIO_QUERY_DEVICE_ROUTINE CalloutRoutine; 43 PVOID Context; 44 } IO_QUERY, *PIO_QUERY; 45 46 /* Strings corresponding to CONFIGURATION_TYPE */ 47 PCWSTR ArcTypes[MaximumType + 1] = 48 { 49 L"System", 50 L"CentralProcessor", 51 L"FloatingPointProcessor", 52 L"PrimaryICache", 53 L"PrimaryDCache", 54 L"SecondaryICache", 55 L"SecondaryDCache", 56 L"SecondaryCache", 57 L"EisaAdapter", 58 L"TcAdapter", 59 L"ScsiAdapter", 60 L"DtiAdapter", 61 L"MultifunctionAdapter", 62 L"DiskController", 63 L"TapeController", 64 L"CdRomController", 65 L"WormController", 66 L"SerialController", 67 L"NetworkController", 68 L"DisplayController", 69 L"ParallelController", 70 L"PointerController", 71 L"KeyboardController", 72 L"AudioController", 73 L"OtherController", 74 L"DiskPeripheral", 75 L"FloppyDiskPeripheral", 76 L"TapePeripheral", 77 L"ModemPeripheral", 78 L"MonitorPeripheral", 79 L"PrinterPeripheral", 80 L"PointerPeripheral", 81 L"KeyboardPeripheral", 82 L"TerminalPeripheral", 83 L"OtherPeripheral", 84 L"LinePeripheral", 85 L"NetworkPeripheral", 86 L"SystemMemory", 87 L"DockingInformation", 88 L"RealModeIrqRoutingTable", 89 L"RealModePCIEnumeration", 90 L"Undefined" 91 }; 92 93 /* Strings corresponding to IO_QUERY_DEVICE_DATA_FORMAT */ 94 PCWSTR IoDeviceInfoNames[IoQueryDeviceMaxData] = 95 { 96 L"Identifier", 97 L"Configuration Data", 98 L"Component Information" 99 }; 100 101 /* PRIVATE FUNCTIONS **********************************************************/ 102 103 /** 104 * @brief 105 * Reads and returns Hardware information from the appropriate hardware 106 * registry key. Helper stub of IopQueryBusDescription(). 107 * 108 * @param[in] Query 109 * What the parent function wants. 110 * 111 * @param[in] RootKey 112 * Which key to look in. 113 * 114 * @param[in] RootKeyHandle 115 * Handle to the key. 116 * 117 * @param[in] Bus 118 * The bus number. 119 * 120 * @param[in] BusInformation 121 * The configuration information being sent. 122 * 123 * @return A status code. 124 **/ 125 static NTSTATUS 126 IopQueryDeviceDescription( 127 _In_ PIO_QUERY Query, 128 _In_ UNICODE_STRING RootKey, 129 _In_ HANDLE RootKeyHandle, 130 _In_ ULONG Bus, 131 _In_ PKEY_VALUE_FULL_INFORMATION* BusInformation) 132 { 133 NTSTATUS Status = STATUS_SUCCESS; 134 135 /* Controller data */ 136 UNICODE_STRING ControllerString; 137 UNICODE_STRING ControllerRootRegName = RootKey; 138 UNICODE_STRING ControllerRegName; 139 HANDLE ControllerKeyHandle; 140 PKEY_FULL_INFORMATION ControllerFullInformation = NULL; 141 PKEY_VALUE_FULL_INFORMATION ControllerInformation[IoQueryDeviceMaxData] = 142 {NULL, NULL, NULL}; 143 ULONG ControllerNumber; 144 ULONG ControllerLoop; 145 ULONG MaximumControllerNumber; 146 147 /* Peripheral data */ 148 UNICODE_STRING PeripheralString; 149 HANDLE PeripheralKeyHandle; 150 PKEY_FULL_INFORMATION PeripheralFullInformation; 151 PKEY_VALUE_FULL_INFORMATION PeripheralInformation[IoQueryDeviceMaxData] = 152 {NULL, NULL, NULL}; 153 ULONG PeripheralNumber; 154 ULONG PeripheralLoop; 155 ULONG MaximumPeripheralNumber; 156 157 /* Global Registry data */ 158 OBJECT_ATTRIBUTES ObjectAttributes; 159 ULONG LenFullInformation; 160 ULONG LenKeyFullInformation; 161 UNICODE_STRING TempString; 162 WCHAR TempBuffer[14]; 163 164 IORSRCTRACE("\nIopQueryDeviceDescription(Query: 0x%p)\n" 165 " RootKey: '%wZ'\n" 166 " RootKeyHandle: 0x%p\n" 167 " Bus: %lu\n", 168 Query, 169 &RootKey, RootKeyHandle, 170 Bus); 171 172 /* Temporary string */ 173 RtlInitEmptyUnicodeString(&TempString, TempBuffer, sizeof(TempBuffer)); 174 175 /* Append controller name to string */ 176 RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); 177 RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->ControllerType]); 178 179 /* Set the controller number if specified */ 180 if (Query->ControllerNumber) 181 { 182 ControllerNumber = *(Query->ControllerNumber); 183 MaximumControllerNumber = ControllerNumber + 1; 184 IORSRCTRACE(" Getting controller #%lu\n", ControllerNumber); 185 } 186 else 187 { 188 IORSRCTRACE(" Enumerating controllers in '%wZ'...\n", &ControllerRootRegName); 189 190 /* Find out how many controllers there are */ 191 InitializeObjectAttributes(&ObjectAttributes, 192 &ControllerRootRegName, 193 OBJ_CASE_INSENSITIVE, 194 NULL, 195 NULL); 196 197 Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes); 198 199 if (NT_SUCCESS(Status)) 200 { 201 /* Retrieve the necessary buffer space */ 202 ZwQueryKey(ControllerKeyHandle, 203 KeyFullInformation, 204 NULL, 0, 205 &LenFullInformation); 206 207 /* Allocate it */ 208 ControllerFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE); 209 if (!ControllerFullInformation) 210 { 211 ZwClose(ControllerKeyHandle); 212 return STATUS_INSUFFICIENT_RESOURCES; 213 } 214 215 /* Get the information */ 216 Status = ZwQueryKey(ControllerKeyHandle, 217 KeyFullInformation, 218 ControllerFullInformation, 219 LenFullInformation, 220 &LenFullInformation); 221 ZwClose(ControllerKeyHandle); 222 ControllerKeyHandle = NULL; 223 } 224 225 /* No controller was found, bail out */ 226 if (!NT_SUCCESS(Status)) 227 { 228 if (ControllerFullInformation) 229 ExFreePoolWithTag(ControllerFullInformation, TAG_IO_RESOURCE); 230 return Status; 231 } 232 233 /* Find out the controllers */ 234 ControllerNumber = 0; 235 MaximumControllerNumber = ControllerFullInformation->SubKeys; 236 237 /* Cleanup */ 238 ExFreePoolWithTag(ControllerFullInformation, TAG_IO_RESOURCE); 239 ControllerFullInformation = NULL; 240 } 241 242 /* Save string */ 243 ControllerRegName = ControllerRootRegName; 244 245 /* Loop through controllers */ 246 for (; ControllerNumber < MaximumControllerNumber; ControllerNumber++) 247 { 248 /* Load string */ 249 ControllerRootRegName = ControllerRegName; 250 251 /* Convert controller number to registry string */ 252 Status = RtlIntegerToUnicodeString(ControllerNumber, 10, &TempString); 253 254 /* Create string */ 255 Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); 256 Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString); 257 258 /* Something messed up */ 259 if (!NT_SUCCESS(Status)) 260 break; 261 262 IORSRCTRACE(" Retrieving controller '%wZ'\n", &ControllerRootRegName); 263 264 /* Open the registry key */ 265 InitializeObjectAttributes(&ObjectAttributes, 266 &ControllerRootRegName, 267 OBJ_CASE_INSENSITIVE, 268 NULL, 269 NULL); 270 271 Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes); 272 273 /* Read the configuration data */ 274 if (NT_SUCCESS(Status)) 275 { 276 for (ControllerLoop = 0; ControllerLoop < RTL_NUMBER_OF(IoDeviceInfoNames); ControllerLoop++) 277 { 278 /* Identifier string first */ 279 RtlInitUnicodeString(&ControllerString, IoDeviceInfoNames[ControllerLoop]); 280 281 /* Retrieve the necessary buffer space */ 282 Status = ZwQueryValueKey(ControllerKeyHandle, 283 &ControllerString, 284 KeyValueFullInformation, 285 NULL, 0, 286 &LenKeyFullInformation); 287 288 if (!NT_SUCCESS(Status) && 289 (Status != STATUS_BUFFER_TOO_SMALL) && 290 (Status != STATUS_BUFFER_OVERFLOW)) 291 { 292 ControllerInformation[ControllerLoop] = NULL; 293 continue; 294 } 295 296 /* Allocate it */ 297 ControllerInformation[ControllerLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE); 298 if (!ControllerInformation[ControllerLoop]) 299 { 300 Status = STATUS_INSUFFICIENT_RESOURCES; 301 break; 302 } 303 304 /* Get the information */ 305 Status = ZwQueryValueKey(ControllerKeyHandle, 306 &ControllerString, 307 KeyValueFullInformation, 308 ControllerInformation[ControllerLoop], 309 LenKeyFullInformation, 310 &LenKeyFullInformation); 311 } 312 313 /* Cleanup */ 314 ZwClose(ControllerKeyHandle); 315 ControllerKeyHandle = NULL; 316 } 317 318 /* Something messed up */ 319 if (!NT_SUCCESS(Status)) 320 goto EndLoop; 321 322 /* We now have bus *AND* controller information, is it enough? */ 323 if (!Query->PeripheralType || !(*Query->PeripheralType)) 324 { 325 IORSRCTRACE(" --> Bus #%lu Controller #%lu Callout: '%wZ'\n", 326 Bus, ControllerNumber, &ControllerRootRegName); 327 328 Status = Query->CalloutRoutine(Query->Context, 329 &ControllerRootRegName, 330 *Query->BusType, 331 Bus, 332 BusInformation, 333 *Query->ControllerType, 334 ControllerNumber, 335 ControllerInformation, 336 0, 337 0, 338 NULL); 339 goto EndLoop; 340 } 341 342 /* Not enough: the caller also wants peripheral name */ 343 Status = RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); 344 Status |= RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->PeripheralType]); 345 346 /* Something messed up */ 347 if (!NT_SUCCESS(Status)) 348 goto EndLoop; 349 350 /* Set the peripheral number if specified */ 351 if (Query->PeripheralNumber) 352 { 353 PeripheralNumber = *(Query->PeripheralNumber); 354 MaximumPeripheralNumber = PeripheralNumber + 1; 355 IORSRCTRACE(" Getting peripheral #%lu\n", PeripheralNumber); 356 } 357 else 358 { 359 IORSRCTRACE(" Enumerating peripherals in '%wZ'...\n", &ControllerRootRegName); 360 361 /* Find out how many peripherals there are */ 362 InitializeObjectAttributes(&ObjectAttributes, 363 &ControllerRootRegName, 364 OBJ_CASE_INSENSITIVE, 365 NULL, 366 NULL); 367 368 Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes); 369 370 if (NT_SUCCESS(Status)) 371 { 372 /* Retrieve the necessary buffer space */ 373 ZwQueryKey(PeripheralKeyHandle, 374 KeyFullInformation, 375 NULL, 0, 376 &LenFullInformation); 377 378 /* Allocate it */ 379 PeripheralFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE); 380 if (!PeripheralFullInformation) 381 { 382 ZwClose(PeripheralKeyHandle); 383 Status = STATUS_INSUFFICIENT_RESOURCES; 384 goto EndLoop; 385 } 386 387 /* Get the information */ 388 Status = ZwQueryKey(PeripheralKeyHandle, 389 KeyFullInformation, 390 PeripheralFullInformation, 391 LenFullInformation, 392 &LenFullInformation); 393 ZwClose(PeripheralKeyHandle); 394 PeripheralKeyHandle = NULL; 395 } 396 397 /* No controller was found, cleanup and bail out */ 398 if (!NT_SUCCESS(Status)) 399 { 400 Status = STATUS_SUCCESS; 401 goto EndLoop; 402 } 403 404 /* Find out peripheral number */ 405 PeripheralNumber = 0; 406 MaximumPeripheralNumber = PeripheralFullInformation->SubKeys; 407 408 /* Cleanup */ 409 ExFreePoolWithTag(PeripheralFullInformation, TAG_IO_RESOURCE); 410 PeripheralFullInformation = NULL; 411 } 412 413 /* Save name */ 414 ControllerRegName = ControllerRootRegName; 415 416 /* Loop through peripherals */ 417 for (; PeripheralNumber < MaximumPeripheralNumber; PeripheralNumber++) 418 { 419 /* Restore name */ 420 ControllerRootRegName = ControllerRegName; 421 422 /* Convert peripheral number to registry string */ 423 Status = RtlIntegerToUnicodeString(PeripheralNumber, 10, &TempString); 424 425 /* Create string */ 426 Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); 427 Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString); 428 429 /* Something messed up */ 430 if (!NT_SUCCESS(Status)) 431 break; 432 433 IORSRCTRACE(" Retrieving peripheral '%wZ'\n", &ControllerRootRegName); 434 435 /* Open the registry key */ 436 InitializeObjectAttributes(&ObjectAttributes, 437 &ControllerRootRegName, 438 OBJ_CASE_INSENSITIVE, 439 NULL, 440 NULL); 441 442 Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes); 443 444 if (NT_SUCCESS(Status)) 445 { 446 for (PeripheralLoop = 0; PeripheralLoop < RTL_NUMBER_OF(IoDeviceInfoNames); PeripheralLoop++) 447 { 448 /* Identifier string first */ 449 RtlInitUnicodeString(&PeripheralString, IoDeviceInfoNames[PeripheralLoop]); 450 451 /* Retrieve the necessary buffer space */ 452 Status = ZwQueryValueKey(PeripheralKeyHandle, 453 &PeripheralString, 454 KeyValueFullInformation, 455 NULL, 0, 456 &LenKeyFullInformation); 457 458 if (!NT_SUCCESS(Status) && 459 (Status != STATUS_BUFFER_TOO_SMALL) && 460 (Status != STATUS_BUFFER_OVERFLOW)) 461 { 462 PeripheralInformation[PeripheralLoop] = NULL; 463 continue; 464 } 465 466 /* Allocate it */ 467 PeripheralInformation[PeripheralLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE); 468 if (!PeripheralInformation[PeripheralLoop]) 469 { 470 Status = STATUS_INSUFFICIENT_RESOURCES; 471 break; 472 } 473 474 /* Get the information */ 475 Status = ZwQueryValueKey(PeripheralKeyHandle, 476 &PeripheralString, 477 KeyValueFullInformation, 478 PeripheralInformation[PeripheralLoop], 479 LenKeyFullInformation, 480 &LenKeyFullInformation); 481 } 482 483 /* Cleanup */ 484 ZwClose(PeripheralKeyHandle); 485 PeripheralKeyHandle = NULL; 486 487 /* We now have everything the caller could possibly want */ 488 if (NT_SUCCESS(Status)) 489 { 490 IORSRCTRACE(" --> Bus #%lu Controller #%lu Peripheral #%lu Callout: '%wZ'\n", 491 Bus, ControllerNumber, PeripheralNumber, &ControllerRootRegName); 492 493 Status = Query->CalloutRoutine(Query->Context, 494 &ControllerRootRegName, 495 *Query->BusType, 496 Bus, 497 BusInformation, 498 *Query->ControllerType, 499 ControllerNumber, 500 ControllerInformation, 501 *Query->PeripheralType, 502 PeripheralNumber, 503 PeripheralInformation); 504 } 505 506 /* Free the allocated memory */ 507 for (PeripheralLoop = 0; PeripheralLoop < RTL_NUMBER_OF(IoDeviceInfoNames); PeripheralLoop++) 508 { 509 if (PeripheralInformation[PeripheralLoop]) 510 { 511 ExFreePoolWithTag(PeripheralInformation[PeripheralLoop], TAG_IO_RESOURCE); 512 PeripheralInformation[PeripheralLoop] = NULL; 513 } 514 } 515 516 /* Something messed up */ 517 if (!NT_SUCCESS(Status)) 518 break; 519 } 520 } 521 522 EndLoop: 523 /* Free the allocated memory */ 524 for (ControllerLoop = 0; ControllerLoop < RTL_NUMBER_OF(IoDeviceInfoNames); ControllerLoop++) 525 { 526 if (ControllerInformation[ControllerLoop]) 527 { 528 ExFreePoolWithTag(ControllerInformation[ControllerLoop], TAG_IO_RESOURCE); 529 ControllerInformation[ControllerLoop] = NULL; 530 } 531 } 532 533 /* Something messed up */ 534 if (!NT_SUCCESS(Status)) 535 break; 536 } 537 538 return Status; 539 } 540 541 /** 542 * @brief 543 * Reads and returns Hardware information from the appropriate hardware 544 * registry key. Helper stub of IoQueryDeviceDescription(). Has two modes 545 * of operation, either looking for root bus types or for sub-bus 546 * information. 547 * 548 * @param[in] Query 549 * What the parent function wants. 550 * 551 * @param[in] RootKey 552 * Which key to look in. 553 * 554 * @param[in] RootKeyHandle 555 * Handle to the key. 556 * 557 * @param[in,out] Bus 558 * Pointer to the current bus number. 559 * 560 * @param[in] KeyIsRoot 561 * Whether we are looking for root bus types or information under them. 562 * 563 * @return A status code. 564 **/ 565 static NTSTATUS 566 IopQueryBusDescription( 567 _In_ PIO_QUERY Query, 568 _In_ UNICODE_STRING RootKey, 569 _In_ HANDLE RootKeyHandle, 570 _Inout_ PULONG Bus, 571 _In_ BOOLEAN KeyIsRoot) 572 { 573 NTSTATUS Status; 574 ULONG BusLoop; 575 UNICODE_STRING SubRootRegName; 576 UNICODE_STRING BusString; 577 UNICODE_STRING SubBusString; 578 ULONG LenBasicInformation = 0; 579 ULONG LenFullInformation; 580 ULONG LenKeyFullInformation; 581 ULONG LenKey; 582 HANDLE SubRootKeyHandle; 583 PKEY_FULL_INFORMATION FullInformation; 584 PKEY_BASIC_INFORMATION BasicInformation = NULL; 585 OBJECT_ATTRIBUTES ObjectAttributes; 586 PKEY_VALUE_FULL_INFORMATION BusInformation[IoQueryDeviceMaxData] = 587 {NULL, NULL, NULL}; 588 589 IORSRCTRACE("\nIopQueryBusDescription(Query: 0x%p)\n" 590 " RootKey: '%wZ'\n" 591 " RootKeyHandle: 0x%p\n" 592 " KeyIsRoot: %s\n" 593 " Bus: 0x%p (%lu)\n", 594 Query, 595 &RootKey, RootKeyHandle, 596 KeyIsRoot ? "TRUE" : "FALSE", 597 Bus, Bus ? *Bus : -1); 598 599 /* Retrieve the necessary buffer space */ 600 Status = ZwQueryKey(RootKeyHandle, 601 KeyFullInformation, 602 NULL, 0, 603 &LenFullInformation); 604 605 if (!NT_SUCCESS(Status) && 606 (Status != STATUS_BUFFER_TOO_SMALL) && 607 (Status != STATUS_BUFFER_OVERFLOW)) 608 { 609 return Status; 610 } 611 612 /* Allocate it */ 613 FullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE); 614 if (!FullInformation) 615 return STATUS_INSUFFICIENT_RESOURCES; 616 617 /* Get the information */ 618 Status = ZwQueryKey(RootKeyHandle, 619 KeyFullInformation, 620 FullInformation, 621 LenFullInformation, 622 &LenFullInformation); 623 if (NT_SUCCESS(Status)) 624 { 625 /* Buffer needed for all the keys under this one */ 626 LenBasicInformation = FullInformation->MaxNameLen + sizeof(KEY_BASIC_INFORMATION); 627 628 /* Allocate it */ 629 BasicInformation = ExAllocatePoolWithTag(PagedPool, LenBasicInformation, TAG_IO_RESOURCE); 630 if (!BasicInformation) 631 { 632 ExFreePoolWithTag(FullInformation, TAG_IO_RESOURCE); 633 return STATUS_INSUFFICIENT_RESOURCES; 634 } 635 } 636 637 /* Deallocate the old buffer */ 638 ExFreePoolWithTag(FullInformation, TAG_IO_RESOURCE); 639 640 /* Try to find a bus */ 641 for (BusLoop = 0; NT_SUCCESS(Status); BusLoop++) 642 { 643 /* Bus parameter was passed and number was matched */ 644 if (Query->BusNumber && (*(Query->BusNumber) == *Bus)) 645 break; 646 647 /* Enumerate the Key */ 648 Status = ZwEnumerateKey(RootKeyHandle, 649 BusLoop, 650 KeyBasicInformation, 651 BasicInformation, 652 LenBasicInformation, 653 &LenKey); 654 655 /* Stop if everything was enumerated */ 656 if (!NT_SUCCESS(Status)) 657 break; 658 659 IORSRCTRACE(" Seen: '%.*ws'\n", BasicInformation->NameLength/sizeof(WCHAR), BasicInformation->Name); 660 661 /* What bus are we going to go down? (only check if this is a root key) */ 662 if (KeyIsRoot) 663 { 664 if (wcsncmp(BasicInformation->Name, L"MultifunctionAdapter", BasicInformation->NameLength / sizeof(WCHAR)) && 665 wcsncmp(BasicInformation->Name, L"EisaAdapter", BasicInformation->NameLength / sizeof(WCHAR)) && 666 wcsncmp(BasicInformation->Name, L"TcAdapter", BasicInformation->NameLength / sizeof(WCHAR))) 667 { 668 /* Nothing found, check next */ 669 continue; 670 } 671 } 672 673 /* Enumerate the bus */ 674 BusString.Buffer = BasicInformation->Name; 675 BusString.Length = (USHORT)BasicInformation->NameLength; 676 BusString.MaximumLength = (USHORT)BasicInformation->NameLength; 677 678 /* Open a handle to the root registry key */ 679 InitializeObjectAttributes(&ObjectAttributes, 680 &BusString, 681 OBJ_CASE_INSENSITIVE, 682 RootKeyHandle, 683 NULL); 684 685 Status = ZwOpenKey(&SubRootKeyHandle, KEY_READ, &ObjectAttributes); 686 687 /* Go on if we failed */ 688 if (!NT_SUCCESS(Status)) 689 continue; 690 691 /* Key opened, create the path */ 692 SubRootRegName = RootKey; 693 RtlAppendUnicodeToString(&SubRootRegName, L"\\"); 694 RtlAppendUnicodeStringToString(&SubRootRegName, &BusString); 695 696 IORSRCTRACE(" SubRootRegName: '%wZ'\n", &SubRootRegName); 697 698 if (!KeyIsRoot) 699 { 700 /* Parsing a sub-bus key */ 701 ULONG SubBusLoop; 702 for (SubBusLoop = 0; SubBusLoop < RTL_NUMBER_OF(IoDeviceInfoNames); SubBusLoop++) 703 { 704 /* Identifier string first */ 705 RtlInitUnicodeString(&SubBusString, IoDeviceInfoNames[SubBusLoop]); 706 707 IORSRCTRACE(" Getting bus value: '%wZ'\n", &SubBusString); 708 709 /* Retrieve the necessary buffer space */ 710 ZwQueryValueKey(SubRootKeyHandle, 711 &SubBusString, 712 KeyValueFullInformation, 713 NULL, 0, 714 &LenKeyFullInformation); 715 716 /* Allocate it */ 717 BusInformation[SubBusLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE); 718 if (!BusInformation[SubBusLoop]) 719 { 720 Status = STATUS_INSUFFICIENT_RESOURCES; 721 break; 722 } 723 724 /* Get the information */ 725 Status = ZwQueryValueKey(SubRootKeyHandle, 726 &SubBusString, 727 KeyValueFullInformation, 728 BusInformation[SubBusLoop], 729 LenKeyFullInformation, 730 &LenKeyFullInformation); 731 } 732 733 if (NT_SUCCESS(Status)) 734 { 735 PKEY_VALUE_FULL_INFORMATION BusConfigData = 736 BusInformation[IoQueryDeviceConfigurationData]; 737 738 /* Do we have something? */ 739 if (BusConfigData != NULL && 740 BusConfigData->DataLength != 0 && 741 /* Does it match what we want? */ 742 (((PCM_FULL_RESOURCE_DESCRIPTOR)((ULONG_PTR)BusConfigData + 743 BusConfigData->DataOffset))->InterfaceType == *(Query->BusType))) 744 { 745 /* Found a bus */ 746 (*Bus)++; 747 748 /* Is it the bus we wanted? */ 749 if (Query->BusNumber == NULL || *(Query->BusNumber) == *Bus) 750 { 751 if (Query->ControllerType == NULL) 752 { 753 IORSRCTRACE(" --> Bus #%lu Callout: '%wZ'\n", *Bus, &SubRootRegName); 754 755 /* We don't want controller information: call the callback */ 756 Status = Query->CalloutRoutine(Query->Context, 757 &SubRootRegName, 758 *(Query->BusType), 759 *Bus, 760 BusInformation, 761 0, 762 0, 763 NULL, 764 0, 765 0, 766 NULL); 767 } 768 else 769 { 770 IORSRCTRACE(" --> Getting device on Bus #%lu : '%wZ'\n", *Bus, &SubRootRegName); 771 772 /* We want controller information: get it */ 773 Status = IopQueryDeviceDescription(Query, 774 SubRootRegName, 775 RootKeyHandle, 776 *Bus, 777 (PKEY_VALUE_FULL_INFORMATION*)BusInformation); 778 } 779 } 780 } 781 } 782 783 /* Free the allocated memory */ 784 for (SubBusLoop = 0; SubBusLoop < RTL_NUMBER_OF(IoDeviceInfoNames); SubBusLoop++) 785 { 786 if (BusInformation[SubBusLoop]) 787 { 788 ExFreePoolWithTag(BusInformation[SubBusLoop], TAG_IO_RESOURCE); 789 BusInformation[SubBusLoop] = NULL; 790 } 791 } 792 793 /* Exit the loop if we found the bus */ 794 if (Query->BusNumber && (*(Query->BusNumber) == *Bus)) 795 { 796 ZwClose(SubRootKeyHandle); 797 SubRootKeyHandle = NULL; 798 continue; 799 } 800 } 801 802 /* Enumerate the buses below us recursively if we haven't found the bus yet */ 803 Status = IopQueryBusDescription(Query, SubRootRegName, SubRootKeyHandle, Bus, !KeyIsRoot); 804 805 /* Everything enumerated */ 806 if (Status == STATUS_NO_MORE_ENTRIES) 807 Status = STATUS_SUCCESS; 808 809 ZwClose(SubRootKeyHandle); 810 SubRootKeyHandle = NULL; 811 } 812 813 /* Free the last remaining allocated memory */ 814 if (BasicInformation) 815 ExFreePoolWithTag(BasicInformation, TAG_IO_RESOURCE); 816 817 return Status; 818 } 819 820 NTSTATUS 821 IopFetchConfigurationInformation( 822 _Out_ PWSTR* SymbolicLinkList, 823 _In_ GUID Guid, 824 _In_ ULONG ExpectedInterfaces, 825 _Out_ PULONG Interfaces) 826 { 827 NTSTATUS Status; 828 ULONG interfaces = 0; 829 PWSTR symbolicLinkList; 830 831 /* Get the associated enabled interfaces with the given GUID */ 832 Status = IoGetDeviceInterfaces(&Guid, NULL, 0, SymbolicLinkList); 833 if (!NT_SUCCESS(Status)) 834 { 835 /* Zero output and leave */ 836 if (SymbolicLinkList) 837 *SymbolicLinkList = NULL; 838 839 return STATUS_UNSUCCESSFUL; 840 } 841 842 symbolicLinkList = *SymbolicLinkList; 843 844 /* Count the number of enabled interfaces by counting the number of symbolic links */ 845 while (*symbolicLinkList != UNICODE_NULL) 846 { 847 interfaces++; 848 symbolicLinkList += (wcslen(symbolicLinkList) + 1); 849 } 850 851 /* Matching result will define the result */ 852 Status = (interfaces >= ExpectedInterfaces) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 853 /* Finally, give back to the caller the number of found interfaces */ 854 *Interfaces = interfaces; 855 856 return Status; 857 } 858 859 VOID 860 IopStoreSystemPartitionInformation( 861 _In_ PUNICODE_STRING NtSystemPartitionDeviceName, 862 _In_ PUNICODE_STRING OsLoaderPathName) 863 { 864 NTSTATUS Status; 865 UNICODE_STRING LinkTarget, KeyName; 866 OBJECT_ATTRIBUTES ObjectAttributes; 867 HANDLE LinkHandle, RegistryHandle, KeyHandle; 868 WCHAR LinkTargetBuffer[256]; 869 UNICODE_STRING CmRegistryMachineSystemName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM"); 870 871 ASSERT(NtSystemPartitionDeviceName->MaximumLength >= NtSystemPartitionDeviceName->Length + sizeof(WCHAR)); 872 ASSERT(NtSystemPartitionDeviceName->Buffer[NtSystemPartitionDeviceName->Length / sizeof(WCHAR)] == UNICODE_NULL); 873 ASSERT(OsLoaderPathName->MaximumLength >= OsLoaderPathName->Length + sizeof(WCHAR)); 874 ASSERT(OsLoaderPathName->Buffer[OsLoaderPathName->Length / sizeof(WCHAR)] == UNICODE_NULL); 875 876 /* First define needed stuff to open NtSystemPartitionDeviceName symbolic link */ 877 InitializeObjectAttributes(&ObjectAttributes, 878 NtSystemPartitionDeviceName, 879 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 880 NULL, 881 NULL); 882 883 /* Open NtSystemPartitionDeviceName symbolic link */ 884 Status = ZwOpenSymbolicLinkObject(&LinkHandle, 885 SYMBOLIC_LINK_QUERY, 886 &ObjectAttributes); 887 if (!NT_SUCCESS(Status)) 888 { 889 DPRINT("Failed to open symlink %wZ, Status=%lx\n", NtSystemPartitionDeviceName, Status); 890 return; 891 } 892 893 /* Prepare the string that will receive where symbolic link points to. 894 * We will zero the end of the string after having received it */ 895 RtlInitEmptyUnicodeString(&LinkTarget, LinkTargetBuffer, 896 sizeof(LinkTargetBuffer) - sizeof(UNICODE_NULL)); 897 898 /* Query target */ 899 Status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkTarget, NULL); 900 901 /* We are done with symbolic link */ 902 ObCloseHandle(LinkHandle, KernelMode); 903 904 if (!NT_SUCCESS(Status)) 905 { 906 DPRINT("Failed querying symlink %wZ, Status=%lx\n", NtSystemPartitionDeviceName, Status); 907 return; 908 } 909 910 /* As promised, we zero the end */ 911 LinkTarget.Buffer[LinkTarget.Length / sizeof(WCHAR)] = UNICODE_NULL; 912 913 /* Open registry to save data (HKLM\SYSTEM) */ 914 Status = IopOpenRegistryKeyEx(&RegistryHandle, 915 NULL, 916 &CmRegistryMachineSystemName, 917 KEY_ALL_ACCESS); 918 if (!NT_SUCCESS(Status)) 919 { 920 DPRINT("Failed to open HKLM\\SYSTEM, Status=%lx\n", Status); 921 return; 922 } 923 924 /* Open or create the Setup subkey where we'll store in */ 925 RtlInitUnicodeString(&KeyName, L"Setup"); 926 927 Status = IopCreateRegistryKeyEx(&KeyHandle, 928 RegistryHandle, 929 &KeyName, 930 KEY_ALL_ACCESS, 931 REG_OPTION_NON_VOLATILE, 932 NULL); 933 934 /* We're done with HKLM\SYSTEM */ 935 ObCloseHandle(RegistryHandle, KernelMode); 936 937 if (!NT_SUCCESS(Status)) 938 { 939 DPRINT("Failed opening/creating Setup key, Status=%lx\n", Status); 940 return; 941 } 942 943 /* Prepare first data writing */ 944 RtlInitUnicodeString(&KeyName, L"SystemPartition"); 945 946 /* Write SystemPartition value which is the target of the symbolic link */ 947 Status = ZwSetValueKey(KeyHandle, 948 &KeyName, 949 0, 950 REG_SZ, 951 LinkTarget.Buffer, 952 LinkTarget.Length + sizeof(WCHAR)); 953 if (!NT_SUCCESS(Status)) 954 { 955 DPRINT("Failed writing SystemPartition value, Status=%lx\n", Status); 956 } 957 958 /* Prepare for second data writing */ 959 RtlInitUnicodeString(&KeyName, L"OsLoaderPath"); 960 961 /* Remove trailing slash if any (one slash only excepted) */ 962 if (OsLoaderPathName->Length > sizeof(WCHAR) && 963 OsLoaderPathName->Buffer[(OsLoaderPathName->Length / sizeof(WCHAR)) - 1] == OBJ_NAME_PATH_SEPARATOR) 964 { 965 OsLoaderPathName->Length -= sizeof(WCHAR); 966 OsLoaderPathName->Buffer[OsLoaderPathName->Length / sizeof(WCHAR)] = UNICODE_NULL; 967 } 968 969 /* Then, write down data */ 970 Status = ZwSetValueKey(KeyHandle, 971 &KeyName, 972 0, 973 REG_SZ, 974 OsLoaderPathName->Buffer, 975 OsLoaderPathName->Length + sizeof(UNICODE_NULL)); 976 if (!NT_SUCCESS(Status)) 977 { 978 DPRINT("Failed writing OsLoaderPath value, Status=%lx\n", Status); 979 } 980 981 /* We're finally done! */ 982 ObCloseHandle(KeyHandle, KernelMode); 983 } 984 985 /* PUBLIC FUNCTIONS ***********************************************************/ 986 987 /** 988 * @brief 989 * Returns a pointer to the I/O manager's global configuration 990 * information structure. 991 * 992 * This structure contains the current values for how many physical storage 993 * media, SCSI HBA, serial, and parallel devices have device objects created 994 * to represent them by drivers as they are loaded. 995 **/ 996 PCONFIGURATION_INFORMATION 997 NTAPI 998 IoGetConfigurationInformation(VOID) 999 { 1000 return &_SystemConfigurationInformation; 1001 } 1002 1003 /** 1004 * @halfplemented 1005 * 1006 * @brief 1007 * Reports hardware resources in the \Registry\Machine\Hardware\ResourceMap 1008 * tree, so that a subsequently loaded driver cannot attempt to use the 1009 * same resources. 1010 * 1011 * @param[in] DriverClassName 1012 * The driver class under which the resource information should be stored. 1013 * 1014 * @param[in] DriverObject 1015 * The driver object that was provided to the DriverEntry routine. 1016 * 1017 * @param[in] DriverList 1018 * Resources claimed for the all the driver's devices, rather than per-device. 1019 * 1020 * @param[in] DriverListSize 1021 * Size in bytes of the DriverList. 1022 * 1023 * @param[in] DeviceObject 1024 * The device object for which resources should be claimed. 1025 * 1026 * @param[in] DeviceList 1027 * List of resources that should be claimed for the device. 1028 * 1029 * @param[in] DeviceListSize 1030 * Size of the per-device resource list in bytes. 1031 * 1032 * @param[in] OverrideConflict 1033 * TRUE if the resources should be claimed even if a conflict is found. 1034 * 1035 * @param[out] ConflictDetected 1036 * Points to a variable that receives TRUE if a conflict is detected 1037 * with another driver. 1038 **/ 1039 NTSTATUS 1040 NTAPI 1041 IoReportResourceUsage( 1042 _In_opt_ PUNICODE_STRING DriverClassName, 1043 _In_ PDRIVER_OBJECT DriverObject, 1044 _In_reads_bytes_opt_(DriverListSize) PCM_RESOURCE_LIST DriverList, 1045 _In_opt_ ULONG DriverListSize, 1046 _In_opt_ PDEVICE_OBJECT DeviceObject, 1047 _In_reads_bytes_opt_(DeviceListSize) PCM_RESOURCE_LIST DeviceList, 1048 _In_opt_ ULONG DeviceListSize, 1049 _In_ BOOLEAN OverrideConflict, 1050 _Out_ PBOOLEAN ConflictDetected) 1051 { 1052 NTSTATUS Status; 1053 PCM_RESOURCE_LIST ResourceList; 1054 1055 DPRINT1("IoReportResourceUsage is halfplemented!\n"); 1056 1057 if (!DriverList && !DeviceList) 1058 return STATUS_INVALID_PARAMETER; 1059 1060 if (DeviceList) 1061 ResourceList = DeviceList; 1062 else 1063 ResourceList = DriverList; 1064 1065 Status = IopDetectResourceConflict(ResourceList, FALSE, NULL); 1066 if (Status == STATUS_CONFLICTING_ADDRESSES) 1067 { 1068 *ConflictDetected = TRUE; 1069 1070 if (!OverrideConflict) 1071 { 1072 DPRINT1("Denying an attempt to claim resources currently in use by another device!\n"); 1073 return STATUS_CONFLICTING_ADDRESSES; 1074 } 1075 else 1076 { 1077 DPRINT1("Proceeding with conflicting resources\n"); 1078 } 1079 } 1080 else if (!NT_SUCCESS(Status)) 1081 { 1082 return Status; 1083 } 1084 1085 /* TODO: Claim resources in registry */ 1086 1087 *ConflictDetected = FALSE; 1088 1089 return STATUS_SUCCESS; 1090 } 1091 1092 static NTSTATUS 1093 IopLegacyResourceAllocation( 1094 _In_ ARBITER_REQUEST_SOURCE AllocationType, 1095 _In_ PDRIVER_OBJECT DriverObject, 1096 _In_opt_ PDEVICE_OBJECT DeviceObject, 1097 _In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements, 1098 _Inout_ PCM_RESOURCE_LIST* AllocatedResources) 1099 { 1100 NTSTATUS Status; 1101 1102 DPRINT1("IopLegacyResourceAllocation is halfplemented!\n"); 1103 1104 if (!ResourceRequirements) 1105 { 1106 /* We can get there by calling IoAssignResources() with RequestedResources = NULL. 1107 * TODO: not sure what we should do, but we shouldn't crash. 1108 */ 1109 UNIMPLEMENTED; 1110 return STATUS_NOT_IMPLEMENTED; 1111 } 1112 1113 Status = IopFixupResourceListWithRequirements(ResourceRequirements, 1114 AllocatedResources); 1115 if (!NT_SUCCESS(Status)) 1116 { 1117 if (Status == STATUS_CONFLICTING_ADDRESSES) 1118 { 1119 DPRINT1("Denying an attempt to claim resources currently in use by another device!\n"); 1120 } 1121 1122 return Status; 1123 } 1124 1125 /* TODO: Claim resources in registry */ 1126 return STATUS_SUCCESS; 1127 } 1128 1129 /* 1130 * @implemented 1131 */ 1132 NTSTATUS 1133 NTAPI 1134 IoAssignResources( 1135 _In_ PUNICODE_STRING RegistryPath, 1136 _In_opt_ PUNICODE_STRING DriverClassName, 1137 _In_ PDRIVER_OBJECT DriverObject, 1138 _In_opt_ PDEVICE_OBJECT DeviceObject, 1139 _In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources, 1140 _Inout_ PCM_RESOURCE_LIST* AllocatedResources) 1141 { 1142 PDEVICE_NODE DeviceNode; 1143 1144 UNREFERENCED_PARAMETER(RegistryPath); 1145 UNREFERENCED_PARAMETER(DriverClassName); 1146 1147 /* Do we have a DO? */ 1148 if (DeviceObject) 1149 { 1150 /* Get its device node */ 1151 DeviceNode = IopGetDeviceNode(DeviceObject); 1152 if (DeviceNode && !(DeviceNode->Flags & DNF_LEGACY_RESOURCE_DEVICENODE)) 1153 { 1154 /* New drivers should not call this API */ 1155 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 1156 0x2, 1157 (ULONG_PTR)DeviceObject, 1158 (ULONG_PTR)DriverObject, 1159 0); 1160 } 1161 } 1162 1163 /* Did the driver supply resources? */ 1164 if (RequestedResources) 1165 { 1166 /* Make sure there's actually something useful in them */ 1167 if (!(RequestedResources->AlternativeLists) || !(RequestedResources->List[0].Count)) 1168 { 1169 /* Empty resources are no resources */ 1170 RequestedResources = NULL; 1171 } 1172 } 1173 1174 /* Initialize output if given */ 1175 if (AllocatedResources) 1176 *AllocatedResources = NULL; 1177 1178 /* Call internal helper function */ 1179 return IopLegacyResourceAllocation(ArbiterRequestLegacyAssigned, 1180 DriverObject, 1181 DeviceObject, 1182 RequestedResources, 1183 AllocatedResources); 1184 } 1185 1186 /** 1187 * @brief 1188 * Reads and returns Hardware information from the appropriate 1189 * hardware registry key. 1190 * 1191 * @param[in] BusType 1192 * Specifies the bus type, for example: MCA, ISA, EISA, etc. 1193 * 1194 * @param[in] BusNumber 1195 * The number of the specified bus type to query. 1196 * 1197 * @param[in] ControllerType 1198 * Specifies the controller type 1199 * 1200 * @param[in] ControllerNumber 1201 * The number of the specified controller type to query. 1202 * 1203 * @param[in] CalloutRoutine 1204 * A user-provided callback function to call for each valid query. 1205 * 1206 * @param[in] Context 1207 * A callback-specific context value. 1208 * 1209 * @return A status code. 1210 **/ 1211 NTSTATUS 1212 NTAPI 1213 IoQueryDeviceDescription( 1214 _In_opt_ PINTERFACE_TYPE BusType, 1215 _In_opt_ PULONG BusNumber, 1216 _In_opt_ PCONFIGURATION_TYPE ControllerType, 1217 _In_opt_ PULONG ControllerNumber, 1218 _In_opt_ PCONFIGURATION_TYPE PeripheralType, 1219 _In_opt_ PULONG PeripheralNumber, 1220 _In_ PIO_QUERY_DEVICE_ROUTINE CalloutRoutine, 1221 _In_opt_ PVOID Context) 1222 { 1223 NTSTATUS Status; 1224 ULONG BusLoopNumber = -1; /* Root Bus */ 1225 OBJECT_ATTRIBUTES ObjectAttributes; 1226 UNICODE_STRING RootRegKey; 1227 HANDLE RootRegHandle; 1228 IO_QUERY Query; 1229 1230 IORSRCTRACE("\nIoQueryDeviceDescription()\n" 1231 " BusType: 0x%p (%lu)\n" 1232 " BusNumber: 0x%p (%lu)\n" 1233 " ControllerType: 0x%p (%lu)\n" 1234 " ControllerNumber: 0x%p (%lu)\n" 1235 " PeripheralType: 0x%p (%lu)\n" 1236 " PeripheralNumber: 0x%p (%lu)\n" 1237 " CalloutRoutine: 0x%p\n" 1238 " Context: 0x%p\n" 1239 "--> Query: 0x%p\n", 1240 BusType, BusType ? *BusType : -1, 1241 BusNumber, BusNumber ? *BusNumber : -1, 1242 ControllerType, ControllerType ? *ControllerType : -1, 1243 ControllerNumber, ControllerNumber ? *ControllerNumber : -1, 1244 PeripheralType, PeripheralType ? *PeripheralType : -1, 1245 PeripheralNumber, PeripheralNumber ? *PeripheralNumber : -1, 1246 CalloutRoutine, Context, 1247 &Query); 1248 1249 if (!BusType) 1250 return STATUS_NOT_IMPLEMENTED; 1251 1252 /* Set up the string */ 1253 RootRegKey.Length = 0; 1254 RootRegKey.MaximumLength = 2048; 1255 RootRegKey.Buffer = ExAllocatePoolWithTag(PagedPool, RootRegKey.MaximumLength, TAG_IO_RESOURCE); 1256 if (!RootRegKey.Buffer) 1257 return STATUS_INSUFFICIENT_RESOURCES; 1258 1259 RtlAppendUnicodeToString(&RootRegKey, L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM"); 1260 1261 /* Open a handle to the Root Registry Key */ 1262 InitializeObjectAttributes(&ObjectAttributes, 1263 &RootRegKey, 1264 OBJ_CASE_INSENSITIVE, 1265 NULL, 1266 NULL); 1267 1268 Status = ZwOpenKey(&RootRegHandle, KEY_READ, &ObjectAttributes); 1269 1270 if (NT_SUCCESS(Status)) 1271 { 1272 /* Use a helper function to loop though this key and get the information */ 1273 Query.BusType = BusType; 1274 Query.BusNumber = BusNumber; 1275 Query.ControllerType = ControllerType; 1276 Query.ControllerNumber = ControllerNumber; 1277 Query.PeripheralType = PeripheralType; 1278 Query.PeripheralNumber = PeripheralNumber; 1279 Query.CalloutRoutine = CalloutRoutine; 1280 Query.Context = Context; 1281 Status = IopQueryBusDescription(&Query, 1282 RootRegKey, 1283 RootRegHandle, 1284 &BusLoopNumber, 1285 TRUE); 1286 1287 /* Close registry key */ 1288 ZwClose(RootRegHandle); 1289 } 1290 1291 /* Cleanup */ 1292 ExFreePoolWithTag(RootRegKey.Buffer, TAG_IO_RESOURCE); 1293 1294 return Status; 1295 } 1296 1297 /** 1298 * @brief 1299 * Reports hardware resources of the HAL in the 1300 * \Registry\Machine\Hardware\ResourceMap tree. 1301 * 1302 * @param[in] HalName 1303 * Descriptive name of the HAL. 1304 * 1305 * @param[in] RawResourceList 1306 * List of raw (bus specific) resources which should be claimed 1307 * for the HAL. 1308 * 1309 * @param[in] TranslatedResourceList 1310 * List of translated (system wide) resources which should be claimed 1311 * for the HAL. 1312 * 1313 * @param[in] ResourceListSize 1314 * Size in bytes of the raw and translated resource lists. 1315 * Both lists have the same size. 1316 * 1317 * @return A status code. 1318 **/ 1319 NTSTATUS 1320 NTAPI 1321 IoReportHalResourceUsage( 1322 _In_ PUNICODE_STRING HalName, 1323 _In_ PCM_RESOURCE_LIST RawResourceList, 1324 _In_ PCM_RESOURCE_LIST TranslatedResourceList, 1325 _In_ ULONG ResourceListSize) 1326 { 1327 NTSTATUS Status; 1328 OBJECT_ATTRIBUTES ObjectAttributes; 1329 UNICODE_STRING Name; 1330 ULONG Disposition; 1331 HANDLE ResourceMapKey; 1332 HANDLE HalKey; 1333 HANDLE DescriptionKey; 1334 1335 /* Open/Create 'RESOURCEMAP' key */ 1336 RtlInitUnicodeString(&Name, L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP"); 1337 InitializeObjectAttributes(&ObjectAttributes, 1338 &Name, 1339 OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 1340 0, 1341 NULL); 1342 Status = ZwCreateKey(&ResourceMapKey, 1343 KEY_ALL_ACCESS, 1344 &ObjectAttributes, 1345 0, 1346 NULL, 1347 REG_OPTION_VOLATILE, 1348 &Disposition); 1349 if (!NT_SUCCESS(Status)) 1350 return Status; 1351 1352 /* Open/Create 'Hardware Abstraction Layer' key */ 1353 RtlInitUnicodeString(&Name, L"Hardware Abstraction Layer"); 1354 InitializeObjectAttributes(&ObjectAttributes, 1355 &Name, 1356 OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 1357 ResourceMapKey, 1358 NULL); 1359 Status = ZwCreateKey(&HalKey, 1360 KEY_ALL_ACCESS, 1361 &ObjectAttributes, 1362 0, 1363 NULL, 1364 REG_OPTION_VOLATILE, 1365 &Disposition); 1366 ZwClose(ResourceMapKey); 1367 if (!NT_SUCCESS(Status)) 1368 return Status; 1369 1370 /* Create 'HalName' key */ 1371 InitializeObjectAttributes(&ObjectAttributes, 1372 HalName, 1373 OBJ_CASE_INSENSITIVE, 1374 HalKey, 1375 NULL); 1376 Status = ZwCreateKey(&DescriptionKey, 1377 KEY_ALL_ACCESS, 1378 &ObjectAttributes, 1379 0, 1380 NULL, 1381 REG_OPTION_VOLATILE, 1382 &Disposition); 1383 ZwClose(HalKey); 1384 if (!NT_SUCCESS(Status)) 1385 return Status; 1386 1387 /* Add '.Raw' value */ 1388 RtlInitUnicodeString(&Name, L".Raw"); 1389 Status = ZwSetValueKey(DescriptionKey, 1390 &Name, 1391 0, 1392 REG_RESOURCE_LIST, 1393 RawResourceList, 1394 ResourceListSize); 1395 if (!NT_SUCCESS(Status)) 1396 { 1397 ZwClose(DescriptionKey); 1398 return Status; 1399 } 1400 1401 /* Add '.Translated' value */ 1402 RtlInitUnicodeString(&Name, L".Translated"); 1403 Status = ZwSetValueKey(DescriptionKey, 1404 &Name, 1405 0, 1406 REG_RESOURCE_LIST, 1407 TranslatedResourceList, 1408 ResourceListSize); 1409 ZwClose(DescriptionKey); 1410 1411 return Status; 1412 } 1413 1414 /* EOF */ 1415