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