1 /* 2 * PROJECT: ReactOS Kernel 3 * COPYRIGHT: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/io/pnpmgr/pnpmgr.c 5 * PURPOSE: Initializes the PnP manager 6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 * Copyright 2007 Herv� Poussineau (hpoussin@reactos.org) 8 */ 9 10 /* INCLUDES ******************************************************************/ 11 12 #include <ntoskrnl.h> 13 #define NDEBUG 14 #include <debug.h> 15 16 /* GLOBALS *******************************************************************/ 17 18 ERESOURCE PpRegistryDeviceResource; 19 KGUARDED_MUTEX PpDeviceReferenceTableLock; 20 RTL_AVL_TABLE PpDeviceReferenceTable; 21 BOOLEAN PnPBootDriversLoaded; 22 23 extern ULONG ExpInitializationPhase; 24 25 /* DATA **********************************************************************/ 26 27 PDRIVER_OBJECT IopRootDriverObject; 28 PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList = NULL; 29 30 /* FUNCTIONS *****************************************************************/ 31 32 VOID 33 IopFixupDeviceId(PWCHAR String) 34 { 35 SIZE_T Length = wcslen(String), i; 36 37 for (i = 0; i < Length; i++) 38 { 39 if (String[i] == L'\\') 40 String[i] = L'#'; 41 } 42 } 43 44 VOID 45 NTAPI 46 IopInstallCriticalDevice(PDEVICE_NODE DeviceNode) 47 { 48 NTSTATUS Status; 49 HANDLE CriticalDeviceKey, InstanceKey; 50 OBJECT_ATTRIBUTES ObjectAttributes; 51 UNICODE_STRING CriticalDeviceKeyU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\CriticalDeviceDatabase"); 52 UNICODE_STRING CompatibleIdU = RTL_CONSTANT_STRING(L"CompatibleIDs"); 53 UNICODE_STRING HardwareIdU = RTL_CONSTANT_STRING(L"HardwareID"); 54 UNICODE_STRING ServiceU = RTL_CONSTANT_STRING(L"Service"); 55 UNICODE_STRING ClassGuidU = RTL_CONSTANT_STRING(L"ClassGUID"); 56 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo; 57 ULONG HidLength = 0, CidLength = 0, BufferLength; 58 PWCHAR IdBuffer, OriginalIdBuffer; 59 60 /* Open the device instance key */ 61 Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey); 62 if (Status != STATUS_SUCCESS) 63 return; 64 65 Status = ZwQueryValueKey(InstanceKey, 66 &HardwareIdU, 67 KeyValuePartialInformation, 68 NULL, 69 0, 70 &HidLength); 71 if (Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL) 72 { 73 ZwClose(InstanceKey); 74 return; 75 } 76 77 Status = ZwQueryValueKey(InstanceKey, 78 &CompatibleIdU, 79 KeyValuePartialInformation, 80 NULL, 81 0, 82 &CidLength); 83 if (Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL) 84 { 85 CidLength = 0; 86 } 87 88 BufferLength = HidLength + CidLength; 89 BufferLength -= (((CidLength != 0) ? 2 : 1) * FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data)); 90 91 /* Allocate a buffer to hold data from both */ 92 OriginalIdBuffer = IdBuffer = ExAllocatePool(PagedPool, BufferLength); 93 if (!IdBuffer) 94 { 95 ZwClose(InstanceKey); 96 return; 97 } 98 99 /* Compute the buffer size */ 100 if (HidLength > CidLength) 101 BufferLength = HidLength; 102 else 103 BufferLength = CidLength; 104 105 PartialInfo = ExAllocatePool(PagedPool, BufferLength); 106 if (!PartialInfo) 107 { 108 ZwClose(InstanceKey); 109 ExFreePool(OriginalIdBuffer); 110 return; 111 } 112 113 Status = ZwQueryValueKey(InstanceKey, 114 &HardwareIdU, 115 KeyValuePartialInformation, 116 PartialInfo, 117 HidLength, 118 &HidLength); 119 if (Status != STATUS_SUCCESS) 120 { 121 ExFreePool(PartialInfo); 122 ExFreePool(OriginalIdBuffer); 123 ZwClose(InstanceKey); 124 return; 125 } 126 127 /* Copy in HID info first (without 2nd terminating NULL if CID is present) */ 128 HidLength = PartialInfo->DataLength - ((CidLength != 0) ? sizeof(WCHAR) : 0); 129 RtlCopyMemory(IdBuffer, PartialInfo->Data, HidLength); 130 131 if (CidLength != 0) 132 { 133 Status = ZwQueryValueKey(InstanceKey, 134 &CompatibleIdU, 135 KeyValuePartialInformation, 136 PartialInfo, 137 CidLength, 138 &CidLength); 139 if (Status != STATUS_SUCCESS) 140 { 141 ExFreePool(PartialInfo); 142 ExFreePool(OriginalIdBuffer); 143 ZwClose(InstanceKey); 144 return; 145 } 146 147 /* Copy CID next */ 148 CidLength = PartialInfo->DataLength; 149 RtlCopyMemory(((PUCHAR)IdBuffer) + HidLength, PartialInfo->Data, CidLength); 150 } 151 152 /* Free our temp buffer */ 153 ExFreePool(PartialInfo); 154 155 InitializeObjectAttributes(&ObjectAttributes, 156 &CriticalDeviceKeyU, 157 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 158 NULL, 159 NULL); 160 Status = ZwOpenKey(&CriticalDeviceKey, 161 KEY_ENUMERATE_SUB_KEYS, 162 &ObjectAttributes); 163 if (!NT_SUCCESS(Status)) 164 { 165 /* The critical device database doesn't exist because 166 * we're probably in 1st stage setup, but it's ok */ 167 ExFreePool(OriginalIdBuffer); 168 ZwClose(InstanceKey); 169 return; 170 } 171 172 while (*IdBuffer) 173 { 174 USHORT StringLength = (USHORT)wcslen(IdBuffer) + 1, Index; 175 176 IopFixupDeviceId(IdBuffer); 177 178 /* Look through all subkeys for a match */ 179 for (Index = 0; TRUE; Index++) 180 { 181 ULONG NeededLength; 182 PKEY_BASIC_INFORMATION BasicInfo; 183 184 Status = ZwEnumerateKey(CriticalDeviceKey, 185 Index, 186 KeyBasicInformation, 187 NULL, 188 0, 189 &NeededLength); 190 if (Status == STATUS_NO_MORE_ENTRIES) 191 break; 192 else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 193 { 194 UNICODE_STRING ChildIdNameU, RegKeyNameU; 195 196 BasicInfo = ExAllocatePool(PagedPool, NeededLength); 197 if (!BasicInfo) 198 { 199 /* No memory */ 200 ExFreePool(OriginalIdBuffer); 201 ZwClose(CriticalDeviceKey); 202 ZwClose(InstanceKey); 203 return; 204 } 205 206 Status = ZwEnumerateKey(CriticalDeviceKey, 207 Index, 208 KeyBasicInformation, 209 BasicInfo, 210 NeededLength, 211 &NeededLength); 212 if (Status != STATUS_SUCCESS) 213 { 214 /* This shouldn't happen */ 215 ExFreePool(BasicInfo); 216 continue; 217 } 218 219 ChildIdNameU.Buffer = IdBuffer; 220 ChildIdNameU.MaximumLength = ChildIdNameU.Length = (StringLength - 1) * sizeof(WCHAR); 221 RegKeyNameU.Buffer = BasicInfo->Name; 222 RegKeyNameU.MaximumLength = RegKeyNameU.Length = (USHORT)BasicInfo->NameLength; 223 224 if (RtlEqualUnicodeString(&ChildIdNameU, &RegKeyNameU, TRUE)) 225 { 226 HANDLE ChildKeyHandle; 227 228 InitializeObjectAttributes(&ObjectAttributes, 229 &ChildIdNameU, 230 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 231 CriticalDeviceKey, 232 NULL); 233 234 Status = ZwOpenKey(&ChildKeyHandle, 235 KEY_QUERY_VALUE, 236 &ObjectAttributes); 237 if (Status != STATUS_SUCCESS) 238 { 239 ExFreePool(BasicInfo); 240 continue; 241 } 242 243 /* Check if there's already a driver installed */ 244 Status = ZwQueryValueKey(InstanceKey, 245 &ClassGuidU, 246 KeyValuePartialInformation, 247 NULL, 248 0, 249 &NeededLength); 250 if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 251 { 252 ExFreePool(BasicInfo); 253 continue; 254 } 255 256 Status = ZwQueryValueKey(ChildKeyHandle, 257 &ClassGuidU, 258 KeyValuePartialInformation, 259 NULL, 260 0, 261 &NeededLength); 262 if (Status != STATUS_BUFFER_OVERFLOW && Status != STATUS_BUFFER_TOO_SMALL) 263 { 264 ExFreePool(BasicInfo); 265 continue; 266 } 267 268 PartialInfo = ExAllocatePool(PagedPool, NeededLength); 269 if (!PartialInfo) 270 { 271 ExFreePool(OriginalIdBuffer); 272 ExFreePool(BasicInfo); 273 ZwClose(InstanceKey); 274 ZwClose(ChildKeyHandle); 275 ZwClose(CriticalDeviceKey); 276 return; 277 } 278 279 /* Read ClassGUID entry in the CDDB */ 280 Status = ZwQueryValueKey(ChildKeyHandle, 281 &ClassGuidU, 282 KeyValuePartialInformation, 283 PartialInfo, 284 NeededLength, 285 &NeededLength); 286 if (Status != STATUS_SUCCESS) 287 { 288 ExFreePool(BasicInfo); 289 continue; 290 } 291 292 /* Write it to the ENUM key */ 293 Status = ZwSetValueKey(InstanceKey, 294 &ClassGuidU, 295 0, 296 REG_SZ, 297 PartialInfo->Data, 298 PartialInfo->DataLength); 299 if (Status != STATUS_SUCCESS) 300 { 301 ExFreePool(BasicInfo); 302 ExFreePool(PartialInfo); 303 ZwClose(ChildKeyHandle); 304 continue; 305 } 306 307 Status = ZwQueryValueKey(ChildKeyHandle, 308 &ServiceU, 309 KeyValuePartialInformation, 310 NULL, 311 0, 312 &NeededLength); 313 if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 314 { 315 ExFreePool(PartialInfo); 316 PartialInfo = ExAllocatePool(PagedPool, NeededLength); 317 if (!PartialInfo) 318 { 319 ExFreePool(OriginalIdBuffer); 320 ExFreePool(BasicInfo); 321 ZwClose(InstanceKey); 322 ZwClose(ChildKeyHandle); 323 ZwClose(CriticalDeviceKey); 324 return; 325 } 326 327 /* Read the service entry from the CDDB */ 328 Status = ZwQueryValueKey(ChildKeyHandle, 329 &ServiceU, 330 KeyValuePartialInformation, 331 PartialInfo, 332 NeededLength, 333 &NeededLength); 334 if (Status != STATUS_SUCCESS) 335 { 336 ExFreePool(BasicInfo); 337 ExFreePool(PartialInfo); 338 ZwClose(ChildKeyHandle); 339 continue; 340 } 341 342 /* Write it to the ENUM key */ 343 Status = ZwSetValueKey(InstanceKey, 344 &ServiceU, 345 0, 346 REG_SZ, 347 PartialInfo->Data, 348 PartialInfo->DataLength); 349 if (Status != STATUS_SUCCESS) 350 { 351 ExFreePool(BasicInfo); 352 ExFreePool(PartialInfo); 353 ZwClose(ChildKeyHandle); 354 continue; 355 } 356 357 DPRINT("Installed service '%S' for critical device '%wZ'\n", PartialInfo->Data, &ChildIdNameU); 358 } 359 else 360 { 361 DPRINT1("Installed NULL service for critical device '%wZ'\n", &ChildIdNameU); 362 } 363 364 ExFreePool(OriginalIdBuffer); 365 ExFreePool(PartialInfo); 366 ExFreePool(BasicInfo); 367 ZwClose(InstanceKey); 368 ZwClose(ChildKeyHandle); 369 ZwClose(CriticalDeviceKey); 370 371 /* That's it */ 372 return; 373 } 374 375 ExFreePool(BasicInfo); 376 } 377 else 378 { 379 /* Umm, not sure what happened here */ 380 continue; 381 } 382 } 383 384 /* Advance to the next ID */ 385 IdBuffer += StringLength; 386 } 387 388 ExFreePool(OriginalIdBuffer); 389 ZwClose(InstanceKey); 390 ZwClose(CriticalDeviceKey); 391 } 392 393 NTSTATUS 394 FASTCALL 395 IopInitializeDevice(PDEVICE_NODE DeviceNode, 396 PDRIVER_OBJECT DriverObject) 397 { 398 PDEVICE_OBJECT Fdo; 399 NTSTATUS Status; 400 401 if (!DriverObject) 402 { 403 /* Special case for bus driven devices */ 404 DeviceNode->Flags |= DNF_ADDED; 405 return STATUS_SUCCESS; 406 } 407 408 if (!DriverObject->DriverExtension->AddDevice) 409 { 410 DeviceNode->Flags |= DNF_LEGACY_DRIVER; 411 } 412 413 if (DeviceNode->Flags & DNF_LEGACY_DRIVER) 414 { 415 DeviceNode->Flags |= (DNF_ADDED | DNF_STARTED); 416 return STATUS_SUCCESS; 417 } 418 419 /* This is a Plug and Play driver */ 420 DPRINT("Plug and Play driver found\n"); 421 ASSERT(DeviceNode->PhysicalDeviceObject); 422 423 DPRINT("Calling %wZ->AddDevice(%wZ)\n", 424 &DriverObject->DriverName, 425 &DeviceNode->InstancePath); 426 Status = DriverObject->DriverExtension->AddDevice(DriverObject, 427 DeviceNode->PhysicalDeviceObject); 428 if (!NT_SUCCESS(Status)) 429 { 430 DPRINT1("%wZ->AddDevice(%wZ) failed with status 0x%x\n", 431 &DriverObject->DriverName, 432 &DeviceNode->InstancePath, 433 Status); 434 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED); 435 DeviceNode->Problem = CM_PROB_FAILED_ADD; 436 return Status; 437 } 438 439 Fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject); 440 441 /* Check if we have a ACPI device (needed for power management) */ 442 if (Fdo->DeviceType == FILE_DEVICE_ACPI) 443 { 444 static BOOLEAN SystemPowerDeviceNodeCreated = FALSE; 445 446 /* There can be only one system power device */ 447 if (!SystemPowerDeviceNodeCreated) 448 { 449 PopSystemPowerDeviceNode = DeviceNode; 450 ObReferenceObject(PopSystemPowerDeviceNode->PhysicalDeviceObject); 451 SystemPowerDeviceNodeCreated = TRUE; 452 } 453 } 454 455 ObDereferenceObject(Fdo); 456 457 IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED); 458 459 return STATUS_SUCCESS; 460 } 461 462 NTSTATUS 463 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject) 464 { 465 KIRQL OldIrql; 466 467 if (PopSystemPowerDeviceNode) 468 { 469 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql); 470 *DeviceObject = PopSystemPowerDeviceNode->PhysicalDeviceObject; 471 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql); 472 473 return STATUS_SUCCESS; 474 } 475 476 return STATUS_UNSUCCESSFUL; 477 } 478 479 USHORT 480 NTAPI 481 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid) 482 { 483 USHORT i = 0, FoundIndex = 0xFFFF; 484 ULONG NewSize; 485 PVOID NewList; 486 487 /* Acquire the lock */ 488 ExAcquireFastMutex(&PnpBusTypeGuidList->Lock); 489 490 /* Loop all entries */ 491 while (i < PnpBusTypeGuidList->GuidCount) 492 { 493 /* Try to find a match */ 494 if (RtlCompareMemory(BusTypeGuid, 495 &PnpBusTypeGuidList->Guids[i], 496 sizeof(GUID)) == sizeof(GUID)) 497 { 498 /* Found it */ 499 FoundIndex = i; 500 goto Quickie; 501 } 502 i++; 503 } 504 505 /* Check if we have to grow the list */ 506 if (PnpBusTypeGuidList->GuidCount) 507 { 508 /* Calculate the new size */ 509 NewSize = sizeof(IO_BUS_TYPE_GUID_LIST) + 510 (sizeof(GUID) * PnpBusTypeGuidList->GuidCount); 511 512 /* Allocate the new copy */ 513 NewList = ExAllocatePool(PagedPool, NewSize); 514 515 if (!NewList) 516 { 517 /* Fail */ 518 ExFreePool(PnpBusTypeGuidList); 519 goto Quickie; 520 } 521 522 /* Now copy them, decrease the size too */ 523 NewSize -= sizeof(GUID); 524 RtlCopyMemory(NewList, PnpBusTypeGuidList, NewSize); 525 526 /* Free the old list */ 527 ExFreePool(PnpBusTypeGuidList); 528 529 /* Use the new buffer */ 530 PnpBusTypeGuidList = NewList; 531 } 532 533 /* Copy the new GUID */ 534 RtlCopyMemory(&PnpBusTypeGuidList->Guids[PnpBusTypeGuidList->GuidCount], 535 BusTypeGuid, 536 sizeof(GUID)); 537 538 /* The new entry is the index */ 539 FoundIndex = (USHORT)PnpBusTypeGuidList->GuidCount; 540 PnpBusTypeGuidList->GuidCount++; 541 542 Quickie: 543 ExReleaseFastMutex(&PnpBusTypeGuidList->Lock); 544 return FoundIndex; 545 } 546 547 NTSTATUS 548 NTAPI 549 IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject, 550 IN PIO_STACK_LOCATION IoStackLocation, 551 OUT PVOID *Information) 552 { 553 PIRP Irp; 554 PIO_STACK_LOCATION IrpStack; 555 IO_STATUS_BLOCK IoStatusBlock; 556 KEVENT Event; 557 NTSTATUS Status; 558 PDEVICE_OBJECT TopDeviceObject; 559 PAGED_CODE(); 560 561 /* Call the top of the device stack */ 562 TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject); 563 564 /* Allocate an IRP */ 565 Irp = IoAllocateIrp(TopDeviceObject->StackSize, FALSE); 566 if (!Irp) 567 { 568 ObDereferenceObject(TopDeviceObject); 569 return STATUS_INSUFFICIENT_RESOURCES; 570 } 571 572 /* Initialize to failure */ 573 Irp->IoStatus.Status = IoStatusBlock.Status = STATUS_NOT_SUPPORTED; 574 Irp->IoStatus.Information = IoStatusBlock.Information = 0; 575 576 /* Special case for IRP_MN_FILTER_RESOURCE_REQUIREMENTS */ 577 if ((IoStackLocation->MajorFunction == IRP_MJ_PNP) && 578 (IoStackLocation->MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS)) 579 { 580 /* Copy the resource requirements list into the IOSB */ 581 Irp->IoStatus.Information = 582 IoStatusBlock.Information = (ULONG_PTR)IoStackLocation->Parameters.FilterResourceRequirements.IoResourceRequirementList; 583 } 584 585 /* Initialize the event */ 586 KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 587 588 /* Set them up */ 589 Irp->UserIosb = &IoStatusBlock; 590 Irp->UserEvent = &Event; 591 592 /* Queue the IRP */ 593 Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 594 IoQueueThreadIrp(Irp); 595 596 /* Copy-in the stack */ 597 IrpStack = IoGetNextIrpStackLocation(Irp); 598 *IrpStack = *IoStackLocation; 599 600 /* Call the driver */ 601 Status = IoCallDriver(TopDeviceObject, Irp); 602 /* Otherwise we may get stuck here or have IoStatusBlock not populated */ 603 ASSERT(!KeAreAllApcsDisabled()); 604 if (Status == STATUS_PENDING) 605 { 606 /* Wait for it */ 607 KeWaitForSingleObject(&Event, 608 Executive, 609 KernelMode, 610 FALSE, 611 NULL); 612 Status = IoStatusBlock.Status; 613 } 614 615 /* Remove the reference */ 616 ObDereferenceObject(TopDeviceObject); 617 618 /* Return the information */ 619 *Information = (PVOID)IoStatusBlock.Information; 620 return Status; 621 } 622 623 NTSTATUS 624 NTAPI 625 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject, 626 IN OUT PIO_STATUS_BLOCK IoStatusBlock, 627 IN UCHAR MinorFunction, 628 IN PIO_STACK_LOCATION Stack OPTIONAL) 629 { 630 IO_STACK_LOCATION IoStackLocation; 631 632 /* Fill out the stack information */ 633 RtlZeroMemory(&IoStackLocation, sizeof(IO_STACK_LOCATION)); 634 IoStackLocation.MajorFunction = IRP_MJ_PNP; 635 IoStackLocation.MinorFunction = MinorFunction; 636 if (Stack) 637 { 638 /* Copy the rest */ 639 RtlCopyMemory(&IoStackLocation.Parameters, 640 &Stack->Parameters, 641 sizeof(Stack->Parameters)); 642 } 643 644 /* Do the PnP call */ 645 IoStatusBlock->Status = IopSynchronousCall(DeviceObject, 646 &IoStackLocation, 647 (PVOID)&IoStatusBlock->Information); 648 return IoStatusBlock->Status; 649 } 650 651 /* 652 * IopCreateDeviceKeyPath 653 * 654 * Creates a registry key 655 * 656 * Parameters 657 * RegistryPath 658 * Name of the key to be created. 659 * Handle 660 * Handle to the newly created key 661 * 662 * Remarks 663 * This method can create nested trees, so parent of RegistryPath can 664 * be not existant, and will be created if needed. 665 */ 666 NTSTATUS 667 NTAPI 668 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, 669 IN ULONG CreateOptions, 670 OUT PHANDLE Handle) 671 { 672 UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT); 673 HANDLE hParent = NULL, hKey; 674 OBJECT_ATTRIBUTES ObjectAttributes; 675 UNICODE_STRING KeyName; 676 PCWSTR Current, Last; 677 USHORT Length; 678 NTSTATUS Status; 679 680 /* Assume failure */ 681 *Handle = NULL; 682 683 /* Open root key for device instances */ 684 Status = IopOpenRegistryKeyEx(&hParent, NULL, &EnumU, KEY_CREATE_SUB_KEY); 685 if (!NT_SUCCESS(Status)) 686 { 687 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU, Status); 688 return Status; 689 } 690 691 Current = KeyName.Buffer = RegistryPath->Buffer; 692 Last = &RegistryPath->Buffer[RegistryPath->Length / sizeof(WCHAR)]; 693 694 /* Go up to the end of the string */ 695 while (Current <= Last) 696 { 697 if (Current != Last && *Current != L'\\') 698 { 699 /* Not the end of the string and not a separator */ 700 Current++; 701 continue; 702 } 703 704 /* Prepare relative key name */ 705 Length = (USHORT)((ULONG_PTR)Current - (ULONG_PTR)KeyName.Buffer); 706 KeyName.MaximumLength = KeyName.Length = Length; 707 DPRINT("Create '%wZ'\n", &KeyName); 708 709 /* Open key */ 710 InitializeObjectAttributes(&ObjectAttributes, 711 &KeyName, 712 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 713 hParent, 714 NULL); 715 Status = ZwCreateKey(&hKey, 716 Current == Last ? KEY_ALL_ACCESS : KEY_CREATE_SUB_KEY, 717 &ObjectAttributes, 718 0, 719 NULL, 720 CreateOptions, 721 NULL); 722 723 /* Close parent key handle, we don't need it anymore */ 724 if (hParent) 725 ZwClose(hParent); 726 727 /* Key opening/creating failed? */ 728 if (!NT_SUCCESS(Status)) 729 { 730 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName, Status); 731 return Status; 732 } 733 734 /* Check if it is the end of the string */ 735 if (Current == Last) 736 { 737 /* Yes, return success */ 738 *Handle = hKey; 739 return STATUS_SUCCESS; 740 } 741 742 /* Start with this new parent key */ 743 hParent = hKey; 744 Current++; 745 KeyName.Buffer = (PWSTR)Current; 746 } 747 748 return STATUS_UNSUCCESSFUL; 749 } 750 751 NTSTATUS 752 IopSetDeviceInstanceData(HANDLE InstanceKey, 753 PDEVICE_NODE DeviceNode) 754 { 755 OBJECT_ATTRIBUTES ObjectAttributes; 756 UNICODE_STRING KeyName; 757 HANDLE LogConfKey, ControlKey, DeviceParamsKey; 758 ULONG ResCount; 759 ULONG ResultLength; 760 NTSTATUS Status; 761 762 DPRINT("IopSetDeviceInstanceData() called\n"); 763 764 /* Create the 'LogConf' key */ 765 RtlInitUnicodeString(&KeyName, L"LogConf"); 766 InitializeObjectAttributes(&ObjectAttributes, 767 &KeyName, 768 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 769 InstanceKey, 770 NULL); 771 Status = ZwCreateKey(&LogConfKey, 772 KEY_ALL_ACCESS, 773 &ObjectAttributes, 774 0, 775 NULL, 776 // FIXME? In r53694 it was silently turned from non-volatile into this, 777 // without any extra warning. Is this still needed?? 778 REG_OPTION_VOLATILE, 779 NULL); 780 if (NT_SUCCESS(Status)) 781 { 782 /* Set 'BootConfig' value */ 783 if (DeviceNode->BootResources != NULL) 784 { 785 ResCount = DeviceNode->BootResources->Count; 786 if (ResCount != 0) 787 { 788 RtlInitUnicodeString(&KeyName, L"BootConfig"); 789 Status = ZwSetValueKey(LogConfKey, 790 &KeyName, 791 0, 792 REG_RESOURCE_LIST, 793 DeviceNode->BootResources, 794 PnpDetermineResourceListSize(DeviceNode->BootResources)); 795 } 796 } 797 798 /* Set 'BasicConfigVector' value */ 799 if (DeviceNode->ResourceRequirements != NULL && 800 DeviceNode->ResourceRequirements->ListSize != 0) 801 { 802 RtlInitUnicodeString(&KeyName, L"BasicConfigVector"); 803 Status = ZwSetValueKey(LogConfKey, 804 &KeyName, 805 0, 806 REG_RESOURCE_REQUIREMENTS_LIST, 807 DeviceNode->ResourceRequirements, 808 DeviceNode->ResourceRequirements->ListSize); 809 } 810 811 ZwClose(LogConfKey); 812 } 813 814 /* Set the 'ConfigFlags' value */ 815 RtlInitUnicodeString(&KeyName, L"ConfigFlags"); 816 Status = ZwQueryValueKey(InstanceKey, 817 &KeyName, 818 KeyValueBasicInformation, 819 NULL, 820 0, 821 &ResultLength); 822 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 823 { 824 /* Write the default value */ 825 ULONG DefaultConfigFlags = 0; 826 Status = ZwSetValueKey(InstanceKey, 827 &KeyName, 828 0, 829 REG_DWORD, 830 &DefaultConfigFlags, 831 sizeof(DefaultConfigFlags)); 832 } 833 834 /* Create the 'Control' key */ 835 RtlInitUnicodeString(&KeyName, L"Control"); 836 InitializeObjectAttributes(&ObjectAttributes, 837 &KeyName, 838 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 839 InstanceKey, 840 NULL); 841 Status = ZwCreateKey(&ControlKey, 842 0, 843 &ObjectAttributes, 844 0, 845 NULL, 846 REG_OPTION_VOLATILE, 847 NULL); 848 if (NT_SUCCESS(Status)) 849 ZwClose(ControlKey); 850 851 /* Create the 'Device Parameters' key and set the 'FirmwareIdentified' value for all ACPI-enumerated devices */ 852 if (_wcsnicmp(DeviceNode->InstancePath.Buffer, L"ACPI\\", 5) == 0) 853 { 854 RtlInitUnicodeString(&KeyName, L"Device Parameters"); 855 InitializeObjectAttributes(&ObjectAttributes, 856 &KeyName, 857 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 858 InstanceKey, 859 NULL); 860 Status = ZwCreateKey(&DeviceParamsKey, 861 0, 862 &ObjectAttributes, 863 0, 864 NULL, 865 REG_OPTION_NON_VOLATILE, 866 NULL); 867 if (NT_SUCCESS(Status)) 868 { 869 ULONG FirmwareIdentified = 1; 870 RtlInitUnicodeString(&KeyName, L"FirmwareIdentified"); 871 Status = ZwSetValueKey(DeviceParamsKey, 872 &KeyName, 873 0, 874 REG_DWORD, 875 &FirmwareIdentified, 876 sizeof(FirmwareIdentified)); 877 878 ZwClose(DeviceParamsKey); 879 } 880 } 881 882 DPRINT("IopSetDeviceInstanceData() done\n"); 883 884 return Status; 885 } 886 887 /* 888 * IopGetParentIdPrefix 889 * 890 * Retrieve (or create) a string which identifies a device. 891 * 892 * Parameters 893 * DeviceNode 894 * Pointer to device node. 895 * ParentIdPrefix 896 * Pointer to the string where is returned the parent node identifier 897 * 898 * Remarks 899 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is 900 * valid and its Buffer field is NULL-terminated. The caller needs to 901 * to free the string with RtlFreeUnicodeString when it is no longer 902 * needed. 903 */ 904 905 NTSTATUS 906 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode, 907 PUNICODE_STRING ParentIdPrefix) 908 { 909 const UNICODE_STRING EnumKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); 910 ULONG KeyNameBufferLength; 911 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation = NULL; 912 UNICODE_STRING KeyName = {0, 0, NULL}; 913 UNICODE_STRING KeyValue; 914 UNICODE_STRING ValueName; 915 HANDLE hKey = NULL; 916 ULONG crc32; 917 NTSTATUS Status; 918 919 /* HACK: As long as some devices have a NULL device 920 * instance path, the following test is required :( 921 */ 922 if (DeviceNode->Parent->InstancePath.Length == 0) 923 { 924 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n", 925 &DeviceNode->InstancePath); 926 return STATUS_UNSUCCESSFUL; 927 } 928 929 /* 1. Try to retrieve ParentIdPrefix from registry */ 930 KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(L"12345678&12345678"); 931 ParentIdPrefixInformation = ExAllocatePoolWithTag(PagedPool, 932 KeyNameBufferLength + sizeof(UNICODE_NULL), 933 TAG_IO); 934 if (!ParentIdPrefixInformation) 935 { 936 return STATUS_INSUFFICIENT_RESOURCES; 937 } 938 939 KeyName.Length = 0; 940 KeyName.MaximumLength = EnumKeyPath.Length + 941 DeviceNode->Parent->InstancePath.Length + 942 sizeof(UNICODE_NULL); 943 KeyName.Buffer = ExAllocatePoolWithTag(PagedPool, 944 KeyName.MaximumLength, 945 TAG_IO); 946 if (!KeyName.Buffer) 947 { 948 Status = STATUS_INSUFFICIENT_RESOURCES; 949 goto cleanup; 950 } 951 952 RtlCopyUnicodeString(&KeyName, &EnumKeyPath); 953 RtlAppendUnicodeStringToString(&KeyName, &DeviceNode->Parent->InstancePath); 954 955 Status = IopOpenRegistryKeyEx(&hKey, NULL, &KeyName, KEY_QUERY_VALUE | KEY_SET_VALUE); 956 if (!NT_SUCCESS(Status)) 957 { 958 goto cleanup; 959 } 960 RtlInitUnicodeString(&ValueName, L"ParentIdPrefix"); 961 Status = ZwQueryValueKey(hKey, 962 &ValueName, 963 KeyValuePartialInformation, 964 ParentIdPrefixInformation, 965 KeyNameBufferLength, 966 &KeyNameBufferLength); 967 if (NT_SUCCESS(Status)) 968 { 969 if (ParentIdPrefixInformation->Type != REG_SZ) 970 { 971 Status = STATUS_UNSUCCESSFUL; 972 } 973 else 974 { 975 KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength; 976 KeyValue.Length = KeyValue.MaximumLength - sizeof(UNICODE_NULL); 977 KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data; 978 ASSERT(KeyValue.Buffer[KeyValue.Length / sizeof(WCHAR)] == UNICODE_NULL); 979 } 980 goto cleanup; 981 } 982 if (Status != STATUS_OBJECT_NAME_NOT_FOUND) 983 { 984 /* FIXME how do we get here and why is ParentIdPrefixInformation valid? */ 985 KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength; 986 KeyValue.Length = KeyValue.MaximumLength - sizeof(UNICODE_NULL); 987 KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data; 988 ASSERT(KeyValue.Buffer[KeyValue.Length / sizeof(WCHAR)] == UNICODE_NULL); 989 goto cleanup; 990 } 991 992 /* 2. Create the ParentIdPrefix value */ 993 crc32 = RtlComputeCrc32(0, 994 (PUCHAR)DeviceNode->Parent->InstancePath.Buffer, 995 DeviceNode->Parent->InstancePath.Length); 996 997 RtlStringCbPrintfW((PWSTR)ParentIdPrefixInformation, 998 KeyNameBufferLength, 999 L"%lx&%lx", 1000 DeviceNode->Parent->Level, 1001 crc32); 1002 RtlInitUnicodeString(&KeyValue, (PWSTR)ParentIdPrefixInformation); 1003 1004 /* 3. Try to write the ParentIdPrefix to registry */ 1005 Status = ZwSetValueKey(hKey, 1006 &ValueName, 1007 0, 1008 REG_SZ, 1009 KeyValue.Buffer, 1010 ((ULONG)wcslen(KeyValue.Buffer) + 1) * sizeof(WCHAR)); 1011 1012 cleanup: 1013 if (NT_SUCCESS(Status)) 1014 { 1015 /* Duplicate the string to return it */ 1016 Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, 1017 &KeyValue, 1018 ParentIdPrefix); 1019 } 1020 ExFreePoolWithTag(ParentIdPrefixInformation, TAG_IO); 1021 RtlFreeUnicodeString(&KeyName); 1022 if (hKey != NULL) 1023 { 1024 ZwClose(hKey); 1025 } 1026 return Status; 1027 } 1028 1029 static 1030 CODE_SEG("INIT") 1031 NTSTATUS 1032 IopEnumerateDetectedDevices( 1033 IN HANDLE hBaseKey, 1034 IN PUNICODE_STRING RelativePath OPTIONAL, 1035 IN HANDLE hRootKey, 1036 IN BOOLEAN EnumerateSubKeys, 1037 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources, 1038 IN ULONG ParentBootResourcesLength) 1039 { 1040 UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier"); 1041 UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID"); 1042 UNICODE_STRING ConfigurationDataU = RTL_CONSTANT_STRING(L"Configuration Data"); 1043 UNICODE_STRING BootConfigU = RTL_CONSTANT_STRING(L"BootConfig"); 1044 UNICODE_STRING LogConfU = RTL_CONSTANT_STRING(L"LogConf"); 1045 OBJECT_ATTRIBUTES ObjectAttributes; 1046 HANDLE hDevicesKey = NULL; 1047 HANDLE hDeviceKey = NULL; 1048 HANDLE hLevel1Key, hLevel2Key = NULL, hLogConf; 1049 UNICODE_STRING Level2NameU; 1050 WCHAR Level2Name[5]; 1051 ULONG IndexDevice = 0; 1052 ULONG IndexSubKey; 1053 PKEY_BASIC_INFORMATION pDeviceInformation = NULL; 1054 ULONG DeviceInfoLength = sizeof(KEY_BASIC_INFORMATION) + 50 * sizeof(WCHAR); 1055 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation = NULL; 1056 ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR); 1057 UNICODE_STRING DeviceName, ValueName; 1058 ULONG RequiredSize; 1059 PCM_FULL_RESOURCE_DESCRIPTOR BootResources = NULL; 1060 ULONG BootResourcesLength; 1061 NTSTATUS Status; 1062 1063 const UNICODE_STRING IdentifierSerial = RTL_CONSTANT_STRING(L"SerialController"); 1064 UNICODE_STRING HardwareIdSerial = RTL_CONSTANT_STRING(L"*PNP0501\0"); 1065 static ULONG DeviceIndexSerial = 0; 1066 const UNICODE_STRING IdentifierKeyboard = RTL_CONSTANT_STRING(L"KeyboardController"); 1067 UNICODE_STRING HardwareIdKeyboard = RTL_CONSTANT_STRING(L"*PNP0303\0"); 1068 static ULONG DeviceIndexKeyboard = 0; 1069 const UNICODE_STRING IdentifierMouse = RTL_CONSTANT_STRING(L"PointerController"); 1070 /* FIXME: IopEnumerateDetectedDevices() should be rewritten. 1071 * The PnP identifiers can either be hardcoded or parsed from a LegacyXlate 1072 * sections of driver INF files. 1073 */ 1074 #if defined(SARCH_PC98) 1075 UNICODE_STRING HardwareIdMouse = RTL_CONSTANT_STRING(L"*nEC1F00\0"); 1076 #else 1077 UNICODE_STRING HardwareIdMouse = RTL_CONSTANT_STRING(L"*PNP0F13\0"); 1078 #endif 1079 static ULONG DeviceIndexMouse = 0; 1080 const UNICODE_STRING IdentifierParallel = RTL_CONSTANT_STRING(L"ParallelController"); 1081 UNICODE_STRING HardwareIdParallel = RTL_CONSTANT_STRING(L"*PNP0400\0"); 1082 static ULONG DeviceIndexParallel = 0; 1083 const UNICODE_STRING IdentifierFloppy = RTL_CONSTANT_STRING(L"FloppyDiskPeripheral"); 1084 UNICODE_STRING HardwareIdFloppy = RTL_CONSTANT_STRING(L"*PNP0700\0"); 1085 static ULONG DeviceIndexFloppy = 0; 1086 UNICODE_STRING HardwareIdKey; 1087 PUNICODE_STRING pHardwareId; 1088 ULONG DeviceIndex = 0; 1089 PUCHAR CmResourceList; 1090 ULONG ListCount; 1091 1092 if (RelativePath) 1093 { 1094 Status = IopOpenRegistryKeyEx(&hDevicesKey, hBaseKey, RelativePath, KEY_ENUMERATE_SUB_KEYS); 1095 if (!NT_SUCCESS(Status)) 1096 { 1097 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); 1098 goto cleanup; 1099 } 1100 } 1101 else 1102 hDevicesKey = hBaseKey; 1103 1104 pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength); 1105 if (!pDeviceInformation) 1106 { 1107 DPRINT("ExAllocatePool() failed\n"); 1108 Status = STATUS_NO_MEMORY; 1109 goto cleanup; 1110 } 1111 1112 pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); 1113 if (!pValueInformation) 1114 { 1115 DPRINT("ExAllocatePool() failed\n"); 1116 Status = STATUS_NO_MEMORY; 1117 goto cleanup; 1118 } 1119 1120 while (TRUE) 1121 { 1122 Status = ZwEnumerateKey(hDevicesKey, IndexDevice, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize); 1123 if (Status == STATUS_NO_MORE_ENTRIES) 1124 break; 1125 else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 1126 { 1127 ExFreePool(pDeviceInformation); 1128 DeviceInfoLength = RequiredSize; 1129 pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength); 1130 if (!pDeviceInformation) 1131 { 1132 DPRINT("ExAllocatePool() failed\n"); 1133 Status = STATUS_NO_MEMORY; 1134 goto cleanup; 1135 } 1136 Status = ZwEnumerateKey(hDevicesKey, IndexDevice, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize); 1137 } 1138 if (!NT_SUCCESS(Status)) 1139 { 1140 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); 1141 goto cleanup; 1142 } 1143 IndexDevice++; 1144 1145 /* Open device key */ 1146 DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength; 1147 DeviceName.Buffer = pDeviceInformation->Name; 1148 1149 Status = IopOpenRegistryKeyEx(&hDeviceKey, hDevicesKey, &DeviceName, 1150 KEY_QUERY_VALUE + (EnumerateSubKeys ? KEY_ENUMERATE_SUB_KEYS : 0)); 1151 if (!NT_SUCCESS(Status)) 1152 { 1153 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); 1154 goto cleanup; 1155 } 1156 1157 /* Read boot resources, and add then to parent ones */ 1158 Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); 1159 if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 1160 { 1161 ExFreePool(pValueInformation); 1162 ValueInfoLength = RequiredSize; 1163 pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); 1164 if (!pValueInformation) 1165 { 1166 DPRINT("ExAllocatePool() failed\n"); 1167 ZwDeleteKey(hLevel2Key); 1168 Status = STATUS_NO_MEMORY; 1169 goto cleanup; 1170 } 1171 Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); 1172 } 1173 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 1174 { 1175 BootResources = ParentBootResources; 1176 BootResourcesLength = ParentBootResourcesLength; 1177 } 1178 else if (!NT_SUCCESS(Status)) 1179 { 1180 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); 1181 goto nextdevice; 1182 } 1183 else if (pValueInformation->Type != REG_FULL_RESOURCE_DESCRIPTOR) 1184 { 1185 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_FULL_RESOURCE_DESCRIPTOR); 1186 goto nextdevice; 1187 } 1188 else 1189 { 1190 static const ULONG Header = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors); 1191 1192 /* Concatenate current resources and parent ones */ 1193 if (ParentBootResourcesLength == 0) 1194 BootResourcesLength = pValueInformation->DataLength; 1195 else 1196 BootResourcesLength = ParentBootResourcesLength 1197 + pValueInformation->DataLength 1198 - Header; 1199 BootResources = ExAllocatePool(PagedPool, BootResourcesLength); 1200 if (!BootResources) 1201 { 1202 DPRINT("ExAllocatePool() failed\n"); 1203 goto nextdevice; 1204 } 1205 if (ParentBootResourcesLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) 1206 { 1207 RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength); 1208 } 1209 else if (ParentBootResources->PartialResourceList.PartialDescriptors[ParentBootResources->PartialResourceList.Count - 1].Type == CmResourceTypeDeviceSpecific) 1210 { 1211 RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength); 1212 RtlCopyMemory( 1213 (PVOID)((ULONG_PTR)BootResources + pValueInformation->DataLength), 1214 (PVOID)((ULONG_PTR)ParentBootResources + Header), 1215 ParentBootResourcesLength - Header); 1216 BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count; 1217 } 1218 else 1219 { 1220 RtlCopyMemory(BootResources, pValueInformation->Data, Header); 1221 RtlCopyMemory( 1222 (PVOID)((ULONG_PTR)BootResources + Header), 1223 (PVOID)((ULONG_PTR)ParentBootResources + Header), 1224 ParentBootResourcesLength - Header); 1225 RtlCopyMemory( 1226 (PVOID)((ULONG_PTR)BootResources + ParentBootResourcesLength), 1227 pValueInformation->Data + Header, 1228 pValueInformation->DataLength - Header); 1229 BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count; 1230 } 1231 } 1232 1233 if (EnumerateSubKeys) 1234 { 1235 IndexSubKey = 0; 1236 while (TRUE) 1237 { 1238 Status = ZwEnumerateKey(hDeviceKey, IndexSubKey, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize); 1239 if (Status == STATUS_NO_MORE_ENTRIES) 1240 break; 1241 else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 1242 { 1243 ExFreePool(pDeviceInformation); 1244 DeviceInfoLength = RequiredSize; 1245 pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength); 1246 if (!pDeviceInformation) 1247 { 1248 DPRINT("ExAllocatePool() failed\n"); 1249 Status = STATUS_NO_MEMORY; 1250 goto cleanup; 1251 } 1252 Status = ZwEnumerateKey(hDeviceKey, IndexSubKey, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize); 1253 } 1254 if (!NT_SUCCESS(Status)) 1255 { 1256 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); 1257 goto cleanup; 1258 } 1259 IndexSubKey++; 1260 DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength; 1261 DeviceName.Buffer = pDeviceInformation->Name; 1262 1263 Status = IopEnumerateDetectedDevices( 1264 hDeviceKey, 1265 &DeviceName, 1266 hRootKey, 1267 TRUE, 1268 BootResources, 1269 BootResourcesLength); 1270 if (!NT_SUCCESS(Status)) 1271 goto cleanup; 1272 } 1273 } 1274 1275 /* Read identifier */ 1276 Status = ZwQueryValueKey(hDeviceKey, &IdentifierU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); 1277 if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 1278 { 1279 ExFreePool(pValueInformation); 1280 ValueInfoLength = RequiredSize; 1281 pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); 1282 if (!pValueInformation) 1283 { 1284 DPRINT("ExAllocatePool() failed\n"); 1285 Status = STATUS_NO_MEMORY; 1286 goto cleanup; 1287 } 1288 Status = ZwQueryValueKey(hDeviceKey, &IdentifierU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); 1289 } 1290 if (!NT_SUCCESS(Status)) 1291 { 1292 if (Status != STATUS_OBJECT_NAME_NOT_FOUND) 1293 { 1294 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); 1295 goto nextdevice; 1296 } 1297 ValueName.Length = ValueName.MaximumLength = 0; 1298 } 1299 else if (pValueInformation->Type != REG_SZ) 1300 { 1301 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_SZ); 1302 goto nextdevice; 1303 } 1304 else 1305 { 1306 /* Assign hardware id to this device */ 1307 ValueName.Length = ValueName.MaximumLength = (USHORT)pValueInformation->DataLength; 1308 ValueName.Buffer = (PWCHAR)pValueInformation->Data; 1309 if (ValueName.Length >= sizeof(WCHAR) && ValueName.Buffer[ValueName.Length / sizeof(WCHAR) - 1] == UNICODE_NULL) 1310 ValueName.Length -= sizeof(WCHAR); 1311 } 1312 1313 if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierSerial, FALSE) == 0) 1314 { 1315 pHardwareId = &HardwareIdSerial; 1316 DeviceIndex = DeviceIndexSerial++; 1317 } 1318 else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierKeyboard, FALSE) == 0) 1319 { 1320 pHardwareId = &HardwareIdKeyboard; 1321 DeviceIndex = DeviceIndexKeyboard++; 1322 } 1323 else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierMouse, FALSE) == 0) 1324 { 1325 pHardwareId = &HardwareIdMouse; 1326 DeviceIndex = DeviceIndexMouse++; 1327 } 1328 else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierParallel, FALSE) == 0) 1329 { 1330 pHardwareId = &HardwareIdParallel; 1331 DeviceIndex = DeviceIndexParallel++; 1332 } 1333 else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierFloppy, FALSE) == 0) 1334 { 1335 pHardwareId = &HardwareIdFloppy; 1336 DeviceIndex = DeviceIndexFloppy++; 1337 } 1338 else 1339 { 1340 /* Unknown key path */ 1341 DPRINT("Unknown key path '%wZ'\n", RelativePath); 1342 goto nextdevice; 1343 } 1344 1345 /* Prepare hardware id key (hardware id value without final \0) */ 1346 HardwareIdKey = *pHardwareId; 1347 HardwareIdKey.Length -= sizeof(UNICODE_NULL); 1348 1349 /* Add the detected device to Root key */ 1350 InitializeObjectAttributes(&ObjectAttributes, &HardwareIdKey, OBJ_KERNEL_HANDLE, hRootKey, NULL); 1351 Status = ZwCreateKey( 1352 &hLevel1Key, 1353 KEY_CREATE_SUB_KEY, 1354 &ObjectAttributes, 1355 0, 1356 NULL, 1357 REG_OPTION_NON_VOLATILE, 1358 NULL); 1359 if (!NT_SUCCESS(Status)) 1360 { 1361 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); 1362 goto nextdevice; 1363 } 1364 swprintf(Level2Name, L"%04lu", DeviceIndex); 1365 RtlInitUnicodeString(&Level2NameU, Level2Name); 1366 InitializeObjectAttributes(&ObjectAttributes, &Level2NameU, OBJ_KERNEL_HANDLE, hLevel1Key, NULL); 1367 Status = ZwCreateKey( 1368 &hLevel2Key, 1369 KEY_SET_VALUE | KEY_CREATE_SUB_KEY, 1370 &ObjectAttributes, 1371 0, 1372 NULL, 1373 REG_OPTION_NON_VOLATILE, 1374 NULL); 1375 ZwClose(hLevel1Key); 1376 if (!NT_SUCCESS(Status)) 1377 { 1378 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); 1379 goto nextdevice; 1380 } 1381 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName, DeviceIndex, &HardwareIdKey); 1382 Status = ZwSetValueKey(hLevel2Key, &HardwareIDU, 0, REG_MULTI_SZ, pHardwareId->Buffer, pHardwareId->MaximumLength); 1383 if (!NT_SUCCESS(Status)) 1384 { 1385 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); 1386 ZwDeleteKey(hLevel2Key); 1387 goto nextdevice; 1388 } 1389 /* Create 'LogConf' subkey */ 1390 InitializeObjectAttributes(&ObjectAttributes, &LogConfU, OBJ_KERNEL_HANDLE, hLevel2Key, NULL); 1391 Status = ZwCreateKey( 1392 &hLogConf, 1393 KEY_SET_VALUE, 1394 &ObjectAttributes, 1395 0, 1396 NULL, 1397 REG_OPTION_VOLATILE, 1398 NULL); 1399 if (!NT_SUCCESS(Status)) 1400 { 1401 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); 1402 ZwDeleteKey(hLevel2Key); 1403 goto nextdevice; 1404 } 1405 if (BootResourcesLength >= sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) 1406 { 1407 CmResourceList = ExAllocatePool(PagedPool, BootResourcesLength + sizeof(ULONG)); 1408 if (!CmResourceList) 1409 { 1410 ZwClose(hLogConf); 1411 ZwDeleteKey(hLevel2Key); 1412 goto nextdevice; 1413 } 1414 1415 /* Add the list count (1st member of CM_RESOURCE_LIST) */ 1416 ListCount = 1; 1417 RtlCopyMemory(CmResourceList, 1418 &ListCount, 1419 sizeof(ULONG)); 1420 1421 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */ 1422 RtlCopyMemory(CmResourceList + sizeof(ULONG), 1423 BootResources, 1424 BootResourcesLength); 1425 1426 /* Save boot resources to 'LogConf\BootConfig' */ 1427 Status = ZwSetValueKey(hLogConf, &BootConfigU, 0, REG_RESOURCE_LIST, CmResourceList, BootResourcesLength + sizeof(ULONG)); 1428 if (!NT_SUCCESS(Status)) 1429 { 1430 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); 1431 ZwClose(hLogConf); 1432 ZwDeleteKey(hLevel2Key); 1433 goto nextdevice; 1434 } 1435 } 1436 ZwClose(hLogConf); 1437 1438 nextdevice: 1439 if (BootResources && BootResources != ParentBootResources) 1440 { 1441 ExFreePool(BootResources); 1442 BootResources = NULL; 1443 } 1444 if (hLevel2Key) 1445 { 1446 ZwClose(hLevel2Key); 1447 hLevel2Key = NULL; 1448 } 1449 if (hDeviceKey) 1450 { 1451 ZwClose(hDeviceKey); 1452 hDeviceKey = NULL; 1453 } 1454 } 1455 1456 Status = STATUS_SUCCESS; 1457 1458 cleanup: 1459 if (hDevicesKey && hDevicesKey != hBaseKey) 1460 ZwClose(hDevicesKey); 1461 if (hDeviceKey) 1462 ZwClose(hDeviceKey); 1463 if (pDeviceInformation) 1464 ExFreePool(pDeviceInformation); 1465 if (pValueInformation) 1466 ExFreePool(pValueInformation); 1467 return Status; 1468 } 1469 1470 static 1471 CODE_SEG("INIT") 1472 BOOLEAN 1473 IopIsFirmwareMapperDisabled(VOID) 1474 { 1475 UNICODE_STRING KeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CURRENTCONTROLSET\\Control\\Pnp"); 1476 UNICODE_STRING KeyNameU = RTL_CONSTANT_STRING(L"DisableFirmwareMapper"); 1477 OBJECT_ATTRIBUTES ObjectAttributes; 1478 HANDLE hPnpKey; 1479 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation; 1480 ULONG DesiredLength, Length; 1481 ULONG KeyValue = 0; 1482 NTSTATUS Status; 1483 1484 InitializeObjectAttributes(&ObjectAttributes, &KeyPathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); 1485 Status = ZwOpenKey(&hPnpKey, KEY_QUERY_VALUE, &ObjectAttributes); 1486 if (NT_SUCCESS(Status)) 1487 { 1488 Status = ZwQueryValueKey(hPnpKey, 1489 &KeyNameU, 1490 KeyValuePartialInformation, 1491 NULL, 1492 0, 1493 &DesiredLength); 1494 if ((Status == STATUS_BUFFER_TOO_SMALL) || 1495 (Status == STATUS_BUFFER_OVERFLOW)) 1496 { 1497 Length = DesiredLength; 1498 KeyInformation = ExAllocatePool(PagedPool, Length); 1499 if (KeyInformation) 1500 { 1501 Status = ZwQueryValueKey(hPnpKey, 1502 &KeyNameU, 1503 KeyValuePartialInformation, 1504 KeyInformation, 1505 Length, 1506 &DesiredLength); 1507 if (NT_SUCCESS(Status) && KeyInformation->DataLength == sizeof(ULONG)) 1508 { 1509 KeyValue = (ULONG)(*KeyInformation->Data); 1510 } 1511 else 1512 { 1513 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed\n", &KeyPathU, &KeyNameU); 1514 } 1515 1516 ExFreePool(KeyInformation); 1517 } 1518 else 1519 { 1520 DPRINT1("Failed to allocate memory for registry query\n"); 1521 } 1522 } 1523 else 1524 { 1525 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed with status 0x%08lx\n", &KeyPathU, &KeyNameU, Status); 1526 } 1527 1528 ZwClose(hPnpKey); 1529 } 1530 else 1531 { 1532 DPRINT1("ZwOpenKey(%wZ) failed with status 0x%08lx\n", &KeyPathU, Status); 1533 } 1534 1535 DPRINT("Firmware mapper is %s\n", KeyValue != 0 ? "disabled" : "enabled"); 1536 1537 return (KeyValue != 0) ? TRUE : FALSE; 1538 } 1539 1540 CODE_SEG("INIT") 1541 NTSTATUS 1542 NTAPI 1543 IopUpdateRootKey(VOID) 1544 { 1545 UNICODE_STRING EnumU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum"); 1546 UNICODE_STRING RootPathU = RTL_CONSTANT_STRING(L"Root"); 1547 UNICODE_STRING MultiKeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"); 1548 OBJECT_ATTRIBUTES ObjectAttributes; 1549 HANDLE hEnum, hRoot; 1550 NTSTATUS Status; 1551 1552 InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); 1553 Status = ZwCreateKey(&hEnum, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL); 1554 if (!NT_SUCCESS(Status)) 1555 { 1556 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status); 1557 return Status; 1558 } 1559 1560 InitializeObjectAttributes(&ObjectAttributes, &RootPathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hEnum, NULL); 1561 Status = ZwCreateKey(&hRoot, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL); 1562 ZwClose(hEnum); 1563 if (!NT_SUCCESS(Status)) 1564 { 1565 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status); 1566 return Status; 1567 } 1568 1569 if (!IopIsFirmwareMapperDisabled()) 1570 { 1571 Status = IopOpenRegistryKeyEx(&hEnum, NULL, &MultiKeyPathU, KEY_ENUMERATE_SUB_KEYS); 1572 if (!NT_SUCCESS(Status)) 1573 { 1574 /* Nothing to do, don't return with an error status */ 1575 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); 1576 ZwClose(hRoot); 1577 return STATUS_SUCCESS; 1578 } 1579 Status = IopEnumerateDetectedDevices( 1580 hEnum, 1581 NULL, 1582 hRoot, 1583 TRUE, 1584 NULL, 1585 0); 1586 ZwClose(hEnum); 1587 } 1588 else 1589 { 1590 /* Enumeration is disabled */ 1591 Status = STATUS_SUCCESS; 1592 } 1593 1594 ZwClose(hRoot); 1595 1596 return Status; 1597 } 1598 1599 NTSTATUS 1600 NTAPI 1601 IopOpenRegistryKeyEx(PHANDLE KeyHandle, 1602 HANDLE ParentKey, 1603 PUNICODE_STRING Name, 1604 ACCESS_MASK DesiredAccess) 1605 { 1606 OBJECT_ATTRIBUTES ObjectAttributes; 1607 NTSTATUS Status; 1608 1609 PAGED_CODE(); 1610 1611 *KeyHandle = NULL; 1612 1613 InitializeObjectAttributes(&ObjectAttributes, 1614 Name, 1615 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 1616 ParentKey, 1617 NULL); 1618 1619 Status = ZwOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes); 1620 1621 return Status; 1622 } 1623 1624 NTSTATUS 1625 NTAPI 1626 IopCreateRegistryKeyEx(OUT PHANDLE Handle, 1627 IN HANDLE RootHandle OPTIONAL, 1628 IN PUNICODE_STRING KeyName, 1629 IN ACCESS_MASK DesiredAccess, 1630 IN ULONG CreateOptions, 1631 OUT PULONG Disposition OPTIONAL) 1632 { 1633 OBJECT_ATTRIBUTES ObjectAttributes; 1634 ULONG KeyDisposition, RootHandleIndex = 0, i = 1, NestedCloseLevel = 0; 1635 USHORT Length; 1636 HANDLE HandleArray[2]; 1637 BOOLEAN Recursing = TRUE; 1638 PWCHAR pp, p, p1; 1639 UNICODE_STRING KeyString; 1640 NTSTATUS Status = STATUS_SUCCESS; 1641 PAGED_CODE(); 1642 1643 /* P1 is start, pp is end */ 1644 p1 = KeyName->Buffer; 1645 pp = (PVOID)((ULONG_PTR)p1 + KeyName->Length); 1646 1647 /* Create the target key */ 1648 InitializeObjectAttributes(&ObjectAttributes, 1649 KeyName, 1650 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 1651 RootHandle, 1652 NULL); 1653 Status = ZwCreateKey(&HandleArray[i], 1654 DesiredAccess, 1655 &ObjectAttributes, 1656 0, 1657 NULL, 1658 CreateOptions, 1659 &KeyDisposition); 1660 1661 /* Now we check if this failed */ 1662 if ((Status == STATUS_OBJECT_NAME_NOT_FOUND) && (RootHandle)) 1663 { 1664 /* Target key failed, so we'll need to create its parent. Setup array */ 1665 HandleArray[0] = NULL; 1666 HandleArray[1] = RootHandle; 1667 1668 /* Keep recursing for each missing parent */ 1669 while (Recursing) 1670 { 1671 /* And if we're deep enough, close the last handle */ 1672 if (NestedCloseLevel > 1) ZwClose(HandleArray[RootHandleIndex]); 1673 1674 /* We're setup to ping-pong between the two handle array entries */ 1675 RootHandleIndex = i; 1676 i = (i + 1) & 1; 1677 1678 /* Clear the one we're attempting to open now */ 1679 HandleArray[i] = NULL; 1680 1681 /* Process the parent key name */ 1682 for (p = p1; ((p < pp) && (*p != OBJ_NAME_PATH_SEPARATOR)); p++); 1683 Length = (USHORT)(p - p1) * sizeof(WCHAR); 1684 1685 /* Is there a parent name? */ 1686 if (Length) 1687 { 1688 /* Build the unicode string for it */ 1689 KeyString.Buffer = p1; 1690 KeyString.Length = KeyString.MaximumLength = Length; 1691 1692 /* Now try opening the parent */ 1693 InitializeObjectAttributes(&ObjectAttributes, 1694 &KeyString, 1695 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 1696 HandleArray[RootHandleIndex], 1697 NULL); 1698 Status = ZwCreateKey(&HandleArray[i], 1699 DesiredAccess, 1700 &ObjectAttributes, 1701 0, 1702 NULL, 1703 CreateOptions, 1704 &KeyDisposition); 1705 if (NT_SUCCESS(Status)) 1706 { 1707 /* It worked, we have one more handle */ 1708 NestedCloseLevel++; 1709 } 1710 else 1711 { 1712 /* Parent key creation failed, abandon loop */ 1713 Recursing = FALSE; 1714 continue; 1715 } 1716 } 1717 else 1718 { 1719 /* We don't have a parent name, probably corrupted key name */ 1720 Status = STATUS_INVALID_PARAMETER; 1721 Recursing = FALSE; 1722 continue; 1723 } 1724 1725 /* Now see if there's more parents to create */ 1726 p1 = p + 1; 1727 if ((p == pp) || (p1 == pp)) 1728 { 1729 /* We're done, hopefully successfully, so stop */ 1730 Recursing = FALSE; 1731 } 1732 } 1733 1734 /* Outer loop check for handle nesting that requires closing the top handle */ 1735 if (NestedCloseLevel > 1) ZwClose(HandleArray[RootHandleIndex]); 1736 } 1737 1738 /* Check if we broke out of the loop due to success */ 1739 if (NT_SUCCESS(Status)) 1740 { 1741 /* Return the target handle (we closed all the parent ones) and disposition */ 1742 *Handle = HandleArray[i]; 1743 if (Disposition) *Disposition = KeyDisposition; 1744 } 1745 1746 /* Return the success state */ 1747 return Status; 1748 } 1749 1750 NTSTATUS 1751 NTAPI 1752 IopGetRegistryValue(IN HANDLE Handle, 1753 IN PWSTR ValueName, 1754 OUT PKEY_VALUE_FULL_INFORMATION *Information) 1755 { 1756 UNICODE_STRING ValueString; 1757 NTSTATUS Status; 1758 PKEY_VALUE_FULL_INFORMATION FullInformation; 1759 ULONG Size; 1760 PAGED_CODE(); 1761 1762 RtlInitUnicodeString(&ValueString, ValueName); 1763 1764 Status = ZwQueryValueKey(Handle, 1765 &ValueString, 1766 KeyValueFullInformation, 1767 NULL, 1768 0, 1769 &Size); 1770 if ((Status != STATUS_BUFFER_OVERFLOW) && 1771 (Status != STATUS_BUFFER_TOO_SMALL)) 1772 { 1773 return Status; 1774 } 1775 1776 FullInformation = ExAllocatePool(NonPagedPool, Size); 1777 if (!FullInformation) return STATUS_INSUFFICIENT_RESOURCES; 1778 1779 Status = ZwQueryValueKey(Handle, 1780 &ValueString, 1781 KeyValueFullInformation, 1782 FullInformation, 1783 Size, 1784 &Size); 1785 if (!NT_SUCCESS(Status)) 1786 { 1787 ExFreePool(FullInformation); 1788 return Status; 1789 } 1790 1791 *Information = FullInformation; 1792 return STATUS_SUCCESS; 1793 } 1794 1795 RTL_GENERIC_COMPARE_RESULTS 1796 NTAPI 1797 PiCompareInstancePath(IN PRTL_AVL_TABLE Table, 1798 IN PVOID FirstStruct, 1799 IN PVOID SecondStruct) 1800 { 1801 /* FIXME: TODO */ 1802 ASSERT(FALSE); 1803 return 0; 1804 } 1805 1806 // 1807 // The allocation function is called by the generic table package whenever 1808 // it needs to allocate memory for the table. 1809 // 1810 1811 PVOID 1812 NTAPI 1813 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table, 1814 IN CLONG ByteSize) 1815 { 1816 /* FIXME: TODO */ 1817 ASSERT(FALSE); 1818 return NULL; 1819 } 1820 1821 VOID 1822 NTAPI 1823 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table, 1824 IN PVOID Buffer) 1825 { 1826 /* FIXME: TODO */ 1827 ASSERT(FALSE); 1828 } 1829 1830 VOID 1831 NTAPI 1832 PpInitializeDeviceReferenceTable(VOID) 1833 { 1834 /* Setup the guarded mutex and AVL table */ 1835 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock); 1836 RtlInitializeGenericTableAvl( 1837 &PpDeviceReferenceTable, 1838 (PRTL_AVL_COMPARE_ROUTINE)PiCompareInstancePath, 1839 (PRTL_AVL_ALLOCATE_ROUTINE)PiAllocateGenericTableEntry, 1840 (PRTL_AVL_FREE_ROUTINE)PiFreeGenericTableEntry, 1841 NULL); 1842 } 1843 1844 BOOLEAN 1845 NTAPI 1846 PiInitPhase0(VOID) 1847 { 1848 /* Initialize the resource when accessing device registry data */ 1849 ExInitializeResourceLite(&PpRegistryDeviceResource); 1850 1851 /* Setup the device reference AVL table */ 1852 PpInitializeDeviceReferenceTable(); 1853 return TRUE; 1854 } 1855 1856 BOOLEAN 1857 NTAPI 1858 PpInitSystem(VOID) 1859 { 1860 /* Check the initialization phase */ 1861 switch (ExpInitializationPhase) 1862 { 1863 case 0: 1864 1865 /* Do Phase 0 */ 1866 return PiInitPhase0(); 1867 1868 case 1: 1869 1870 /* Do Phase 1 */ 1871 return TRUE; 1872 //return PiInitPhase1(); 1873 1874 default: 1875 1876 /* Don't know any other phase! Bugcheck! */ 1877 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL); 1878 return FALSE; 1879 } 1880 } 1881 1882 /* PUBLIC FUNCTIONS **********************************************************/ 1883 1884 NTSTATUS 1885 NTAPI 1886 PnpBusTypeGuidGet(IN USHORT Index, 1887 IN LPGUID BusTypeGuid) 1888 { 1889 NTSTATUS Status = STATUS_SUCCESS; 1890 1891 /* Acquire the lock */ 1892 ExAcquireFastMutex(&PnpBusTypeGuidList->Lock); 1893 1894 /* Validate size */ 1895 if (Index < PnpBusTypeGuidList->GuidCount) 1896 { 1897 /* Copy the data */ 1898 RtlCopyMemory(BusTypeGuid, &PnpBusTypeGuidList->Guids[Index], sizeof(GUID)); 1899 } 1900 else 1901 { 1902 /* Failure path */ 1903 Status = STATUS_OBJECT_NAME_NOT_FOUND; 1904 } 1905 1906 /* Release lock and return status */ 1907 ExReleaseFastMutex(&PnpBusTypeGuidList->Lock); 1908 return Status; 1909 } 1910 1911 NTSTATUS 1912 NTAPI 1913 PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject, 1914 IN PHANDLE DeviceInstanceHandle, 1915 IN ACCESS_MASK DesiredAccess) 1916 { 1917 NTSTATUS Status; 1918 HANDLE KeyHandle; 1919 PDEVICE_NODE DeviceNode; 1920 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM"); 1921 PAGED_CODE(); 1922 1923 /* Open the enum key */ 1924 Status = IopOpenRegistryKeyEx(&KeyHandle, 1925 NULL, 1926 &KeyName, 1927 KEY_READ); 1928 if (!NT_SUCCESS(Status)) return Status; 1929 1930 /* Make sure we have an instance path */ 1931 DeviceNode = IopGetDeviceNode(DeviceObject); 1932 if ((DeviceNode) && (DeviceNode->InstancePath.Length)) 1933 { 1934 /* Get the instance key */ 1935 Status = IopOpenRegistryKeyEx(DeviceInstanceHandle, 1936 KeyHandle, 1937 &DeviceNode->InstancePath, 1938 DesiredAccess); 1939 } 1940 else 1941 { 1942 /* Fail */ 1943 Status = STATUS_INVALID_DEVICE_REQUEST; 1944 } 1945 1946 /* Close the handle and return status */ 1947 ZwClose(KeyHandle); 1948 return Status; 1949 } 1950 1951 ULONG 1952 NTAPI 1953 PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList) 1954 { 1955 ULONG FinalSize, PartialSize, EntrySize, i, j; 1956 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; 1957 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 1958 1959 /* If we don't have one, that's easy */ 1960 if (!ResourceList) return 0; 1961 1962 /* Start with the minimum size possible */ 1963 FinalSize = FIELD_OFFSET(CM_RESOURCE_LIST, List); 1964 1965 /* Loop each full descriptor */ 1966 FullDescriptor = ResourceList->List; 1967 for (i = 0; i < ResourceList->Count; i++) 1968 { 1969 /* Start with the minimum size possible */ 1970 PartialSize = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) + 1971 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors); 1972 1973 /* Loop each partial descriptor */ 1974 PartialDescriptor = FullDescriptor->PartialResourceList.PartialDescriptors; 1975 for (j = 0; j < FullDescriptor->PartialResourceList.Count; j++) 1976 { 1977 /* Start with the minimum size possible */ 1978 EntrySize = sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 1979 1980 /* Check if there is extra data */ 1981 if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific) 1982 { 1983 /* Add that data */ 1984 EntrySize += PartialDescriptor->u.DeviceSpecificData.DataSize; 1985 } 1986 1987 /* The size of partial descriptors is bigger */ 1988 PartialSize += EntrySize; 1989 1990 /* Go to the next partial descriptor */ 1991 PartialDescriptor = (PVOID)((ULONG_PTR)PartialDescriptor + EntrySize); 1992 } 1993 1994 /* The size of full descriptors is bigger */ 1995 FinalSize += PartialSize; 1996 1997 /* Go to the next full descriptor */ 1998 FullDescriptor = (PVOID)((ULONG_PTR)FullDescriptor + PartialSize); 1999 } 2000 2001 /* Return the final size */ 2002 return FinalSize; 2003 } 2004 2005 NTSTATUS 2006 NTAPI 2007 PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject, 2008 IN ULONG ValueType, 2009 IN PWSTR ValueName, 2010 IN PWSTR KeyName, 2011 OUT PVOID Buffer, 2012 IN PULONG BufferLength) 2013 { 2014 NTSTATUS Status; 2015 HANDLE KeyHandle, SubHandle; 2016 UNICODE_STRING KeyString; 2017 PKEY_VALUE_FULL_INFORMATION KeyValueInfo = NULL; 2018 ULONG Length; 2019 PAGED_CODE(); 2020 2021 /* Find the instance key */ 2022 Status = PnpDeviceObjectToDeviceInstance(DeviceObject, &KeyHandle, KEY_READ); 2023 if (NT_SUCCESS(Status)) 2024 { 2025 /* Check for name given by caller */ 2026 if (KeyName) 2027 { 2028 /* Open this key */ 2029 RtlInitUnicodeString(&KeyString, KeyName); 2030 Status = IopOpenRegistryKeyEx(&SubHandle, 2031 KeyHandle, 2032 &KeyString, 2033 KEY_READ); 2034 if (NT_SUCCESS(Status)) 2035 { 2036 /* And use this handle instead */ 2037 ZwClose(KeyHandle); 2038 KeyHandle = SubHandle; 2039 } 2040 } 2041 2042 /* Check if sub-key handle succeeded (or no-op if no key name given) */ 2043 if (NT_SUCCESS(Status)) 2044 { 2045 /* Now get the size of the property */ 2046 Status = IopGetRegistryValue(KeyHandle, 2047 ValueName, 2048 &KeyValueInfo); 2049 } 2050 2051 /* Close the key */ 2052 ZwClose(KeyHandle); 2053 } 2054 2055 /* Fail if any of the registry operations failed */ 2056 if (!NT_SUCCESS(Status)) return Status; 2057 2058 /* Check how much data we have to copy */ 2059 Length = KeyValueInfo->DataLength; 2060 if (*BufferLength >= Length) 2061 { 2062 /* Check for a match in the value type */ 2063 if (KeyValueInfo->Type == ValueType) 2064 { 2065 /* Copy the data */ 2066 RtlCopyMemory(Buffer, 2067 (PVOID)((ULONG_PTR)KeyValueInfo + 2068 KeyValueInfo->DataOffset), 2069 Length); 2070 } 2071 else 2072 { 2073 /* Invalid registry property type, fail */ 2074 Status = STATUS_INVALID_PARAMETER_2; 2075 } 2076 } 2077 else 2078 { 2079 /* Buffer is too small to hold data */ 2080 Status = STATUS_BUFFER_TOO_SMALL; 2081 } 2082 2083 /* Return the required buffer length, free the buffer, and return status */ 2084 *BufferLength = Length; 2085 ExFreePool(KeyValueInfo); 2086 return Status; 2087 } 2088 2089 #define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;} 2090 #define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;} 2091 #define PIP_UNIMPLEMENTED() {UNIMPLEMENTED_DBGBREAK(); break;} 2092 2093 /* 2094 * @implemented 2095 */ 2096 NTSTATUS 2097 NTAPI 2098 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, 2099 IN DEVICE_REGISTRY_PROPERTY DeviceProperty, 2100 IN ULONG BufferLength, 2101 OUT PVOID PropertyBuffer, 2102 OUT PULONG ResultLength) 2103 { 2104 PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject); 2105 DEVICE_CAPABILITIES DeviceCaps; 2106 ULONG ReturnLength = 0, Length = 0, ValueType; 2107 PWCHAR ValueName = NULL, EnumeratorNameEnd, DeviceInstanceName; 2108 PVOID Data = NULL; 2109 NTSTATUS Status = STATUS_BUFFER_TOO_SMALL; 2110 GUID BusTypeGuid; 2111 POBJECT_NAME_INFORMATION ObjectNameInfo = NULL; 2112 BOOLEAN NullTerminate = FALSE; 2113 DEVICE_REMOVAL_POLICY Policy; 2114 2115 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject, DeviceProperty); 2116 2117 /* Assume failure */ 2118 *ResultLength = 0; 2119 2120 /* Only PDOs can call this */ 2121 if (!DeviceNode) return STATUS_INVALID_DEVICE_REQUEST; 2122 2123 /* Handle all properties */ 2124 switch (DeviceProperty) 2125 { 2126 case DevicePropertyBusTypeGuid: 2127 2128 /* Get the GUID from the internal cache */ 2129 Status = PnpBusTypeGuidGet(DeviceNode->ChildBusTypeIndex, &BusTypeGuid); 2130 if (!NT_SUCCESS(Status)) return Status; 2131 2132 /* This is the format of the returned data */ 2133 PIP_RETURN_DATA(sizeof(GUID), &BusTypeGuid); 2134 2135 case DevicePropertyLegacyBusType: 2136 2137 /* Validate correct interface type */ 2138 if (DeviceNode->ChildInterfaceType == InterfaceTypeUndefined) 2139 return STATUS_OBJECT_NAME_NOT_FOUND; 2140 2141 /* This is the format of the returned data */ 2142 PIP_RETURN_DATA(sizeof(INTERFACE_TYPE), &DeviceNode->ChildInterfaceType); 2143 2144 case DevicePropertyBusNumber: 2145 2146 /* Validate correct bus number */ 2147 if ((DeviceNode->ChildBusNumber & 0x80000000) == 0x80000000) 2148 return STATUS_OBJECT_NAME_NOT_FOUND; 2149 2150 /* This is the format of the returned data */ 2151 PIP_RETURN_DATA(sizeof(ULONG), &DeviceNode->ChildBusNumber); 2152 2153 case DevicePropertyEnumeratorName: 2154 2155 /* Get the instance path */ 2156 DeviceInstanceName = DeviceNode->InstancePath.Buffer; 2157 2158 /* Sanity checks */ 2159 ASSERT((BufferLength & 1) == 0); 2160 ASSERT(DeviceInstanceName != NULL); 2161 2162 /* Get the name from the path */ 2163 EnumeratorNameEnd = wcschr(DeviceInstanceName, OBJ_NAME_PATH_SEPARATOR); 2164 ASSERT(EnumeratorNameEnd); 2165 2166 /* This string needs to be NULL-terminated */ 2167 NullTerminate = TRUE; 2168 2169 /* This is the format of the returned data */ 2170 PIP_RETURN_DATA((ULONG)(EnumeratorNameEnd - DeviceInstanceName) * sizeof(WCHAR), 2171 DeviceInstanceName); 2172 2173 case DevicePropertyAddress: 2174 2175 /* Query the device caps */ 2176 Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCaps); 2177 if (!NT_SUCCESS(Status) || (DeviceCaps.Address == MAXULONG)) 2178 return STATUS_OBJECT_NAME_NOT_FOUND; 2179 2180 /* This is the format of the returned data */ 2181 PIP_RETURN_DATA(sizeof(ULONG), &DeviceCaps.Address); 2182 2183 case DevicePropertyBootConfigurationTranslated: 2184 2185 /* Validate we have resources */ 2186 if (!DeviceNode->BootResources) 2187 // if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field 2188 { 2189 /* No resources will still fake success, but with 0 bytes */ 2190 *ResultLength = 0; 2191 return STATUS_SUCCESS; 2192 } 2193 2194 /* This is the format of the returned data */ 2195 PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode->BootResources), // FIXFIX: Should use BootResourcesTranslated 2196 DeviceNode->BootResources); // FIXFIX: Should use BootResourcesTranslated 2197 2198 case DevicePropertyPhysicalDeviceObjectName: 2199 2200 /* Sanity check for Unicode-sized string */ 2201 ASSERT((BufferLength & 1) == 0); 2202 2203 /* Allocate name buffer */ 2204 Length = BufferLength + sizeof(OBJECT_NAME_INFORMATION); 2205 ObjectNameInfo = ExAllocatePool(PagedPool, Length); 2206 if (!ObjectNameInfo) return STATUS_INSUFFICIENT_RESOURCES; 2207 2208 /* Query the PDO name */ 2209 Status = ObQueryNameString(DeviceObject, 2210 ObjectNameInfo, 2211 Length, 2212 ResultLength); 2213 if (Status == STATUS_INFO_LENGTH_MISMATCH) 2214 { 2215 /* It's up to the caller to try again */ 2216 Status = STATUS_BUFFER_TOO_SMALL; 2217 } 2218 2219 /* This string needs to be NULL-terminated */ 2220 NullTerminate = TRUE; 2221 2222 /* Return if successful */ 2223 if (NT_SUCCESS(Status)) PIP_RETURN_DATA(ObjectNameInfo->Name.Length, 2224 ObjectNameInfo->Name.Buffer); 2225 2226 /* Let the caller know how big the name is */ 2227 *ResultLength -= sizeof(OBJECT_NAME_INFORMATION); 2228 break; 2229 2230 case DevicePropertyRemovalPolicy: 2231 2232 Policy = DeviceNode->RemovalPolicy; 2233 PIP_RETURN_DATA(sizeof(Policy), &Policy); 2234 2235 /* Handle the registry-based properties */ 2236 case DevicePropertyUINumber: 2237 PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER, REG_DWORD); 2238 case DevicePropertyLocationInformation: 2239 PIP_REGISTRY_DATA(REGSTR_VAL_LOCATION_INFORMATION, REG_SZ); 2240 case DevicePropertyDeviceDescription: 2241 PIP_REGISTRY_DATA(REGSTR_VAL_DEVDESC, REG_SZ); 2242 case DevicePropertyHardwareID: 2243 PIP_REGISTRY_DATA(REGSTR_VAL_HARDWAREID, REG_MULTI_SZ); 2244 case DevicePropertyCompatibleIDs: 2245 PIP_REGISTRY_DATA(REGSTR_VAL_COMPATIBLEIDS, REG_MULTI_SZ); 2246 case DevicePropertyBootConfiguration: 2247 PIP_REGISTRY_DATA(REGSTR_VAL_BOOTCONFIG, REG_RESOURCE_LIST); 2248 case DevicePropertyClassName: 2249 PIP_REGISTRY_DATA(REGSTR_VAL_CLASS, REG_SZ); 2250 case DevicePropertyClassGuid: 2251 PIP_REGISTRY_DATA(REGSTR_VAL_CLASSGUID, REG_SZ); 2252 case DevicePropertyDriverKeyName: 2253 PIP_REGISTRY_DATA(REGSTR_VAL_DRIVER, REG_SZ); 2254 case DevicePropertyManufacturer: 2255 PIP_REGISTRY_DATA(REGSTR_VAL_MFG, REG_SZ); 2256 case DevicePropertyFriendlyName: 2257 PIP_REGISTRY_DATA(REGSTR_VAL_FRIENDLYNAME, REG_SZ); 2258 case DevicePropertyContainerID: 2259 //PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7 2260 PIP_UNIMPLEMENTED(); 2261 break; 2262 case DevicePropertyInstallState: 2263 PIP_REGISTRY_DATA(REGSTR_VAL_CONFIGFLAGS, REG_DWORD); 2264 break; 2265 case DevicePropertyResourceRequirements: 2266 PIP_UNIMPLEMENTED(); 2267 case DevicePropertyAllocatedResources: 2268 PIP_UNIMPLEMENTED(); 2269 default: 2270 return STATUS_INVALID_PARAMETER_2; 2271 } 2272 2273 /* Having a registry value name implies registry data */ 2274 if (ValueName) 2275 { 2276 /* We know up-front how much data to expect */ 2277 *ResultLength = BufferLength; 2278 2279 /* Go get the data, use the LogConf subkey if necessary */ 2280 Status = PiGetDeviceRegistryProperty(DeviceObject, 2281 ValueType, 2282 ValueName, 2283 (DeviceProperty == 2284 DevicePropertyBootConfiguration) ? 2285 L"LogConf": NULL, 2286 PropertyBuffer, 2287 ResultLength); 2288 } 2289 else if (NT_SUCCESS(Status)) 2290 { 2291 /* We know up-front how much data to expect, check the caller's buffer */ 2292 *ResultLength = ReturnLength + (NullTerminate ? sizeof(UNICODE_NULL) : 0); 2293 if (*ResultLength <= BufferLength) 2294 { 2295 /* Buffer is all good, copy the data */ 2296 RtlCopyMemory(PropertyBuffer, Data, ReturnLength); 2297 2298 /* Check if we need to NULL-terminate the string */ 2299 if (NullTerminate) 2300 { 2301 /* Terminate the string */ 2302 ((PWCHAR)PropertyBuffer)[ReturnLength / sizeof(WCHAR)] = UNICODE_NULL; 2303 } 2304 2305 /* This is the success path */ 2306 Status = STATUS_SUCCESS; 2307 } 2308 else 2309 { 2310 /* Failure path */ 2311 Status = STATUS_BUFFER_TOO_SMALL; 2312 } 2313 } 2314 2315 /* Free any allocation we may have made, and return the status code */ 2316 if (ObjectNameInfo) ExFreePool(ObjectNameInfo); 2317 return Status; 2318 } 2319 2320 /** 2321 * @name IoOpenDeviceRegistryKey 2322 * 2323 * Open a registry key unique for a specified driver or device instance. 2324 * 2325 * @param DeviceObject Device to get the registry key for. 2326 * @param DevInstKeyType Type of the key to return. 2327 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE). 2328 * @param DevInstRegKey Handle to the opened registry key on 2329 * successful return. 2330 * 2331 * @return Status. 2332 * 2333 * @implemented 2334 */ 2335 NTSTATUS 2336 NTAPI 2337 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject, 2338 IN ULONG DevInstKeyType, 2339 IN ACCESS_MASK DesiredAccess, 2340 OUT PHANDLE DevInstRegKey) 2341 { 2342 static WCHAR RootKeyName[] = 2343 L"\\Registry\\Machine\\System\\CurrentControlSet\\"; 2344 static WCHAR ProfileKeyName[] = 2345 L"Hardware Profiles\\Current\\System\\CurrentControlSet\\"; 2346 static WCHAR ClassKeyName[] = L"Control\\Class\\"; 2347 static WCHAR EnumKeyName[] = L"Enum\\"; 2348 static WCHAR DeviceParametersKeyName[] = L"Device Parameters"; 2349 ULONG KeyNameLength; 2350 PWSTR KeyNameBuffer; 2351 UNICODE_STRING KeyName; 2352 ULONG DriverKeyLength; 2353 OBJECT_ATTRIBUTES ObjectAttributes; 2354 PDEVICE_NODE DeviceNode = NULL; 2355 NTSTATUS Status; 2356 2357 DPRINT("IoOpenDeviceRegistryKey() called\n"); 2358 2359 if ((DevInstKeyType & (PLUGPLAY_REGKEY_DEVICE | PLUGPLAY_REGKEY_DRIVER)) == 0) 2360 { 2361 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n"); 2362 return STATUS_INVALID_PARAMETER; 2363 } 2364 2365 if (!IopIsValidPhysicalDeviceObject(DeviceObject)) 2366 return STATUS_INVALID_DEVICE_REQUEST; 2367 DeviceNode = IopGetDeviceNode(DeviceObject); 2368 2369 /* 2370 * Calculate the length of the base key name. This is the full 2371 * name for driver key or the name excluding "Device Parameters" 2372 * subkey for device key. 2373 */ 2374 2375 KeyNameLength = sizeof(RootKeyName); 2376 if (DevInstKeyType & PLUGPLAY_REGKEY_CURRENT_HWPROFILE) 2377 KeyNameLength += sizeof(ProfileKeyName) - sizeof(UNICODE_NULL); 2378 if (DevInstKeyType & PLUGPLAY_REGKEY_DRIVER) 2379 { 2380 KeyNameLength += sizeof(ClassKeyName) - sizeof(UNICODE_NULL); 2381 Status = IoGetDeviceProperty(DeviceObject, DevicePropertyDriverKeyName, 2382 0, NULL, &DriverKeyLength); 2383 if (Status != STATUS_BUFFER_TOO_SMALL) 2384 return Status; 2385 KeyNameLength += DriverKeyLength; 2386 } 2387 else 2388 { 2389 KeyNameLength += sizeof(EnumKeyName) - sizeof(UNICODE_NULL) + 2390 DeviceNode->InstancePath.Length; 2391 } 2392 2393 /* 2394 * Now allocate the buffer for the key name... 2395 */ 2396 2397 KeyNameBuffer = ExAllocatePool(PagedPool, KeyNameLength); 2398 if (KeyNameBuffer == NULL) 2399 return STATUS_INSUFFICIENT_RESOURCES; 2400 2401 KeyName.Length = 0; 2402 KeyName.MaximumLength = (USHORT)KeyNameLength; 2403 KeyName.Buffer = KeyNameBuffer; 2404 2405 /* 2406 * ...and build the key name. 2407 */ 2408 2409 KeyName.Length += sizeof(RootKeyName) - sizeof(UNICODE_NULL); 2410 RtlCopyMemory(KeyNameBuffer, RootKeyName, KeyName.Length); 2411 2412 if (DevInstKeyType & PLUGPLAY_REGKEY_CURRENT_HWPROFILE) 2413 RtlAppendUnicodeToString(&KeyName, ProfileKeyName); 2414 2415 if (DevInstKeyType & PLUGPLAY_REGKEY_DRIVER) 2416 { 2417 RtlAppendUnicodeToString(&KeyName, ClassKeyName); 2418 Status = IoGetDeviceProperty(DeviceObject, DevicePropertyDriverKeyName, 2419 DriverKeyLength, KeyNameBuffer + 2420 (KeyName.Length / sizeof(WCHAR)), 2421 &DriverKeyLength); 2422 if (!NT_SUCCESS(Status)) 2423 { 2424 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status); 2425 ExFreePool(KeyNameBuffer); 2426 return Status; 2427 } 2428 KeyName.Length += (USHORT)DriverKeyLength - sizeof(UNICODE_NULL); 2429 } 2430 else 2431 { 2432 RtlAppendUnicodeToString(&KeyName, EnumKeyName); 2433 Status = RtlAppendUnicodeStringToString(&KeyName, &DeviceNode->InstancePath); 2434 if (DeviceNode->InstancePath.Length == 0) 2435 { 2436 ExFreePool(KeyNameBuffer); 2437 return Status; 2438 } 2439 } 2440 2441 /* 2442 * Open the base key. 2443 */ 2444 Status = IopOpenRegistryKeyEx(DevInstRegKey, NULL, &KeyName, DesiredAccess); 2445 if (!NT_SUCCESS(Status)) 2446 { 2447 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName, Status); 2448 ExFreePool(KeyNameBuffer); 2449 return Status; 2450 } 2451 ExFreePool(KeyNameBuffer); 2452 2453 /* 2454 * For driver key we're done now. 2455 */ 2456 2457 if (DevInstKeyType & PLUGPLAY_REGKEY_DRIVER) 2458 return Status; 2459 2460 /* 2461 * Let's go further. For device key we must open "Device Parameters" 2462 * subkey and create it if it doesn't exist yet. 2463 */ 2464 2465 RtlInitUnicodeString(&KeyName, DeviceParametersKeyName); 2466 InitializeObjectAttributes(&ObjectAttributes, 2467 &KeyName, 2468 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 2469 *DevInstRegKey, 2470 NULL); 2471 Status = ZwCreateKey(DevInstRegKey, 2472 DesiredAccess, 2473 &ObjectAttributes, 2474 0, 2475 NULL, 2476 REG_OPTION_NON_VOLATILE, 2477 NULL); 2478 ZwClose(ObjectAttributes.RootDirectory); 2479 2480 return Status; 2481 } 2482 2483 /* 2484 * @implemented 2485 */ 2486 VOID 2487 NTAPI 2488 IoInvalidateDeviceRelations( 2489 IN PDEVICE_OBJECT DeviceObject, 2490 IN DEVICE_RELATION_TYPE Type) 2491 { 2492 if (!IopIsValidPhysicalDeviceObject(DeviceObject)) 2493 { 2494 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG_PTR)DeviceObject, 0, 0); 2495 } 2496 2497 switch (Type) 2498 { 2499 case BusRelations: 2500 /* Enumerate the device */ 2501 PiQueueDeviceAction(DeviceObject, PiActionEnumDeviceTree, NULL, NULL); 2502 break; 2503 default: 2504 /* Everything else is not implemented */ 2505 break; 2506 } 2507 } 2508 2509 /* 2510 * @implemented 2511 */ 2512 NTSTATUS 2513 NTAPI 2514 IoSynchronousInvalidateDeviceRelations( 2515 IN PDEVICE_OBJECT DeviceObject, 2516 IN DEVICE_RELATION_TYPE Type) 2517 { 2518 PAGED_CODE(); 2519 2520 if (!IopIsValidPhysicalDeviceObject(DeviceObject)) 2521 { 2522 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG_PTR)DeviceObject, 0, 0); 2523 } 2524 2525 switch (Type) 2526 { 2527 case BusRelations: 2528 /* Enumerate the device */ 2529 return PiPerformSyncDeviceAction(DeviceObject, PiActionEnumDeviceTree); 2530 case PowerRelations: 2531 /* Not handled yet */ 2532 return STATUS_NOT_IMPLEMENTED; 2533 case TargetDeviceRelation: 2534 /* Nothing to do */ 2535 return STATUS_SUCCESS; 2536 default: 2537 /* Ejection relations are not supported */ 2538 return STATUS_NOT_SUPPORTED; 2539 } 2540 } 2541 2542 /* 2543 * @implemented 2544 */ 2545 BOOLEAN 2546 NTAPI 2547 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType, 2548 IN ULONG BusNumber, 2549 IN PHYSICAL_ADDRESS BusAddress, 2550 IN OUT PULONG AddressSpace, 2551 OUT PPHYSICAL_ADDRESS TranslatedAddress) 2552 { 2553 /* FIXME: Notify the resource arbiter */ 2554 2555 return HalTranslateBusAddress(InterfaceType, 2556 BusNumber, 2557 BusAddress, 2558 AddressSpace, 2559 TranslatedAddress); 2560 } 2561