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 if (Status == STATUS_PENDING) 603 { 604 /* Wait for it */ 605 KeWaitForSingleObject(&Event, 606 Executive, 607 KernelMode, 608 FALSE, 609 NULL); 610 Status = IoStatusBlock.Status; 611 } 612 613 /* Remove the reference */ 614 ObDereferenceObject(TopDeviceObject); 615 616 /* Return the information */ 617 *Information = (PVOID)IoStatusBlock.Information; 618 return Status; 619 } 620 621 NTSTATUS 622 NTAPI 623 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject, 624 IN OUT PIO_STATUS_BLOCK IoStatusBlock, 625 IN UCHAR MinorFunction, 626 IN PIO_STACK_LOCATION Stack OPTIONAL) 627 { 628 IO_STACK_LOCATION IoStackLocation; 629 630 /* Fill out the stack information */ 631 RtlZeroMemory(&IoStackLocation, sizeof(IO_STACK_LOCATION)); 632 IoStackLocation.MajorFunction = IRP_MJ_PNP; 633 IoStackLocation.MinorFunction = MinorFunction; 634 if (Stack) 635 { 636 /* Copy the rest */ 637 RtlCopyMemory(&IoStackLocation.Parameters, 638 &Stack->Parameters, 639 sizeof(Stack->Parameters)); 640 } 641 642 /* Do the PnP call */ 643 IoStatusBlock->Status = IopSynchronousCall(DeviceObject, 644 &IoStackLocation, 645 (PVOID)&IoStatusBlock->Information); 646 return IoStatusBlock->Status; 647 } 648 649 /* 650 * IopCreateDeviceKeyPath 651 * 652 * Creates a registry key 653 * 654 * Parameters 655 * RegistryPath 656 * Name of the key to be created. 657 * Handle 658 * Handle to the newly created key 659 * 660 * Remarks 661 * This method can create nested trees, so parent of RegistryPath can 662 * be not existant, and will be created if needed. 663 */ 664 NTSTATUS 665 NTAPI 666 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, 667 IN ULONG CreateOptions, 668 OUT PHANDLE Handle) 669 { 670 UNICODE_STRING EnumU = RTL_CONSTANT_STRING(ENUM_ROOT); 671 HANDLE hParent = NULL, hKey; 672 OBJECT_ATTRIBUTES ObjectAttributes; 673 UNICODE_STRING KeyName; 674 PCWSTR Current, Last; 675 USHORT Length; 676 NTSTATUS Status; 677 678 /* Assume failure */ 679 *Handle = NULL; 680 681 /* Open root key for device instances */ 682 Status = IopOpenRegistryKeyEx(&hParent, NULL, &EnumU, KEY_CREATE_SUB_KEY); 683 if (!NT_SUCCESS(Status)) 684 { 685 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU, Status); 686 return Status; 687 } 688 689 Current = KeyName.Buffer = RegistryPath->Buffer; 690 Last = &RegistryPath->Buffer[RegistryPath->Length / sizeof(WCHAR)]; 691 692 /* Go up to the end of the string */ 693 while (Current <= Last) 694 { 695 if (Current != Last && *Current != L'\\') 696 { 697 /* Not the end of the string and not a separator */ 698 Current++; 699 continue; 700 } 701 702 /* Prepare relative key name */ 703 Length = (USHORT)((ULONG_PTR)Current - (ULONG_PTR)KeyName.Buffer); 704 KeyName.MaximumLength = KeyName.Length = Length; 705 DPRINT("Create '%wZ'\n", &KeyName); 706 707 /* Open key */ 708 InitializeObjectAttributes(&ObjectAttributes, 709 &KeyName, 710 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 711 hParent, 712 NULL); 713 Status = ZwCreateKey(&hKey, 714 Current == Last ? KEY_ALL_ACCESS : KEY_CREATE_SUB_KEY, 715 &ObjectAttributes, 716 0, 717 NULL, 718 CreateOptions, 719 NULL); 720 721 /* Close parent key handle, we don't need it anymore */ 722 if (hParent) 723 ZwClose(hParent); 724 725 /* Key opening/creating failed? */ 726 if (!NT_SUCCESS(Status)) 727 { 728 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName, Status); 729 return Status; 730 } 731 732 /* Check if it is the end of the string */ 733 if (Current == Last) 734 { 735 /* Yes, return success */ 736 *Handle = hKey; 737 return STATUS_SUCCESS; 738 } 739 740 /* Start with this new parent key */ 741 hParent = hKey; 742 Current++; 743 KeyName.Buffer = (PWSTR)Current; 744 } 745 746 return STATUS_UNSUCCESSFUL; 747 } 748 749 NTSTATUS 750 IopSetDeviceInstanceData(HANDLE InstanceKey, 751 PDEVICE_NODE DeviceNode) 752 { 753 OBJECT_ATTRIBUTES ObjectAttributes; 754 UNICODE_STRING KeyName; 755 HANDLE LogConfKey, ControlKey, DeviceParamsKey; 756 ULONG ResCount; 757 ULONG ResultLength; 758 NTSTATUS Status; 759 760 DPRINT("IopSetDeviceInstanceData() called\n"); 761 762 /* Create the 'LogConf' key */ 763 RtlInitUnicodeString(&KeyName, L"LogConf"); 764 InitializeObjectAttributes(&ObjectAttributes, 765 &KeyName, 766 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 767 InstanceKey, 768 NULL); 769 Status = ZwCreateKey(&LogConfKey, 770 KEY_ALL_ACCESS, 771 &ObjectAttributes, 772 0, 773 NULL, 774 // FIXME? In r53694 it was silently turned from non-volatile into this, 775 // without any extra warning. Is this still needed?? 776 REG_OPTION_VOLATILE, 777 NULL); 778 if (NT_SUCCESS(Status)) 779 { 780 /* Set 'BootConfig' value */ 781 if (DeviceNode->BootResources != NULL) 782 { 783 ResCount = DeviceNode->BootResources->Count; 784 if (ResCount != 0) 785 { 786 RtlInitUnicodeString(&KeyName, L"BootConfig"); 787 Status = ZwSetValueKey(LogConfKey, 788 &KeyName, 789 0, 790 REG_RESOURCE_LIST, 791 DeviceNode->BootResources, 792 PnpDetermineResourceListSize(DeviceNode->BootResources)); 793 } 794 } 795 796 /* Set 'BasicConfigVector' value */ 797 if (DeviceNode->ResourceRequirements != NULL && 798 DeviceNode->ResourceRequirements->ListSize != 0) 799 { 800 RtlInitUnicodeString(&KeyName, L"BasicConfigVector"); 801 Status = ZwSetValueKey(LogConfKey, 802 &KeyName, 803 0, 804 REG_RESOURCE_REQUIREMENTS_LIST, 805 DeviceNode->ResourceRequirements, 806 DeviceNode->ResourceRequirements->ListSize); 807 } 808 809 ZwClose(LogConfKey); 810 } 811 812 /* Set the 'ConfigFlags' value */ 813 RtlInitUnicodeString(&KeyName, L"ConfigFlags"); 814 Status = ZwQueryValueKey(InstanceKey, 815 &KeyName, 816 KeyValueBasicInformation, 817 NULL, 818 0, 819 &ResultLength); 820 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 821 { 822 /* Write the default value */ 823 ULONG DefaultConfigFlags = 0; 824 Status = ZwSetValueKey(InstanceKey, 825 &KeyName, 826 0, 827 REG_DWORD, 828 &DefaultConfigFlags, 829 sizeof(DefaultConfigFlags)); 830 } 831 832 /* Create the 'Control' key */ 833 RtlInitUnicodeString(&KeyName, L"Control"); 834 InitializeObjectAttributes(&ObjectAttributes, 835 &KeyName, 836 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 837 InstanceKey, 838 NULL); 839 Status = ZwCreateKey(&ControlKey, 840 0, 841 &ObjectAttributes, 842 0, 843 NULL, 844 REG_OPTION_VOLATILE, 845 NULL); 846 if (NT_SUCCESS(Status)) 847 ZwClose(ControlKey); 848 849 /* Create the 'Device Parameters' key and set the 'FirmwareIdentified' value for all ACPI-enumerated devices */ 850 if (_wcsnicmp(DeviceNode->InstancePath.Buffer, L"ACPI\\", 5) == 0) 851 { 852 RtlInitUnicodeString(&KeyName, L"Device Parameters"); 853 InitializeObjectAttributes(&ObjectAttributes, 854 &KeyName, 855 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 856 InstanceKey, 857 NULL); 858 Status = ZwCreateKey(&DeviceParamsKey, 859 0, 860 &ObjectAttributes, 861 0, 862 NULL, 863 REG_OPTION_NON_VOLATILE, 864 NULL); 865 if (NT_SUCCESS(Status)) 866 { 867 ULONG FirmwareIdentified = 1; 868 RtlInitUnicodeString(&KeyName, L"FirmwareIdentified"); 869 Status = ZwSetValueKey(DeviceParamsKey, 870 &KeyName, 871 0, 872 REG_DWORD, 873 &FirmwareIdentified, 874 sizeof(FirmwareIdentified)); 875 876 ZwClose(DeviceParamsKey); 877 } 878 } 879 880 DPRINT("IopSetDeviceInstanceData() done\n"); 881 882 return Status; 883 } 884 885 /* 886 * IopGetParentIdPrefix 887 * 888 * Retrieve (or create) a string which identifies a device. 889 * 890 * Parameters 891 * DeviceNode 892 * Pointer to device node. 893 * ParentIdPrefix 894 * Pointer to the string where is returned the parent node identifier 895 * 896 * Remarks 897 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is 898 * valid and its Buffer field is NULL-terminated. The caller needs to 899 * to free the string with RtlFreeUnicodeString when it is no longer 900 * needed. 901 */ 902 903 NTSTATUS 904 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode, 905 PUNICODE_STRING ParentIdPrefix) 906 { 907 const UNICODE_STRING EnumKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\"); 908 ULONG KeyNameBufferLength; 909 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation = NULL; 910 UNICODE_STRING KeyName = {0, 0, NULL}; 911 UNICODE_STRING KeyValue; 912 UNICODE_STRING ValueName; 913 HANDLE hKey = NULL; 914 ULONG crc32; 915 NTSTATUS Status; 916 917 /* HACK: As long as some devices have a NULL device 918 * instance path, the following test is required :( 919 */ 920 if (DeviceNode->Parent->InstancePath.Length == 0) 921 { 922 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n", 923 &DeviceNode->InstancePath); 924 return STATUS_UNSUCCESSFUL; 925 } 926 927 /* 1. Try to retrieve ParentIdPrefix from registry */ 928 KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(L"12345678&12345678"); 929 ParentIdPrefixInformation = ExAllocatePoolWithTag(PagedPool, 930 KeyNameBufferLength + sizeof(UNICODE_NULL), 931 TAG_IO); 932 if (!ParentIdPrefixInformation) 933 { 934 return STATUS_INSUFFICIENT_RESOURCES; 935 } 936 937 KeyName.Length = 0; 938 KeyName.MaximumLength = EnumKeyPath.Length + 939 DeviceNode->Parent->InstancePath.Length + 940 sizeof(UNICODE_NULL); 941 KeyName.Buffer = ExAllocatePoolWithTag(PagedPool, 942 KeyName.MaximumLength, 943 TAG_IO); 944 if (!KeyName.Buffer) 945 { 946 Status = STATUS_INSUFFICIENT_RESOURCES; 947 goto cleanup; 948 } 949 950 RtlCopyUnicodeString(&KeyName, &EnumKeyPath); 951 RtlAppendUnicodeStringToString(&KeyName, &DeviceNode->Parent->InstancePath); 952 953 Status = IopOpenRegistryKeyEx(&hKey, NULL, &KeyName, KEY_QUERY_VALUE | KEY_SET_VALUE); 954 if (!NT_SUCCESS(Status)) 955 { 956 goto cleanup; 957 } 958 RtlInitUnicodeString(&ValueName, L"ParentIdPrefix"); 959 Status = ZwQueryValueKey(hKey, 960 &ValueName, 961 KeyValuePartialInformation, 962 ParentIdPrefixInformation, 963 KeyNameBufferLength, 964 &KeyNameBufferLength); 965 if (NT_SUCCESS(Status)) 966 { 967 if (ParentIdPrefixInformation->Type != REG_SZ) 968 { 969 Status = STATUS_UNSUCCESSFUL; 970 } 971 else 972 { 973 KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength; 974 KeyValue.Length = KeyValue.MaximumLength - sizeof(UNICODE_NULL); 975 KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data; 976 ASSERT(KeyValue.Buffer[KeyValue.Length / sizeof(WCHAR)] == UNICODE_NULL); 977 } 978 goto cleanup; 979 } 980 if (Status != STATUS_OBJECT_NAME_NOT_FOUND) 981 { 982 /* FIXME how do we get here and why is ParentIdPrefixInformation valid? */ 983 KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength; 984 KeyValue.Length = KeyValue.MaximumLength - sizeof(UNICODE_NULL); 985 KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data; 986 ASSERT(KeyValue.Buffer[KeyValue.Length / sizeof(WCHAR)] == UNICODE_NULL); 987 goto cleanup; 988 } 989 990 /* 2. Create the ParentIdPrefix value */ 991 crc32 = RtlComputeCrc32(0, 992 (PUCHAR)DeviceNode->Parent->InstancePath.Buffer, 993 DeviceNode->Parent->InstancePath.Length); 994 995 RtlStringCbPrintfW((PWSTR)ParentIdPrefixInformation, 996 KeyNameBufferLength, 997 L"%lx&%lx", 998 DeviceNode->Parent->Level, 999 crc32); 1000 RtlInitUnicodeString(&KeyValue, (PWSTR)ParentIdPrefixInformation); 1001 1002 /* 3. Try to write the ParentIdPrefix to registry */ 1003 Status = ZwSetValueKey(hKey, 1004 &ValueName, 1005 0, 1006 REG_SZ, 1007 KeyValue.Buffer, 1008 ((ULONG)wcslen(KeyValue.Buffer) + 1) * sizeof(WCHAR)); 1009 1010 cleanup: 1011 if (NT_SUCCESS(Status)) 1012 { 1013 /* Duplicate the string to return it */ 1014 Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, 1015 &KeyValue, 1016 ParentIdPrefix); 1017 } 1018 ExFreePoolWithTag(ParentIdPrefixInformation, TAG_IO); 1019 RtlFreeUnicodeString(&KeyName); 1020 if (hKey != NULL) 1021 { 1022 ZwClose(hKey); 1023 } 1024 return Status; 1025 } 1026 1027 static 1028 CODE_SEG("INIT") 1029 NTSTATUS 1030 IopEnumerateDetectedDevices( 1031 IN HANDLE hBaseKey, 1032 IN PUNICODE_STRING RelativePath OPTIONAL, 1033 IN HANDLE hRootKey, 1034 IN BOOLEAN EnumerateSubKeys, 1035 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources, 1036 IN ULONG ParentBootResourcesLength) 1037 { 1038 UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier"); 1039 UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID"); 1040 UNICODE_STRING ConfigurationDataU = RTL_CONSTANT_STRING(L"Configuration Data"); 1041 UNICODE_STRING BootConfigU = RTL_CONSTANT_STRING(L"BootConfig"); 1042 UNICODE_STRING LogConfU = RTL_CONSTANT_STRING(L"LogConf"); 1043 OBJECT_ATTRIBUTES ObjectAttributes; 1044 HANDLE hDevicesKey = NULL; 1045 HANDLE hDeviceKey = NULL; 1046 HANDLE hLevel1Key, hLevel2Key = NULL, hLogConf; 1047 UNICODE_STRING Level2NameU; 1048 WCHAR Level2Name[5]; 1049 ULONG IndexDevice = 0; 1050 ULONG IndexSubKey; 1051 PKEY_BASIC_INFORMATION pDeviceInformation = NULL; 1052 ULONG DeviceInfoLength = sizeof(KEY_BASIC_INFORMATION) + 50 * sizeof(WCHAR); 1053 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation = NULL; 1054 ULONG ValueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 50 * sizeof(WCHAR); 1055 UNICODE_STRING DeviceName, ValueName; 1056 ULONG RequiredSize; 1057 PCM_FULL_RESOURCE_DESCRIPTOR BootResources = NULL; 1058 ULONG BootResourcesLength; 1059 NTSTATUS Status; 1060 1061 const UNICODE_STRING IdentifierSerial = RTL_CONSTANT_STRING(L"SerialController"); 1062 UNICODE_STRING HardwareIdSerial = RTL_CONSTANT_STRING(L"*PNP0501\0"); 1063 static ULONG DeviceIndexSerial = 0; 1064 const UNICODE_STRING IdentifierKeyboard = RTL_CONSTANT_STRING(L"KeyboardController"); 1065 UNICODE_STRING HardwareIdKeyboard = RTL_CONSTANT_STRING(L"*PNP0303\0"); 1066 static ULONG DeviceIndexKeyboard = 0; 1067 const UNICODE_STRING IdentifierMouse = RTL_CONSTANT_STRING(L"PointerController"); 1068 /* FIXME: IopEnumerateDetectedDevices() should be rewritten. 1069 * The PnP identifiers can either be hardcoded or parsed from a LegacyXlate 1070 * sections of driver INF files. 1071 */ 1072 #if defined(SARCH_PC98) 1073 UNICODE_STRING HardwareIdMouse = RTL_CONSTANT_STRING(L"*nEC1F00\0"); 1074 #else 1075 UNICODE_STRING HardwareIdMouse = RTL_CONSTANT_STRING(L"*PNP0F13\0"); 1076 #endif 1077 static ULONG DeviceIndexMouse = 0; 1078 const UNICODE_STRING IdentifierParallel = RTL_CONSTANT_STRING(L"ParallelController"); 1079 UNICODE_STRING HardwareIdParallel = RTL_CONSTANT_STRING(L"*PNP0400\0"); 1080 static ULONG DeviceIndexParallel = 0; 1081 const UNICODE_STRING IdentifierFloppy = RTL_CONSTANT_STRING(L"FloppyDiskPeripheral"); 1082 UNICODE_STRING HardwareIdFloppy = RTL_CONSTANT_STRING(L"*PNP0700\0"); 1083 static ULONG DeviceIndexFloppy = 0; 1084 UNICODE_STRING HardwareIdKey; 1085 PUNICODE_STRING pHardwareId; 1086 ULONG DeviceIndex = 0; 1087 PUCHAR CmResourceList; 1088 ULONG ListCount; 1089 1090 if (RelativePath) 1091 { 1092 Status = IopOpenRegistryKeyEx(&hDevicesKey, hBaseKey, RelativePath, KEY_ENUMERATE_SUB_KEYS); 1093 if (!NT_SUCCESS(Status)) 1094 { 1095 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); 1096 goto cleanup; 1097 } 1098 } 1099 else 1100 hDevicesKey = hBaseKey; 1101 1102 pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength); 1103 if (!pDeviceInformation) 1104 { 1105 DPRINT("ExAllocatePool() failed\n"); 1106 Status = STATUS_NO_MEMORY; 1107 goto cleanup; 1108 } 1109 1110 pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); 1111 if (!pValueInformation) 1112 { 1113 DPRINT("ExAllocatePool() failed\n"); 1114 Status = STATUS_NO_MEMORY; 1115 goto cleanup; 1116 } 1117 1118 while (TRUE) 1119 { 1120 Status = ZwEnumerateKey(hDevicesKey, IndexDevice, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize); 1121 if (Status == STATUS_NO_MORE_ENTRIES) 1122 break; 1123 else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 1124 { 1125 ExFreePool(pDeviceInformation); 1126 DeviceInfoLength = RequiredSize; 1127 pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength); 1128 if (!pDeviceInformation) 1129 { 1130 DPRINT("ExAllocatePool() failed\n"); 1131 Status = STATUS_NO_MEMORY; 1132 goto cleanup; 1133 } 1134 Status = ZwEnumerateKey(hDevicesKey, IndexDevice, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize); 1135 } 1136 if (!NT_SUCCESS(Status)) 1137 { 1138 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); 1139 goto cleanup; 1140 } 1141 IndexDevice++; 1142 1143 /* Open device key */ 1144 DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength; 1145 DeviceName.Buffer = pDeviceInformation->Name; 1146 1147 Status = IopOpenRegistryKeyEx(&hDeviceKey, hDevicesKey, &DeviceName, 1148 KEY_QUERY_VALUE + (EnumerateSubKeys ? KEY_ENUMERATE_SUB_KEYS : 0)); 1149 if (!NT_SUCCESS(Status)) 1150 { 1151 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); 1152 goto cleanup; 1153 } 1154 1155 /* Read boot resources, and add then to parent ones */ 1156 Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); 1157 if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 1158 { 1159 ExFreePool(pValueInformation); 1160 ValueInfoLength = RequiredSize; 1161 pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); 1162 if (!pValueInformation) 1163 { 1164 DPRINT("ExAllocatePool() failed\n"); 1165 ZwDeleteKey(hLevel2Key); 1166 Status = STATUS_NO_MEMORY; 1167 goto cleanup; 1168 } 1169 Status = ZwQueryValueKey(hDeviceKey, &ConfigurationDataU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); 1170 } 1171 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 1172 { 1173 BootResources = ParentBootResources; 1174 BootResourcesLength = ParentBootResourcesLength; 1175 } 1176 else if (!NT_SUCCESS(Status)) 1177 { 1178 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); 1179 goto nextdevice; 1180 } 1181 else if (pValueInformation->Type != REG_FULL_RESOURCE_DESCRIPTOR) 1182 { 1183 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_FULL_RESOURCE_DESCRIPTOR); 1184 goto nextdevice; 1185 } 1186 else 1187 { 1188 static const ULONG Header = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors); 1189 1190 /* Concatenate current resources and parent ones */ 1191 if (ParentBootResourcesLength == 0) 1192 BootResourcesLength = pValueInformation->DataLength; 1193 else 1194 BootResourcesLength = ParentBootResourcesLength 1195 + pValueInformation->DataLength 1196 - Header; 1197 BootResources = ExAllocatePool(PagedPool, BootResourcesLength); 1198 if (!BootResources) 1199 { 1200 DPRINT("ExAllocatePool() failed\n"); 1201 goto nextdevice; 1202 } 1203 if (ParentBootResourcesLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) 1204 { 1205 RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength); 1206 } 1207 else if (ParentBootResources->PartialResourceList.PartialDescriptors[ParentBootResources->PartialResourceList.Count - 1].Type == CmResourceTypeDeviceSpecific) 1208 { 1209 RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength); 1210 RtlCopyMemory( 1211 (PVOID)((ULONG_PTR)BootResources + pValueInformation->DataLength), 1212 (PVOID)((ULONG_PTR)ParentBootResources + Header), 1213 ParentBootResourcesLength - Header); 1214 BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count; 1215 } 1216 else 1217 { 1218 RtlCopyMemory(BootResources, pValueInformation->Data, Header); 1219 RtlCopyMemory( 1220 (PVOID)((ULONG_PTR)BootResources + Header), 1221 (PVOID)((ULONG_PTR)ParentBootResources + Header), 1222 ParentBootResourcesLength - Header); 1223 RtlCopyMemory( 1224 (PVOID)((ULONG_PTR)BootResources + ParentBootResourcesLength), 1225 pValueInformation->Data + Header, 1226 pValueInformation->DataLength - Header); 1227 BootResources->PartialResourceList.Count += ParentBootResources->PartialResourceList.Count; 1228 } 1229 } 1230 1231 if (EnumerateSubKeys) 1232 { 1233 IndexSubKey = 0; 1234 while (TRUE) 1235 { 1236 Status = ZwEnumerateKey(hDeviceKey, IndexSubKey, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize); 1237 if (Status == STATUS_NO_MORE_ENTRIES) 1238 break; 1239 else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 1240 { 1241 ExFreePool(pDeviceInformation); 1242 DeviceInfoLength = RequiredSize; 1243 pDeviceInformation = ExAllocatePool(PagedPool, DeviceInfoLength); 1244 if (!pDeviceInformation) 1245 { 1246 DPRINT("ExAllocatePool() failed\n"); 1247 Status = STATUS_NO_MEMORY; 1248 goto cleanup; 1249 } 1250 Status = ZwEnumerateKey(hDeviceKey, IndexSubKey, KeyBasicInformation, pDeviceInformation, DeviceInfoLength, &RequiredSize); 1251 } 1252 if (!NT_SUCCESS(Status)) 1253 { 1254 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); 1255 goto cleanup; 1256 } 1257 IndexSubKey++; 1258 DeviceName.Length = DeviceName.MaximumLength = (USHORT)pDeviceInformation->NameLength; 1259 DeviceName.Buffer = pDeviceInformation->Name; 1260 1261 Status = IopEnumerateDetectedDevices( 1262 hDeviceKey, 1263 &DeviceName, 1264 hRootKey, 1265 TRUE, 1266 BootResources, 1267 BootResourcesLength); 1268 if (!NT_SUCCESS(Status)) 1269 goto cleanup; 1270 } 1271 } 1272 1273 /* Read identifier */ 1274 Status = ZwQueryValueKey(hDeviceKey, &IdentifierU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); 1275 if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 1276 { 1277 ExFreePool(pValueInformation); 1278 ValueInfoLength = RequiredSize; 1279 pValueInformation = ExAllocatePool(PagedPool, ValueInfoLength); 1280 if (!pValueInformation) 1281 { 1282 DPRINT("ExAllocatePool() failed\n"); 1283 Status = STATUS_NO_MEMORY; 1284 goto cleanup; 1285 } 1286 Status = ZwQueryValueKey(hDeviceKey, &IdentifierU, KeyValuePartialInformation, pValueInformation, ValueInfoLength, &RequiredSize); 1287 } 1288 if (!NT_SUCCESS(Status)) 1289 { 1290 if (Status != STATUS_OBJECT_NAME_NOT_FOUND) 1291 { 1292 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); 1293 goto nextdevice; 1294 } 1295 ValueName.Length = ValueName.MaximumLength = 0; 1296 } 1297 else if (pValueInformation->Type != REG_SZ) 1298 { 1299 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation->Type, REG_SZ); 1300 goto nextdevice; 1301 } 1302 else 1303 { 1304 /* Assign hardware id to this device */ 1305 ValueName.Length = ValueName.MaximumLength = (USHORT)pValueInformation->DataLength; 1306 ValueName.Buffer = (PWCHAR)pValueInformation->Data; 1307 if (ValueName.Length >= sizeof(WCHAR) && ValueName.Buffer[ValueName.Length / sizeof(WCHAR) - 1] == UNICODE_NULL) 1308 ValueName.Length -= sizeof(WCHAR); 1309 } 1310 1311 if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierSerial, FALSE) == 0) 1312 { 1313 pHardwareId = &HardwareIdSerial; 1314 DeviceIndex = DeviceIndexSerial++; 1315 } 1316 else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierKeyboard, FALSE) == 0) 1317 { 1318 pHardwareId = &HardwareIdKeyboard; 1319 DeviceIndex = DeviceIndexKeyboard++; 1320 } 1321 else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierMouse, FALSE) == 0) 1322 { 1323 pHardwareId = &HardwareIdMouse; 1324 DeviceIndex = DeviceIndexMouse++; 1325 } 1326 else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierParallel, FALSE) == 0) 1327 { 1328 pHardwareId = &HardwareIdParallel; 1329 DeviceIndex = DeviceIndexParallel++; 1330 } 1331 else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierFloppy, FALSE) == 0) 1332 { 1333 pHardwareId = &HardwareIdFloppy; 1334 DeviceIndex = DeviceIndexFloppy++; 1335 } 1336 else 1337 { 1338 /* Unknown key path */ 1339 DPRINT("Unknown key path '%wZ'\n", RelativePath); 1340 goto nextdevice; 1341 } 1342 1343 /* Prepare hardware id key (hardware id value without final \0) */ 1344 HardwareIdKey = *pHardwareId; 1345 HardwareIdKey.Length -= sizeof(UNICODE_NULL); 1346 1347 /* Add the detected device to Root key */ 1348 InitializeObjectAttributes(&ObjectAttributes, &HardwareIdKey, OBJ_KERNEL_HANDLE, hRootKey, NULL); 1349 Status = ZwCreateKey( 1350 &hLevel1Key, 1351 KEY_CREATE_SUB_KEY, 1352 &ObjectAttributes, 1353 0, 1354 NULL, 1355 REG_OPTION_NON_VOLATILE, 1356 NULL); 1357 if (!NT_SUCCESS(Status)) 1358 { 1359 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); 1360 goto nextdevice; 1361 } 1362 swprintf(Level2Name, L"%04lu", DeviceIndex); 1363 RtlInitUnicodeString(&Level2NameU, Level2Name); 1364 InitializeObjectAttributes(&ObjectAttributes, &Level2NameU, OBJ_KERNEL_HANDLE, hLevel1Key, NULL); 1365 Status = ZwCreateKey( 1366 &hLevel2Key, 1367 KEY_SET_VALUE | KEY_CREATE_SUB_KEY, 1368 &ObjectAttributes, 1369 0, 1370 NULL, 1371 REG_OPTION_NON_VOLATILE, 1372 NULL); 1373 ZwClose(hLevel1Key); 1374 if (!NT_SUCCESS(Status)) 1375 { 1376 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); 1377 goto nextdevice; 1378 } 1379 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName, DeviceIndex, &HardwareIdKey); 1380 Status = ZwSetValueKey(hLevel2Key, &HardwareIDU, 0, REG_MULTI_SZ, pHardwareId->Buffer, pHardwareId->MaximumLength); 1381 if (!NT_SUCCESS(Status)) 1382 { 1383 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); 1384 ZwDeleteKey(hLevel2Key); 1385 goto nextdevice; 1386 } 1387 /* Create 'LogConf' subkey */ 1388 InitializeObjectAttributes(&ObjectAttributes, &LogConfU, OBJ_KERNEL_HANDLE, hLevel2Key, NULL); 1389 Status = ZwCreateKey( 1390 &hLogConf, 1391 KEY_SET_VALUE, 1392 &ObjectAttributes, 1393 0, 1394 NULL, 1395 REG_OPTION_VOLATILE, 1396 NULL); 1397 if (!NT_SUCCESS(Status)) 1398 { 1399 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); 1400 ZwDeleteKey(hLevel2Key); 1401 goto nextdevice; 1402 } 1403 if (BootResourcesLength >= sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) 1404 { 1405 CmResourceList = ExAllocatePool(PagedPool, BootResourcesLength + sizeof(ULONG)); 1406 if (!CmResourceList) 1407 { 1408 ZwClose(hLogConf); 1409 ZwDeleteKey(hLevel2Key); 1410 goto nextdevice; 1411 } 1412 1413 /* Add the list count (1st member of CM_RESOURCE_LIST) */ 1414 ListCount = 1; 1415 RtlCopyMemory(CmResourceList, 1416 &ListCount, 1417 sizeof(ULONG)); 1418 1419 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */ 1420 RtlCopyMemory(CmResourceList + sizeof(ULONG), 1421 BootResources, 1422 BootResourcesLength); 1423 1424 /* Save boot resources to 'LogConf\BootConfig' */ 1425 Status = ZwSetValueKey(hLogConf, &BootConfigU, 0, REG_RESOURCE_LIST, CmResourceList, BootResourcesLength + sizeof(ULONG)); 1426 if (!NT_SUCCESS(Status)) 1427 { 1428 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); 1429 ZwClose(hLogConf); 1430 ZwDeleteKey(hLevel2Key); 1431 goto nextdevice; 1432 } 1433 } 1434 ZwClose(hLogConf); 1435 1436 nextdevice: 1437 if (BootResources && BootResources != ParentBootResources) 1438 { 1439 ExFreePool(BootResources); 1440 BootResources = NULL; 1441 } 1442 if (hLevel2Key) 1443 { 1444 ZwClose(hLevel2Key); 1445 hLevel2Key = NULL; 1446 } 1447 if (hDeviceKey) 1448 { 1449 ZwClose(hDeviceKey); 1450 hDeviceKey = NULL; 1451 } 1452 } 1453 1454 Status = STATUS_SUCCESS; 1455 1456 cleanup: 1457 if (hDevicesKey && hDevicesKey != hBaseKey) 1458 ZwClose(hDevicesKey); 1459 if (hDeviceKey) 1460 ZwClose(hDeviceKey); 1461 if (pDeviceInformation) 1462 ExFreePool(pDeviceInformation); 1463 if (pValueInformation) 1464 ExFreePool(pValueInformation); 1465 return Status; 1466 } 1467 1468 static 1469 CODE_SEG("INIT") 1470 BOOLEAN 1471 IopIsFirmwareMapperDisabled(VOID) 1472 { 1473 UNICODE_STRING KeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CURRENTCONTROLSET\\Control\\Pnp"); 1474 UNICODE_STRING KeyNameU = RTL_CONSTANT_STRING(L"DisableFirmwareMapper"); 1475 OBJECT_ATTRIBUTES ObjectAttributes; 1476 HANDLE hPnpKey; 1477 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation; 1478 ULONG DesiredLength, Length; 1479 ULONG KeyValue = 0; 1480 NTSTATUS Status; 1481 1482 InitializeObjectAttributes(&ObjectAttributes, &KeyPathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); 1483 Status = ZwOpenKey(&hPnpKey, KEY_QUERY_VALUE, &ObjectAttributes); 1484 if (NT_SUCCESS(Status)) 1485 { 1486 Status = ZwQueryValueKey(hPnpKey, 1487 &KeyNameU, 1488 KeyValuePartialInformation, 1489 NULL, 1490 0, 1491 &DesiredLength); 1492 if ((Status == STATUS_BUFFER_TOO_SMALL) || 1493 (Status == STATUS_BUFFER_OVERFLOW)) 1494 { 1495 Length = DesiredLength; 1496 KeyInformation = ExAllocatePool(PagedPool, Length); 1497 if (KeyInformation) 1498 { 1499 Status = ZwQueryValueKey(hPnpKey, 1500 &KeyNameU, 1501 KeyValuePartialInformation, 1502 KeyInformation, 1503 Length, 1504 &DesiredLength); 1505 if (NT_SUCCESS(Status) && KeyInformation->DataLength == sizeof(ULONG)) 1506 { 1507 KeyValue = (ULONG)(*KeyInformation->Data); 1508 } 1509 else 1510 { 1511 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed\n", &KeyPathU, &KeyNameU); 1512 } 1513 1514 ExFreePool(KeyInformation); 1515 } 1516 else 1517 { 1518 DPRINT1("Failed to allocate memory for registry query\n"); 1519 } 1520 } 1521 else 1522 { 1523 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed with status 0x%08lx\n", &KeyPathU, &KeyNameU, Status); 1524 } 1525 1526 ZwClose(hPnpKey); 1527 } 1528 else 1529 { 1530 DPRINT1("ZwOpenKey(%wZ) failed with status 0x%08lx\n", &KeyPathU, Status); 1531 } 1532 1533 DPRINT("Firmware mapper is %s\n", KeyValue != 0 ? "disabled" : "enabled"); 1534 1535 return (KeyValue != 0) ? TRUE : FALSE; 1536 } 1537 1538 CODE_SEG("INIT") 1539 NTSTATUS 1540 NTAPI 1541 IopUpdateRootKey(VOID) 1542 { 1543 UNICODE_STRING EnumU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum"); 1544 UNICODE_STRING RootPathU = RTL_CONSTANT_STRING(L"Root"); 1545 UNICODE_STRING MultiKeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"); 1546 OBJECT_ATTRIBUTES ObjectAttributes; 1547 HANDLE hEnum, hRoot; 1548 NTSTATUS Status; 1549 1550 InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); 1551 Status = ZwCreateKey(&hEnum, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL); 1552 if (!NT_SUCCESS(Status)) 1553 { 1554 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status); 1555 return Status; 1556 } 1557 1558 InitializeObjectAttributes(&ObjectAttributes, &RootPathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hEnum, NULL); 1559 Status = ZwCreateKey(&hRoot, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL); 1560 ZwClose(hEnum); 1561 if (!NT_SUCCESS(Status)) 1562 { 1563 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status); 1564 return Status; 1565 } 1566 1567 if (!IopIsFirmwareMapperDisabled()) 1568 { 1569 Status = IopOpenRegistryKeyEx(&hEnum, NULL, &MultiKeyPathU, KEY_ENUMERATE_SUB_KEYS); 1570 if (!NT_SUCCESS(Status)) 1571 { 1572 /* Nothing to do, don't return with an error status */ 1573 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); 1574 ZwClose(hRoot); 1575 return STATUS_SUCCESS; 1576 } 1577 Status = IopEnumerateDetectedDevices( 1578 hEnum, 1579 NULL, 1580 hRoot, 1581 TRUE, 1582 NULL, 1583 0); 1584 ZwClose(hEnum); 1585 } 1586 else 1587 { 1588 /* Enumeration is disabled */ 1589 Status = STATUS_SUCCESS; 1590 } 1591 1592 ZwClose(hRoot); 1593 1594 return Status; 1595 } 1596 1597 NTSTATUS 1598 NTAPI 1599 IopOpenRegistryKeyEx(PHANDLE KeyHandle, 1600 HANDLE ParentKey, 1601 PUNICODE_STRING Name, 1602 ACCESS_MASK DesiredAccess) 1603 { 1604 OBJECT_ATTRIBUTES ObjectAttributes; 1605 NTSTATUS Status; 1606 1607 PAGED_CODE(); 1608 1609 *KeyHandle = NULL; 1610 1611 InitializeObjectAttributes(&ObjectAttributes, 1612 Name, 1613 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 1614 ParentKey, 1615 NULL); 1616 1617 Status = ZwOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes); 1618 1619 return Status; 1620 } 1621 1622 NTSTATUS 1623 NTAPI 1624 IopCreateRegistryKeyEx(OUT PHANDLE Handle, 1625 IN HANDLE RootHandle OPTIONAL, 1626 IN PUNICODE_STRING KeyName, 1627 IN ACCESS_MASK DesiredAccess, 1628 IN ULONG CreateOptions, 1629 OUT PULONG Disposition OPTIONAL) 1630 { 1631 OBJECT_ATTRIBUTES ObjectAttributes; 1632 ULONG KeyDisposition, RootHandleIndex = 0, i = 1, NestedCloseLevel = 0; 1633 USHORT Length; 1634 HANDLE HandleArray[2]; 1635 BOOLEAN Recursing = TRUE; 1636 PWCHAR pp, p, p1; 1637 UNICODE_STRING KeyString; 1638 NTSTATUS Status = STATUS_SUCCESS; 1639 PAGED_CODE(); 1640 1641 /* P1 is start, pp is end */ 1642 p1 = KeyName->Buffer; 1643 pp = (PVOID)((ULONG_PTR)p1 + KeyName->Length); 1644 1645 /* Create the target key */ 1646 InitializeObjectAttributes(&ObjectAttributes, 1647 KeyName, 1648 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 1649 RootHandle, 1650 NULL); 1651 Status = ZwCreateKey(&HandleArray[i], 1652 DesiredAccess, 1653 &ObjectAttributes, 1654 0, 1655 NULL, 1656 CreateOptions, 1657 &KeyDisposition); 1658 1659 /* Now we check if this failed */ 1660 if ((Status == STATUS_OBJECT_NAME_NOT_FOUND) && (RootHandle)) 1661 { 1662 /* Target key failed, so we'll need to create its parent. Setup array */ 1663 HandleArray[0] = NULL; 1664 HandleArray[1] = RootHandle; 1665 1666 /* Keep recursing for each missing parent */ 1667 while (Recursing) 1668 { 1669 /* And if we're deep enough, close the last handle */ 1670 if (NestedCloseLevel > 1) ZwClose(HandleArray[RootHandleIndex]); 1671 1672 /* We're setup to ping-pong between the two handle array entries */ 1673 RootHandleIndex = i; 1674 i = (i + 1) & 1; 1675 1676 /* Clear the one we're attempting to open now */ 1677 HandleArray[i] = NULL; 1678 1679 /* Process the parent key name */ 1680 for (p = p1; ((p < pp) && (*p != OBJ_NAME_PATH_SEPARATOR)); p++); 1681 Length = (USHORT)(p - p1) * sizeof(WCHAR); 1682 1683 /* Is there a parent name? */ 1684 if (Length) 1685 { 1686 /* Build the unicode string for it */ 1687 KeyString.Buffer = p1; 1688 KeyString.Length = KeyString.MaximumLength = Length; 1689 1690 /* Now try opening the parent */ 1691 InitializeObjectAttributes(&ObjectAttributes, 1692 &KeyString, 1693 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 1694 HandleArray[RootHandleIndex], 1695 NULL); 1696 Status = ZwCreateKey(&HandleArray[i], 1697 DesiredAccess, 1698 &ObjectAttributes, 1699 0, 1700 NULL, 1701 CreateOptions, 1702 &KeyDisposition); 1703 if (NT_SUCCESS(Status)) 1704 { 1705 /* It worked, we have one more handle */ 1706 NestedCloseLevel++; 1707 } 1708 else 1709 { 1710 /* Parent key creation failed, abandon loop */ 1711 Recursing = FALSE; 1712 continue; 1713 } 1714 } 1715 else 1716 { 1717 /* We don't have a parent name, probably corrupted key name */ 1718 Status = STATUS_INVALID_PARAMETER; 1719 Recursing = FALSE; 1720 continue; 1721 } 1722 1723 /* Now see if there's more parents to create */ 1724 p1 = p + 1; 1725 if ((p == pp) || (p1 == pp)) 1726 { 1727 /* We're done, hopefully successfully, so stop */ 1728 Recursing = FALSE; 1729 } 1730 } 1731 1732 /* Outer loop check for handle nesting that requires closing the top handle */ 1733 if (NestedCloseLevel > 1) ZwClose(HandleArray[RootHandleIndex]); 1734 } 1735 1736 /* Check if we broke out of the loop due to success */ 1737 if (NT_SUCCESS(Status)) 1738 { 1739 /* Return the target handle (we closed all the parent ones) and disposition */ 1740 *Handle = HandleArray[i]; 1741 if (Disposition) *Disposition = KeyDisposition; 1742 } 1743 1744 /* Return the success state */ 1745 return Status; 1746 } 1747 1748 NTSTATUS 1749 NTAPI 1750 IopGetRegistryValue(IN HANDLE Handle, 1751 IN PWSTR ValueName, 1752 OUT PKEY_VALUE_FULL_INFORMATION *Information) 1753 { 1754 UNICODE_STRING ValueString; 1755 NTSTATUS Status; 1756 PKEY_VALUE_FULL_INFORMATION FullInformation; 1757 ULONG Size; 1758 PAGED_CODE(); 1759 1760 RtlInitUnicodeString(&ValueString, ValueName); 1761 1762 Status = ZwQueryValueKey(Handle, 1763 &ValueString, 1764 KeyValueFullInformation, 1765 NULL, 1766 0, 1767 &Size); 1768 if ((Status != STATUS_BUFFER_OVERFLOW) && 1769 (Status != STATUS_BUFFER_TOO_SMALL)) 1770 { 1771 return Status; 1772 } 1773 1774 FullInformation = ExAllocatePool(NonPagedPool, Size); 1775 if (!FullInformation) return STATUS_INSUFFICIENT_RESOURCES; 1776 1777 Status = ZwQueryValueKey(Handle, 1778 &ValueString, 1779 KeyValueFullInformation, 1780 FullInformation, 1781 Size, 1782 &Size); 1783 if (!NT_SUCCESS(Status)) 1784 { 1785 ExFreePool(FullInformation); 1786 return Status; 1787 } 1788 1789 *Information = FullInformation; 1790 return STATUS_SUCCESS; 1791 } 1792 1793 RTL_GENERIC_COMPARE_RESULTS 1794 NTAPI 1795 PiCompareInstancePath(IN PRTL_AVL_TABLE Table, 1796 IN PVOID FirstStruct, 1797 IN PVOID SecondStruct) 1798 { 1799 /* FIXME: TODO */ 1800 ASSERT(FALSE); 1801 return 0; 1802 } 1803 1804 // 1805 // The allocation function is called by the generic table package whenever 1806 // it needs to allocate memory for the table. 1807 // 1808 1809 PVOID 1810 NTAPI 1811 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table, 1812 IN CLONG ByteSize) 1813 { 1814 /* FIXME: TODO */ 1815 ASSERT(FALSE); 1816 return NULL; 1817 } 1818 1819 VOID 1820 NTAPI 1821 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table, 1822 IN PVOID Buffer) 1823 { 1824 /* FIXME: TODO */ 1825 ASSERT(FALSE); 1826 } 1827 1828 VOID 1829 NTAPI 1830 PpInitializeDeviceReferenceTable(VOID) 1831 { 1832 /* Setup the guarded mutex and AVL table */ 1833 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock); 1834 RtlInitializeGenericTableAvl( 1835 &PpDeviceReferenceTable, 1836 (PRTL_AVL_COMPARE_ROUTINE)PiCompareInstancePath, 1837 (PRTL_AVL_ALLOCATE_ROUTINE)PiAllocateGenericTableEntry, 1838 (PRTL_AVL_FREE_ROUTINE)PiFreeGenericTableEntry, 1839 NULL); 1840 } 1841 1842 BOOLEAN 1843 NTAPI 1844 PiInitPhase0(VOID) 1845 { 1846 /* Initialize the resource when accessing device registry data */ 1847 ExInitializeResourceLite(&PpRegistryDeviceResource); 1848 1849 /* Setup the device reference AVL table */ 1850 PpInitializeDeviceReferenceTable(); 1851 return TRUE; 1852 } 1853 1854 BOOLEAN 1855 NTAPI 1856 PpInitSystem(VOID) 1857 { 1858 /* Check the initialization phase */ 1859 switch (ExpInitializationPhase) 1860 { 1861 case 0: 1862 1863 /* Do Phase 0 */ 1864 return PiInitPhase0(); 1865 1866 case 1: 1867 1868 /* Do Phase 1 */ 1869 return TRUE; 1870 //return PiInitPhase1(); 1871 1872 default: 1873 1874 /* Don't know any other phase! Bugcheck! */ 1875 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL); 1876 return FALSE; 1877 } 1878 } 1879 1880 /* PUBLIC FUNCTIONS **********************************************************/ 1881 1882 NTSTATUS 1883 NTAPI 1884 PnpBusTypeGuidGet(IN USHORT Index, 1885 IN LPGUID BusTypeGuid) 1886 { 1887 NTSTATUS Status = STATUS_SUCCESS; 1888 1889 /* Acquire the lock */ 1890 ExAcquireFastMutex(&PnpBusTypeGuidList->Lock); 1891 1892 /* Validate size */ 1893 if (Index < PnpBusTypeGuidList->GuidCount) 1894 { 1895 /* Copy the data */ 1896 RtlCopyMemory(BusTypeGuid, &PnpBusTypeGuidList->Guids[Index], sizeof(GUID)); 1897 } 1898 else 1899 { 1900 /* Failure path */ 1901 Status = STATUS_OBJECT_NAME_NOT_FOUND; 1902 } 1903 1904 /* Release lock and return status */ 1905 ExReleaseFastMutex(&PnpBusTypeGuidList->Lock); 1906 return Status; 1907 } 1908 1909 NTSTATUS 1910 NTAPI 1911 PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject, 1912 IN PHANDLE DeviceInstanceHandle, 1913 IN ACCESS_MASK DesiredAccess) 1914 { 1915 NTSTATUS Status; 1916 HANDLE KeyHandle; 1917 PDEVICE_NODE DeviceNode; 1918 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM"); 1919 PAGED_CODE(); 1920 1921 /* Open the enum key */ 1922 Status = IopOpenRegistryKeyEx(&KeyHandle, 1923 NULL, 1924 &KeyName, 1925 KEY_READ); 1926 if (!NT_SUCCESS(Status)) return Status; 1927 1928 /* Make sure we have an instance path */ 1929 DeviceNode = IopGetDeviceNode(DeviceObject); 1930 if ((DeviceNode) && (DeviceNode->InstancePath.Length)) 1931 { 1932 /* Get the instance key */ 1933 Status = IopOpenRegistryKeyEx(DeviceInstanceHandle, 1934 KeyHandle, 1935 &DeviceNode->InstancePath, 1936 DesiredAccess); 1937 } 1938 else 1939 { 1940 /* Fail */ 1941 Status = STATUS_INVALID_DEVICE_REQUEST; 1942 } 1943 1944 /* Close the handle and return status */ 1945 ZwClose(KeyHandle); 1946 return Status; 1947 } 1948 1949 ULONG 1950 NTAPI 1951 PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList) 1952 { 1953 ULONG FinalSize, PartialSize, EntrySize, i, j; 1954 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; 1955 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; 1956 1957 /* If we don't have one, that's easy */ 1958 if (!ResourceList) return 0; 1959 1960 /* Start with the minimum size possible */ 1961 FinalSize = FIELD_OFFSET(CM_RESOURCE_LIST, List); 1962 1963 /* Loop each full descriptor */ 1964 FullDescriptor = ResourceList->List; 1965 for (i = 0; i < ResourceList->Count; i++) 1966 { 1967 /* Start with the minimum size possible */ 1968 PartialSize = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) + 1969 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors); 1970 1971 /* Loop each partial descriptor */ 1972 PartialDescriptor = FullDescriptor->PartialResourceList.PartialDescriptors; 1973 for (j = 0; j < FullDescriptor->PartialResourceList.Count; j++) 1974 { 1975 /* Start with the minimum size possible */ 1976 EntrySize = sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 1977 1978 /* Check if there is extra data */ 1979 if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific) 1980 { 1981 /* Add that data */ 1982 EntrySize += PartialDescriptor->u.DeviceSpecificData.DataSize; 1983 } 1984 1985 /* The size of partial descriptors is bigger */ 1986 PartialSize += EntrySize; 1987 1988 /* Go to the next partial descriptor */ 1989 PartialDescriptor = (PVOID)((ULONG_PTR)PartialDescriptor + EntrySize); 1990 } 1991 1992 /* The size of full descriptors is bigger */ 1993 FinalSize += PartialSize; 1994 1995 /* Go to the next full descriptor */ 1996 FullDescriptor = (PVOID)((ULONG_PTR)FullDescriptor + PartialSize); 1997 } 1998 1999 /* Return the final size */ 2000 return FinalSize; 2001 } 2002 2003 NTSTATUS 2004 NTAPI 2005 PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject, 2006 IN ULONG ValueType, 2007 IN PWSTR ValueName, 2008 IN PWSTR KeyName, 2009 OUT PVOID Buffer, 2010 IN PULONG BufferLength) 2011 { 2012 NTSTATUS Status; 2013 HANDLE KeyHandle, SubHandle; 2014 UNICODE_STRING KeyString; 2015 PKEY_VALUE_FULL_INFORMATION KeyValueInfo = NULL; 2016 ULONG Length; 2017 PAGED_CODE(); 2018 2019 /* Find the instance key */ 2020 Status = PnpDeviceObjectToDeviceInstance(DeviceObject, &KeyHandle, KEY_READ); 2021 if (NT_SUCCESS(Status)) 2022 { 2023 /* Check for name given by caller */ 2024 if (KeyName) 2025 { 2026 /* Open this key */ 2027 RtlInitUnicodeString(&KeyString, KeyName); 2028 Status = IopOpenRegistryKeyEx(&SubHandle, 2029 KeyHandle, 2030 &KeyString, 2031 KEY_READ); 2032 if (NT_SUCCESS(Status)) 2033 { 2034 /* And use this handle instead */ 2035 ZwClose(KeyHandle); 2036 KeyHandle = SubHandle; 2037 } 2038 } 2039 2040 /* Check if sub-key handle succeeded (or no-op if no key name given) */ 2041 if (NT_SUCCESS(Status)) 2042 { 2043 /* Now get the size of the property */ 2044 Status = IopGetRegistryValue(KeyHandle, 2045 ValueName, 2046 &KeyValueInfo); 2047 } 2048 2049 /* Close the key */ 2050 ZwClose(KeyHandle); 2051 } 2052 2053 /* Fail if any of the registry operations failed */ 2054 if (!NT_SUCCESS(Status)) return Status; 2055 2056 /* Check how much data we have to copy */ 2057 Length = KeyValueInfo->DataLength; 2058 if (*BufferLength >= Length) 2059 { 2060 /* Check for a match in the value type */ 2061 if (KeyValueInfo->Type == ValueType) 2062 { 2063 /* Copy the data */ 2064 RtlCopyMemory(Buffer, 2065 (PVOID)((ULONG_PTR)KeyValueInfo + 2066 KeyValueInfo->DataOffset), 2067 Length); 2068 } 2069 else 2070 { 2071 /* Invalid registry property type, fail */ 2072 Status = STATUS_INVALID_PARAMETER_2; 2073 } 2074 } 2075 else 2076 { 2077 /* Buffer is too small to hold data */ 2078 Status = STATUS_BUFFER_TOO_SMALL; 2079 } 2080 2081 /* Return the required buffer length, free the buffer, and return status */ 2082 *BufferLength = Length; 2083 ExFreePool(KeyValueInfo); 2084 return Status; 2085 } 2086 2087 #define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;} 2088 #define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;} 2089 #define PIP_UNIMPLEMENTED() {UNIMPLEMENTED_DBGBREAK(); break;} 2090 2091 /* 2092 * @implemented 2093 */ 2094 NTSTATUS 2095 NTAPI 2096 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, 2097 IN DEVICE_REGISTRY_PROPERTY DeviceProperty, 2098 IN ULONG BufferLength, 2099 OUT PVOID PropertyBuffer, 2100 OUT PULONG ResultLength) 2101 { 2102 PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject); 2103 DEVICE_CAPABILITIES DeviceCaps; 2104 ULONG ReturnLength = 0, Length = 0, ValueType; 2105 PWCHAR ValueName = NULL, EnumeratorNameEnd, DeviceInstanceName; 2106 PVOID Data = NULL; 2107 NTSTATUS Status = STATUS_BUFFER_TOO_SMALL; 2108 GUID BusTypeGuid; 2109 POBJECT_NAME_INFORMATION ObjectNameInfo = NULL; 2110 BOOLEAN NullTerminate = FALSE; 2111 DEVICE_REMOVAL_POLICY Policy; 2112 2113 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject, DeviceProperty); 2114 2115 /* Assume failure */ 2116 *ResultLength = 0; 2117 2118 /* Only PDOs can call this */ 2119 if (!DeviceNode) return STATUS_INVALID_DEVICE_REQUEST; 2120 2121 /* Handle all properties */ 2122 switch (DeviceProperty) 2123 { 2124 case DevicePropertyBusTypeGuid: 2125 2126 /* Get the GUID from the internal cache */ 2127 Status = PnpBusTypeGuidGet(DeviceNode->ChildBusTypeIndex, &BusTypeGuid); 2128 if (!NT_SUCCESS(Status)) return Status; 2129 2130 /* This is the format of the returned data */ 2131 PIP_RETURN_DATA(sizeof(GUID), &BusTypeGuid); 2132 2133 case DevicePropertyLegacyBusType: 2134 2135 /* Validate correct interface type */ 2136 if (DeviceNode->ChildInterfaceType == InterfaceTypeUndefined) 2137 return STATUS_OBJECT_NAME_NOT_FOUND; 2138 2139 /* This is the format of the returned data */ 2140 PIP_RETURN_DATA(sizeof(INTERFACE_TYPE), &DeviceNode->ChildInterfaceType); 2141 2142 case DevicePropertyBusNumber: 2143 2144 /* Validate correct bus number */ 2145 if ((DeviceNode->ChildBusNumber & 0x80000000) == 0x80000000) 2146 return STATUS_OBJECT_NAME_NOT_FOUND; 2147 2148 /* This is the format of the returned data */ 2149 PIP_RETURN_DATA(sizeof(ULONG), &DeviceNode->ChildBusNumber); 2150 2151 case DevicePropertyEnumeratorName: 2152 2153 /* Get the instance path */ 2154 DeviceInstanceName = DeviceNode->InstancePath.Buffer; 2155 2156 /* Sanity checks */ 2157 ASSERT((BufferLength & 1) == 0); 2158 ASSERT(DeviceInstanceName != NULL); 2159 2160 /* Get the name from the path */ 2161 EnumeratorNameEnd = wcschr(DeviceInstanceName, OBJ_NAME_PATH_SEPARATOR); 2162 ASSERT(EnumeratorNameEnd); 2163 2164 /* This string needs to be NULL-terminated */ 2165 NullTerminate = TRUE; 2166 2167 /* This is the format of the returned data */ 2168 PIP_RETURN_DATA((ULONG)(EnumeratorNameEnd - DeviceInstanceName) * sizeof(WCHAR), 2169 DeviceInstanceName); 2170 2171 case DevicePropertyAddress: 2172 2173 /* Query the device caps */ 2174 Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCaps); 2175 if (!NT_SUCCESS(Status) || (DeviceCaps.Address == MAXULONG)) 2176 return STATUS_OBJECT_NAME_NOT_FOUND; 2177 2178 /* This is the format of the returned data */ 2179 PIP_RETURN_DATA(sizeof(ULONG), &DeviceCaps.Address); 2180 2181 case DevicePropertyBootConfigurationTranslated: 2182 2183 /* Validate we have resources */ 2184 if (!DeviceNode->BootResources) 2185 // if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field 2186 { 2187 /* No resources will still fake success, but with 0 bytes */ 2188 *ResultLength = 0; 2189 return STATUS_SUCCESS; 2190 } 2191 2192 /* This is the format of the returned data */ 2193 PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode->BootResources), // FIXFIX: Should use BootResourcesTranslated 2194 DeviceNode->BootResources); // FIXFIX: Should use BootResourcesTranslated 2195 2196 case DevicePropertyPhysicalDeviceObjectName: 2197 2198 /* Sanity check for Unicode-sized string */ 2199 ASSERT((BufferLength & 1) == 0); 2200 2201 /* Allocate name buffer */ 2202 Length = BufferLength + sizeof(OBJECT_NAME_INFORMATION); 2203 ObjectNameInfo = ExAllocatePool(PagedPool, Length); 2204 if (!ObjectNameInfo) return STATUS_INSUFFICIENT_RESOURCES; 2205 2206 /* Query the PDO name */ 2207 Status = ObQueryNameString(DeviceObject, 2208 ObjectNameInfo, 2209 Length, 2210 ResultLength); 2211 if (Status == STATUS_INFO_LENGTH_MISMATCH) 2212 { 2213 /* It's up to the caller to try again */ 2214 Status = STATUS_BUFFER_TOO_SMALL; 2215 } 2216 2217 /* This string needs to be NULL-terminated */ 2218 NullTerminate = TRUE; 2219 2220 /* Return if successful */ 2221 if (NT_SUCCESS(Status)) PIP_RETURN_DATA(ObjectNameInfo->Name.Length, 2222 ObjectNameInfo->Name.Buffer); 2223 2224 /* Let the caller know how big the name is */ 2225 *ResultLength -= sizeof(OBJECT_NAME_INFORMATION); 2226 break; 2227 2228 case DevicePropertyRemovalPolicy: 2229 2230 Policy = DeviceNode->RemovalPolicy; 2231 PIP_RETURN_DATA(sizeof(Policy), &Policy); 2232 2233 /* Handle the registry-based properties */ 2234 case DevicePropertyUINumber: 2235 PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER, REG_DWORD); 2236 case DevicePropertyLocationInformation: 2237 PIP_REGISTRY_DATA(REGSTR_VAL_LOCATION_INFORMATION, REG_SZ); 2238 case DevicePropertyDeviceDescription: 2239 PIP_REGISTRY_DATA(REGSTR_VAL_DEVDESC, REG_SZ); 2240 case DevicePropertyHardwareID: 2241 PIP_REGISTRY_DATA(REGSTR_VAL_HARDWAREID, REG_MULTI_SZ); 2242 case DevicePropertyCompatibleIDs: 2243 PIP_REGISTRY_DATA(REGSTR_VAL_COMPATIBLEIDS, REG_MULTI_SZ); 2244 case DevicePropertyBootConfiguration: 2245 PIP_REGISTRY_DATA(REGSTR_VAL_BOOTCONFIG, REG_RESOURCE_LIST); 2246 case DevicePropertyClassName: 2247 PIP_REGISTRY_DATA(REGSTR_VAL_CLASS, REG_SZ); 2248 case DevicePropertyClassGuid: 2249 PIP_REGISTRY_DATA(REGSTR_VAL_CLASSGUID, REG_SZ); 2250 case DevicePropertyDriverKeyName: 2251 PIP_REGISTRY_DATA(REGSTR_VAL_DRIVER, REG_SZ); 2252 case DevicePropertyManufacturer: 2253 PIP_REGISTRY_DATA(REGSTR_VAL_MFG, REG_SZ); 2254 case DevicePropertyFriendlyName: 2255 PIP_REGISTRY_DATA(REGSTR_VAL_FRIENDLYNAME, REG_SZ); 2256 case DevicePropertyContainerID: 2257 //PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7 2258 PIP_UNIMPLEMENTED(); 2259 break; 2260 case DevicePropertyInstallState: 2261 PIP_REGISTRY_DATA(REGSTR_VAL_CONFIGFLAGS, REG_DWORD); 2262 break; 2263 case DevicePropertyResourceRequirements: 2264 PIP_UNIMPLEMENTED(); 2265 case DevicePropertyAllocatedResources: 2266 PIP_UNIMPLEMENTED(); 2267 default: 2268 return STATUS_INVALID_PARAMETER_2; 2269 } 2270 2271 /* Having a registry value name implies registry data */ 2272 if (ValueName) 2273 { 2274 /* We know up-front how much data to expect */ 2275 *ResultLength = BufferLength; 2276 2277 /* Go get the data, use the LogConf subkey if necessary */ 2278 Status = PiGetDeviceRegistryProperty(DeviceObject, 2279 ValueType, 2280 ValueName, 2281 (DeviceProperty == 2282 DevicePropertyBootConfiguration) ? 2283 L"LogConf": NULL, 2284 PropertyBuffer, 2285 ResultLength); 2286 } 2287 else if (NT_SUCCESS(Status)) 2288 { 2289 /* We know up-front how much data to expect, check the caller's buffer */ 2290 *ResultLength = ReturnLength + (NullTerminate ? sizeof(UNICODE_NULL) : 0); 2291 if (*ResultLength <= BufferLength) 2292 { 2293 /* Buffer is all good, copy the data */ 2294 RtlCopyMemory(PropertyBuffer, Data, ReturnLength); 2295 2296 /* Check if we need to NULL-terminate the string */ 2297 if (NullTerminate) 2298 { 2299 /* Terminate the string */ 2300 ((PWCHAR)PropertyBuffer)[ReturnLength / sizeof(WCHAR)] = UNICODE_NULL; 2301 } 2302 2303 /* This is the success path */ 2304 Status = STATUS_SUCCESS; 2305 } 2306 else 2307 { 2308 /* Failure path */ 2309 Status = STATUS_BUFFER_TOO_SMALL; 2310 } 2311 } 2312 2313 /* Free any allocation we may have made, and return the status code */ 2314 if (ObjectNameInfo) ExFreePool(ObjectNameInfo); 2315 return Status; 2316 } 2317 2318 /** 2319 * @name IoOpenDeviceRegistryKey 2320 * 2321 * Open a registry key unique for a specified driver or device instance. 2322 * 2323 * @param DeviceObject Device to get the registry key for. 2324 * @param DevInstKeyType Type of the key to return. 2325 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE). 2326 * @param DevInstRegKey Handle to the opened registry key on 2327 * successful return. 2328 * 2329 * @return Status. 2330 * 2331 * @implemented 2332 */ 2333 NTSTATUS 2334 NTAPI 2335 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject, 2336 IN ULONG DevInstKeyType, 2337 IN ACCESS_MASK DesiredAccess, 2338 OUT PHANDLE DevInstRegKey) 2339 { 2340 static WCHAR RootKeyName[] = 2341 L"\\Registry\\Machine\\System\\CurrentControlSet\\"; 2342 static WCHAR ProfileKeyName[] = 2343 L"Hardware Profiles\\Current\\System\\CurrentControlSet\\"; 2344 static WCHAR ClassKeyName[] = L"Control\\Class\\"; 2345 static WCHAR EnumKeyName[] = L"Enum\\"; 2346 static WCHAR DeviceParametersKeyName[] = L"Device Parameters"; 2347 ULONG KeyNameLength; 2348 PWSTR KeyNameBuffer; 2349 UNICODE_STRING KeyName; 2350 ULONG DriverKeyLength; 2351 OBJECT_ATTRIBUTES ObjectAttributes; 2352 PDEVICE_NODE DeviceNode = NULL; 2353 NTSTATUS Status; 2354 2355 DPRINT("IoOpenDeviceRegistryKey() called\n"); 2356 2357 if ((DevInstKeyType & (PLUGPLAY_REGKEY_DEVICE | PLUGPLAY_REGKEY_DRIVER)) == 0) 2358 { 2359 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n"); 2360 return STATUS_INVALID_PARAMETER; 2361 } 2362 2363 if (!IopIsValidPhysicalDeviceObject(DeviceObject)) 2364 return STATUS_INVALID_DEVICE_REQUEST; 2365 DeviceNode = IopGetDeviceNode(DeviceObject); 2366 2367 /* 2368 * Calculate the length of the base key name. This is the full 2369 * name for driver key or the name excluding "Device Parameters" 2370 * subkey for device key. 2371 */ 2372 2373 KeyNameLength = sizeof(RootKeyName); 2374 if (DevInstKeyType & PLUGPLAY_REGKEY_CURRENT_HWPROFILE) 2375 KeyNameLength += sizeof(ProfileKeyName) - sizeof(UNICODE_NULL); 2376 if (DevInstKeyType & PLUGPLAY_REGKEY_DRIVER) 2377 { 2378 KeyNameLength += sizeof(ClassKeyName) - sizeof(UNICODE_NULL); 2379 Status = IoGetDeviceProperty(DeviceObject, DevicePropertyDriverKeyName, 2380 0, NULL, &DriverKeyLength); 2381 if (Status != STATUS_BUFFER_TOO_SMALL) 2382 return Status; 2383 KeyNameLength += DriverKeyLength; 2384 } 2385 else 2386 { 2387 KeyNameLength += sizeof(EnumKeyName) - sizeof(UNICODE_NULL) + 2388 DeviceNode->InstancePath.Length; 2389 } 2390 2391 /* 2392 * Now allocate the buffer for the key name... 2393 */ 2394 2395 KeyNameBuffer = ExAllocatePool(PagedPool, KeyNameLength); 2396 if (KeyNameBuffer == NULL) 2397 return STATUS_INSUFFICIENT_RESOURCES; 2398 2399 KeyName.Length = 0; 2400 KeyName.MaximumLength = (USHORT)KeyNameLength; 2401 KeyName.Buffer = KeyNameBuffer; 2402 2403 /* 2404 * ...and build the key name. 2405 */ 2406 2407 KeyName.Length += sizeof(RootKeyName) - sizeof(UNICODE_NULL); 2408 RtlCopyMemory(KeyNameBuffer, RootKeyName, KeyName.Length); 2409 2410 if (DevInstKeyType & PLUGPLAY_REGKEY_CURRENT_HWPROFILE) 2411 RtlAppendUnicodeToString(&KeyName, ProfileKeyName); 2412 2413 if (DevInstKeyType & PLUGPLAY_REGKEY_DRIVER) 2414 { 2415 RtlAppendUnicodeToString(&KeyName, ClassKeyName); 2416 Status = IoGetDeviceProperty(DeviceObject, DevicePropertyDriverKeyName, 2417 DriverKeyLength, KeyNameBuffer + 2418 (KeyName.Length / sizeof(WCHAR)), 2419 &DriverKeyLength); 2420 if (!NT_SUCCESS(Status)) 2421 { 2422 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status); 2423 ExFreePool(KeyNameBuffer); 2424 return Status; 2425 } 2426 KeyName.Length += (USHORT)DriverKeyLength - sizeof(UNICODE_NULL); 2427 } 2428 else 2429 { 2430 RtlAppendUnicodeToString(&KeyName, EnumKeyName); 2431 Status = RtlAppendUnicodeStringToString(&KeyName, &DeviceNode->InstancePath); 2432 if (DeviceNode->InstancePath.Length == 0) 2433 { 2434 ExFreePool(KeyNameBuffer); 2435 return Status; 2436 } 2437 } 2438 2439 /* 2440 * Open the base key. 2441 */ 2442 Status = IopOpenRegistryKeyEx(DevInstRegKey, NULL, &KeyName, DesiredAccess); 2443 if (!NT_SUCCESS(Status)) 2444 { 2445 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName, Status); 2446 ExFreePool(KeyNameBuffer); 2447 return Status; 2448 } 2449 ExFreePool(KeyNameBuffer); 2450 2451 /* 2452 * For driver key we're done now. 2453 */ 2454 2455 if (DevInstKeyType & PLUGPLAY_REGKEY_DRIVER) 2456 return Status; 2457 2458 /* 2459 * Let's go further. For device key we must open "Device Parameters" 2460 * subkey and create it if it doesn't exist yet. 2461 */ 2462 2463 RtlInitUnicodeString(&KeyName, DeviceParametersKeyName); 2464 InitializeObjectAttributes(&ObjectAttributes, 2465 &KeyName, 2466 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 2467 *DevInstRegKey, 2468 NULL); 2469 Status = ZwCreateKey(DevInstRegKey, 2470 DesiredAccess, 2471 &ObjectAttributes, 2472 0, 2473 NULL, 2474 REG_OPTION_NON_VOLATILE, 2475 NULL); 2476 ZwClose(ObjectAttributes.RootDirectory); 2477 2478 return Status; 2479 } 2480 2481 /* 2482 * @implemented 2483 */ 2484 VOID 2485 NTAPI 2486 IoInvalidateDeviceRelations( 2487 IN PDEVICE_OBJECT DeviceObject, 2488 IN DEVICE_RELATION_TYPE Type) 2489 { 2490 if (!IopIsValidPhysicalDeviceObject(DeviceObject)) 2491 { 2492 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG_PTR)DeviceObject, 0, 0); 2493 } 2494 2495 switch (Type) 2496 { 2497 case BusRelations: 2498 /* Enumerate the device */ 2499 PiQueueDeviceAction(DeviceObject, PiActionEnumDeviceTree, NULL, NULL); 2500 break; 2501 default: 2502 /* Everything else is not implemented */ 2503 break; 2504 } 2505 } 2506 2507 /* 2508 * @implemented 2509 */ 2510 NTSTATUS 2511 NTAPI 2512 IoSynchronousInvalidateDeviceRelations( 2513 IN PDEVICE_OBJECT DeviceObject, 2514 IN DEVICE_RELATION_TYPE Type) 2515 { 2516 PAGED_CODE(); 2517 2518 if (!IopIsValidPhysicalDeviceObject(DeviceObject)) 2519 { 2520 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG_PTR)DeviceObject, 0, 0); 2521 } 2522 2523 switch (Type) 2524 { 2525 case BusRelations: 2526 /* Enumerate the device */ 2527 return PiPerformSyncDeviceAction(DeviceObject, PiActionEnumDeviceTree); 2528 case PowerRelations: 2529 /* Not handled yet */ 2530 return STATUS_NOT_IMPLEMENTED; 2531 case TargetDeviceRelation: 2532 /* Nothing to do */ 2533 return STATUS_SUCCESS; 2534 default: 2535 /* Ejection relations are not supported */ 2536 return STATUS_NOT_SUPPORTED; 2537 } 2538 } 2539 2540 /* 2541 * @implemented 2542 */ 2543 BOOLEAN 2544 NTAPI 2545 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType, 2546 IN ULONG BusNumber, 2547 IN PHYSICAL_ADDRESS BusAddress, 2548 IN OUT PULONG AddressSpace, 2549 OUT PPHYSICAL_ADDRESS TranslatedAddress) 2550 { 2551 /* FIXME: Notify the resource arbiter */ 2552 2553 return HalTranslateBusAddress(InterfaceType, 2554 BusNumber, 2555 BusAddress, 2556 AddressSpace, 2557 TranslatedAddress); 2558 } 2559