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)
10 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 PDEVICE_NODE IopRootDeviceNode
;
19 KSPIN_LOCK IopDeviceTreeLock
;
20 ERESOURCE PpRegistryDeviceResource
;
21 KGUARDED_MUTEX PpDeviceReferenceTableLock
;
22 RTL_AVL_TABLE PpDeviceReferenceTable
;
24 extern ERESOURCE IopDriverLoadResource
;
25 extern ULONG ExpInitializationPhase
;
26 extern BOOLEAN ExpInTextModeSetup
;
27 extern BOOLEAN PnpSystemInit
;
29 #define MAX_DEVICE_ID_LEN 200
30 #define MAX_SEPARATORS_INSTANCEID 0
31 #define MAX_SEPARATORS_DEVICEID 1
33 /* DATA **********************************************************************/
35 PDRIVER_OBJECT IopRootDriverObject
;
36 PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList
= NULL
;
37 LIST_ENTRY IopDeviceActionRequestList
;
38 WORK_QUEUE_ITEM IopDeviceActionWorkItem
;
39 BOOLEAN IopDeviceActionInProgress
;
40 KSPIN_LOCK IopDeviceActionLock
;
42 typedef struct _DEVICE_ACTION_DATA
44 LIST_ENTRY RequestListEntry
;
45 PDEVICE_OBJECT DeviceObject
;
46 DEVICE_RELATION_TYPE Type
;
47 } DEVICE_ACTION_DATA
, *PDEVICE_ACTION_DATA
;
49 /* FUNCTIONS *****************************************************************/
52 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
53 IN ULONG CreateOptions
,
57 IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
);
60 IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
, BOOLEAN Force
);
63 IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance
);
67 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
69 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
73 IopFixupDeviceId(PWCHAR String
)
75 SIZE_T Length
= wcslen(String
), i
;
77 for (i
= 0; i
< Length
; i
++)
79 if (String
[i
] == L
'\\')
86 IopInstallCriticalDevice(PDEVICE_NODE DeviceNode
)
89 HANDLE CriticalDeviceKey
, InstanceKey
;
90 OBJECT_ATTRIBUTES ObjectAttributes
;
91 UNICODE_STRING CriticalDeviceKeyU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\CriticalDeviceDatabase");
92 UNICODE_STRING CompatibleIdU
= RTL_CONSTANT_STRING(L
"CompatibleIDs");
93 UNICODE_STRING HardwareIdU
= RTL_CONSTANT_STRING(L
"HardwareID");
94 UNICODE_STRING ServiceU
= RTL_CONSTANT_STRING(L
"Service");
95 UNICODE_STRING ClassGuidU
= RTL_CONSTANT_STRING(L
"ClassGUID");
96 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
97 ULONG HidLength
= 0, CidLength
= 0, BufferLength
;
98 PWCHAR IdBuffer
, OriginalIdBuffer
;
100 /* Open the device instance key */
101 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, REG_OPTION_NON_VOLATILE
, &InstanceKey
);
102 if (Status
!= STATUS_SUCCESS
)
105 Status
= ZwQueryValueKey(InstanceKey
,
107 KeyValuePartialInformation
,
111 if (Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_BUFFER_TOO_SMALL
)
113 ZwClose(InstanceKey
);
117 Status
= ZwQueryValueKey(InstanceKey
,
119 KeyValuePartialInformation
,
123 if (Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_BUFFER_TOO_SMALL
)
128 BufferLength
= HidLength
+ CidLength
;
129 BufferLength
-= (((CidLength
!= 0) ? 2 : 1) * FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
));
131 /* Allocate a buffer to hold data from both */
132 OriginalIdBuffer
= IdBuffer
= ExAllocatePool(PagedPool
, BufferLength
);
135 ZwClose(InstanceKey
);
139 /* Compute the buffer size */
140 if (HidLength
> CidLength
)
141 BufferLength
= HidLength
;
143 BufferLength
= CidLength
;
145 PartialInfo
= ExAllocatePool(PagedPool
, BufferLength
);
148 ZwClose(InstanceKey
);
149 ExFreePool(OriginalIdBuffer
);
153 Status
= ZwQueryValueKey(InstanceKey
,
155 KeyValuePartialInformation
,
159 if (Status
!= STATUS_SUCCESS
)
161 ExFreePool(PartialInfo
);
162 ExFreePool(OriginalIdBuffer
);
163 ZwClose(InstanceKey
);
167 /* Copy in HID info first (without 2nd terminating NULL if CID is present) */
168 HidLength
= PartialInfo
->DataLength
- ((CidLength
!= 0) ? sizeof(WCHAR
) : 0);
169 RtlCopyMemory(IdBuffer
, PartialInfo
->Data
, HidLength
);
173 Status
= ZwQueryValueKey(InstanceKey
,
175 KeyValuePartialInformation
,
179 if (Status
!= STATUS_SUCCESS
)
181 ExFreePool(PartialInfo
);
182 ExFreePool(OriginalIdBuffer
);
183 ZwClose(InstanceKey
);
188 CidLength
= PartialInfo
->DataLength
;
189 RtlCopyMemory(((PUCHAR
)IdBuffer
) + HidLength
, PartialInfo
->Data
, CidLength
);
192 /* Free our temp buffer */
193 ExFreePool(PartialInfo
);
195 InitializeObjectAttributes(&ObjectAttributes
,
197 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
200 Status
= ZwOpenKey(&CriticalDeviceKey
,
201 KEY_ENUMERATE_SUB_KEYS
,
203 if (!NT_SUCCESS(Status
))
205 /* The critical device database doesn't exist because
206 * we're probably in 1st stage setup, but it's ok */
207 ExFreePool(OriginalIdBuffer
);
208 ZwClose(InstanceKey
);
214 USHORT StringLength
= (USHORT
)wcslen(IdBuffer
) + 1, Index
;
216 IopFixupDeviceId(IdBuffer
);
218 /* Look through all subkeys for a match */
219 for (Index
= 0; TRUE
; Index
++)
222 PKEY_BASIC_INFORMATION BasicInfo
;
224 Status
= ZwEnumerateKey(CriticalDeviceKey
,
230 if (Status
== STATUS_NO_MORE_ENTRIES
)
232 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
234 UNICODE_STRING ChildIdNameU
, RegKeyNameU
;
236 BasicInfo
= ExAllocatePool(PagedPool
, NeededLength
);
240 ExFreePool(OriginalIdBuffer
);
241 ZwClose(CriticalDeviceKey
);
242 ZwClose(InstanceKey
);
246 Status
= ZwEnumerateKey(CriticalDeviceKey
,
252 if (Status
!= STATUS_SUCCESS
)
254 /* This shouldn't happen */
255 ExFreePool(BasicInfo
);
259 ChildIdNameU
.Buffer
= IdBuffer
;
260 ChildIdNameU
.MaximumLength
= ChildIdNameU
.Length
= (StringLength
- 1) * sizeof(WCHAR
);
261 RegKeyNameU
.Buffer
= BasicInfo
->Name
;
262 RegKeyNameU
.MaximumLength
= RegKeyNameU
.Length
= (USHORT
)BasicInfo
->NameLength
;
264 if (RtlEqualUnicodeString(&ChildIdNameU
, &RegKeyNameU
, TRUE
))
266 HANDLE ChildKeyHandle
;
268 InitializeObjectAttributes(&ObjectAttributes
,
270 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
274 Status
= ZwOpenKey(&ChildKeyHandle
,
277 if (Status
!= STATUS_SUCCESS
)
279 ExFreePool(BasicInfo
);
283 /* Check if there's already a driver installed */
284 Status
= ZwQueryValueKey(InstanceKey
,
286 KeyValuePartialInformation
,
290 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
292 ExFreePool(BasicInfo
);
296 Status
= ZwQueryValueKey(ChildKeyHandle
,
298 KeyValuePartialInformation
,
302 if (Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_BUFFER_TOO_SMALL
)
304 ExFreePool(BasicInfo
);
308 PartialInfo
= ExAllocatePool(PagedPool
, NeededLength
);
311 ExFreePool(OriginalIdBuffer
);
312 ExFreePool(BasicInfo
);
313 ZwClose(InstanceKey
);
314 ZwClose(ChildKeyHandle
);
315 ZwClose(CriticalDeviceKey
);
319 /* Read ClassGUID entry in the CDDB */
320 Status
= ZwQueryValueKey(ChildKeyHandle
,
322 KeyValuePartialInformation
,
326 if (Status
!= STATUS_SUCCESS
)
328 ExFreePool(BasicInfo
);
332 /* Write it to the ENUM key */
333 Status
= ZwSetValueKey(InstanceKey
,
338 PartialInfo
->DataLength
);
339 if (Status
!= STATUS_SUCCESS
)
341 ExFreePool(BasicInfo
);
342 ExFreePool(PartialInfo
);
343 ZwClose(ChildKeyHandle
);
347 Status
= ZwQueryValueKey(ChildKeyHandle
,
349 KeyValuePartialInformation
,
353 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
355 ExFreePool(PartialInfo
);
356 PartialInfo
= ExAllocatePool(PagedPool
, NeededLength
);
359 ExFreePool(OriginalIdBuffer
);
360 ExFreePool(BasicInfo
);
361 ZwClose(InstanceKey
);
362 ZwClose(ChildKeyHandle
);
363 ZwClose(CriticalDeviceKey
);
367 /* Read the service entry from the CDDB */
368 Status
= ZwQueryValueKey(ChildKeyHandle
,
370 KeyValuePartialInformation
,
374 if (Status
!= STATUS_SUCCESS
)
376 ExFreePool(BasicInfo
);
377 ExFreePool(PartialInfo
);
378 ZwClose(ChildKeyHandle
);
382 /* Write it to the ENUM key */
383 Status
= ZwSetValueKey(InstanceKey
,
388 PartialInfo
->DataLength
);
389 if (Status
!= STATUS_SUCCESS
)
391 ExFreePool(BasicInfo
);
392 ExFreePool(PartialInfo
);
393 ZwClose(ChildKeyHandle
);
397 DPRINT("Installed service '%S' for critical device '%wZ'\n", PartialInfo
->Data
, &ChildIdNameU
);
401 DPRINT1("Installed NULL service for critical device '%wZ'\n", &ChildIdNameU
);
404 ExFreePool(OriginalIdBuffer
);
405 ExFreePool(PartialInfo
);
406 ExFreePool(BasicInfo
);
407 ZwClose(InstanceKey
);
408 ZwClose(ChildKeyHandle
);
409 ZwClose(CriticalDeviceKey
);
415 ExFreePool(BasicInfo
);
419 /* Umm, not sure what happened here */
424 /* Advance to the next ID */
425 IdBuffer
+= StringLength
;
428 ExFreePool(OriginalIdBuffer
);
429 ZwClose(InstanceKey
);
430 ZwClose(CriticalDeviceKey
);
435 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
436 PDRIVER_OBJECT DriverObject
)
443 /* Special case for bus driven devices */
444 DeviceNode
->Flags
|= DNF_ADDED
;
445 return STATUS_SUCCESS
;
448 if (!DriverObject
->DriverExtension
->AddDevice
)
450 DeviceNode
->Flags
|= DNF_LEGACY_DRIVER
;
453 if (DeviceNode
->Flags
& DNF_LEGACY_DRIVER
)
455 DeviceNode
->Flags
|= (DNF_ADDED
| DNF_STARTED
);
456 return STATUS_SUCCESS
;
459 /* This is a Plug and Play driver */
460 DPRINT("Plug and Play driver found\n");
461 ASSERT(DeviceNode
->PhysicalDeviceObject
);
463 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
464 &DriverObject
->DriverName
,
465 &DeviceNode
->InstancePath
);
466 Status
= DriverObject
->DriverExtension
->AddDevice(DriverObject
,
467 DeviceNode
->PhysicalDeviceObject
);
468 if (!NT_SUCCESS(Status
))
470 DPRINT1("%wZ->AddDevice(%wZ) failed with status 0x%x\n",
471 &DriverObject
->DriverName
,
472 &DeviceNode
->InstancePath
,
474 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
475 DeviceNode
->Problem
= CM_PROB_FAILED_ADD
;
479 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
481 /* Check if we have a ACPI device (needed for power management) */
482 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
484 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
486 /* There can be only one system power device */
487 if (!SystemPowerDeviceNodeCreated
)
489 PopSystemPowerDeviceNode
= DeviceNode
;
490 ObReferenceObject(PopSystemPowerDeviceNode
->PhysicalDeviceObject
);
491 SystemPowerDeviceNodeCreated
= TRUE
;
495 ObDereferenceObject(Fdo
);
497 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
499 return STATUS_SUCCESS
;
505 IopSendEject(IN PDEVICE_OBJECT DeviceObject
)
507 IO_STACK_LOCATION Stack
;
510 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
511 Stack
.MajorFunction
= IRP_MJ_PNP
;
512 Stack
.MinorFunction
= IRP_MN_EJECT
;
514 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
520 IopSendSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject
)
522 IO_STACK_LOCATION Stack
;
525 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
526 Stack
.MajorFunction
= IRP_MJ_PNP
;
527 Stack
.MinorFunction
= IRP_MN_SURPRISE_REMOVAL
;
529 /* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
530 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
536 IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
538 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
539 IO_STACK_LOCATION Stack
;
545 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING
,
546 &DeviceNode
->InstancePath
);
548 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
549 Stack
.MajorFunction
= IRP_MJ_PNP
;
550 Stack
.MinorFunction
= IRP_MN_QUERY_REMOVE_DEVICE
;
552 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
554 IopNotifyPlugPlayNotification(DeviceObject
,
555 EventCategoryTargetDeviceChange
,
556 &GUID_TARGET_DEVICE_QUERY_REMOVE
,
560 if (!NT_SUCCESS(Status
))
562 DPRINT1("Removal vetoed by %wZ\n", &DeviceNode
->InstancePath
);
563 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED
,
564 &DeviceNode
->InstancePath
);
573 IopQueryStopDevice(IN PDEVICE_OBJECT DeviceObject
)
575 IO_STACK_LOCATION Stack
;
578 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
579 Stack
.MajorFunction
= IRP_MJ_PNP
;
580 Stack
.MinorFunction
= IRP_MN_QUERY_STOP_DEVICE
;
582 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
588 IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
590 IO_STACK_LOCATION Stack
;
592 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
594 /* Drop all our state for this device in case it isn't really going away */
595 DeviceNode
->Flags
&= DNF_ENUMERATED
| DNF_PROCESSED
;
597 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
598 Stack
.MajorFunction
= IRP_MJ_PNP
;
599 Stack
.MinorFunction
= IRP_MN_REMOVE_DEVICE
;
601 /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
602 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
604 IopNotifyPlugPlayNotification(DeviceObject
,
605 EventCategoryTargetDeviceChange
,
606 &GUID_TARGET_DEVICE_REMOVE_COMPLETE
,
609 ObDereferenceObject(DeviceObject
);
615 IopCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
617 IO_STACK_LOCATION Stack
;
620 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
621 Stack
.MajorFunction
= IRP_MJ_PNP
;
622 Stack
.MinorFunction
= IRP_MN_CANCEL_REMOVE_DEVICE
;
624 /* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
625 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
627 IopNotifyPlugPlayNotification(DeviceObject
,
628 EventCategoryTargetDeviceChange
,
629 &GUID_TARGET_DEVICE_REMOVE_CANCELLED
,
637 IopSendStopDevice(IN PDEVICE_OBJECT DeviceObject
)
639 IO_STACK_LOCATION Stack
;
642 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
643 Stack
.MajorFunction
= IRP_MJ_PNP
;
644 Stack
.MinorFunction
= IRP_MN_STOP_DEVICE
;
646 /* Drivers should never fail a IRP_MN_STOP_DEVICE request */
647 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
652 IopStartDevice2(IN PDEVICE_OBJECT DeviceObject
)
654 IO_STACK_LOCATION Stack
;
655 PDEVICE_NODE DeviceNode
;
658 DEVICE_CAPABILITIES DeviceCapabilities
;
660 /* Get the device node */
661 DeviceNode
= IopGetDeviceNode(DeviceObject
);
663 ASSERT(!(DeviceNode
->Flags
& DNF_DISABLED
));
665 /* Build the I/O stack location */
666 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
667 Stack
.MajorFunction
= IRP_MJ_PNP
;
668 Stack
.MinorFunction
= IRP_MN_START_DEVICE
;
670 Stack
.Parameters
.StartDevice
.AllocatedResources
=
671 DeviceNode
->ResourceList
;
672 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
=
673 DeviceNode
->ResourceListTranslated
;
676 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
677 if (!NT_SUCCESS(Status
))
679 /* Send an IRP_MN_REMOVE_DEVICE request */
680 IopRemoveDevice(DeviceNode
);
682 /* Set the appropriate flag */
683 DeviceNode
->Flags
|= DNF_START_FAILED
;
684 DeviceNode
->Problem
= CM_PROB_FAILED_START
;
686 DPRINT1("Warning: PnP Start failed (%wZ) [Status: 0x%x]\n", &DeviceNode
->InstancePath
, Status
);
690 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n");
692 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
693 if (!NT_SUCCESS(Status
))
695 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
698 /* Invalidate device state so IRP_MN_QUERY_PNP_DEVICE_STATE is sent */
699 IoInvalidateDeviceState(DeviceObject
);
701 /* Otherwise, mark us as started */
702 DeviceNode
->Flags
|= DNF_STARTED
;
703 DeviceNode
->Flags
&= ~DNF_STOPPED
;
705 /* We now need enumeration */
706 DeviceNode
->Flags
|= DNF_NEED_ENUMERATION_ONLY
;
711 IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode
)
713 PDEVICE_OBJECT DeviceObject
;
718 ASSERT((DeviceNode
->Flags
& DNF_ADDED
));
719 ASSERT((DeviceNode
->Flags
& (DNF_RESOURCE_ASSIGNED
|
720 DNF_RESOURCE_REPORTED
|
721 DNF_NO_RESOURCE_REQUIRED
)));
723 /* Get the device object */
724 DeviceObject
= DeviceNode
->PhysicalDeviceObject
;
726 /* Check if we're not started yet */
727 if (!(DeviceNode
->Flags
& DNF_STARTED
))
730 IopStartDevice2(DeviceObject
);
733 /* Do we need to query IDs? This happens in the case of manual reporting */
735 if (DeviceNode
->Flags
& DNF_NEED_QUERY_IDS
)
737 DPRINT1("Warning: Device node has DNF_NEED_QUERY_IDS\n");
738 /* And that case shouldn't happen yet */
743 /* Make sure we're started, and check if we need enumeration */
744 if ((DeviceNode
->Flags
& DNF_STARTED
) &&
745 (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
))
748 IoSynchronousInvalidateDeviceRelations(DeviceObject
, BusRelations
);
749 Status
= STATUS_SUCCESS
;
754 Status
= STATUS_SUCCESS
;
763 PDEVICE_NODE DeviceNode
)
767 DPRINT("Stopping device: %wZ\n", &DeviceNode
->InstancePath
);
769 Status
= IopQueryStopDevice(DeviceNode
->PhysicalDeviceObject
);
770 if (NT_SUCCESS(Status
))
772 IopSendStopDevice(DeviceNode
->PhysicalDeviceObject
);
774 DeviceNode
->Flags
&= ~(DNF_STARTED
| DNF_START_REQUEST_PENDING
);
775 DeviceNode
->Flags
|= DNF_STOPPED
;
777 return STATUS_SUCCESS
;
785 PDEVICE_NODE DeviceNode
)
788 HANDLE InstanceHandle
= NULL
, ControlHandle
= NULL
;
789 UNICODE_STRING KeyName
, ValueString
;
790 OBJECT_ATTRIBUTES ObjectAttributes
;
792 if (DeviceNode
->Flags
& DNF_DISABLED
)
793 return STATUS_SUCCESS
;
795 Status
= IopAssignDeviceResources(DeviceNode
);
796 if (!NT_SUCCESS(Status
))
800 IopStartAndEnumerateDevice(DeviceNode
);
802 /* FIX: Should be done in new device instance code */
803 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, REG_OPTION_NON_VOLATILE
, &InstanceHandle
);
804 if (!NT_SUCCESS(Status
))
807 /* FIX: Should be done in IoXxxPrepareDriverLoading */
809 RtlInitUnicodeString(&KeyName
, L
"Control");
810 InitializeObjectAttributes(&ObjectAttributes
,
812 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
815 Status
= ZwCreateKey(&ControlHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
816 if (!NT_SUCCESS(Status
))
819 RtlInitUnicodeString(&KeyName
, L
"ActiveService");
820 ValueString
= DeviceNode
->ServiceName
;
821 if (!ValueString
.Buffer
)
822 RtlInitUnicodeString(&ValueString
, L
"");
823 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_SZ
, ValueString
.Buffer
, ValueString
.Length
+ sizeof(UNICODE_NULL
));
827 if (ControlHandle
!= NULL
)
828 ZwClose(ControlHandle
);
830 if (InstanceHandle
!= NULL
)
831 ZwClose(InstanceHandle
);
838 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
839 PDEVICE_CAPABILITIES DeviceCaps
)
841 IO_STATUS_BLOCK StatusBlock
;
842 IO_STACK_LOCATION Stack
;
845 UNICODE_STRING ValueName
;
847 /* Set up the Header */
848 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
849 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
850 DeviceCaps
->Version
= 1;
851 DeviceCaps
->Address
= -1;
852 DeviceCaps
->UINumber
= -1;
854 /* Set up the Stack */
855 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
856 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
859 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
861 IRP_MN_QUERY_CAPABILITIES
,
863 if (!NT_SUCCESS(Status
))
865 if (Status
!= STATUS_NOT_SUPPORTED
)
867 DPRINT1("IRP_MN_QUERY_CAPABILITIES failed with status 0x%lx\n", Status
);
872 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCaps
->Version
+ sizeof(DeviceCaps
->Version
));
874 if (DeviceCaps
->NoDisplayInUI
)
875 DeviceNode
->UserFlags
|= DNUF_DONT_SHOW_IN_UI
;
877 DeviceNode
->UserFlags
&= ~DNUF_DONT_SHOW_IN_UI
;
879 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, REG_OPTION_NON_VOLATILE
, &InstanceKey
);
880 if (NT_SUCCESS(Status
))
882 /* Set 'Capabilities' value */
883 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
884 Status
= ZwSetValueKey(InstanceKey
,
888 &DeviceNode
->CapabilityFlags
,
891 /* Set 'UINumber' value */
892 if (DeviceCaps
->UINumber
!= MAXULONG
)
894 RtlInitUnicodeString(&ValueName
, L
"UINumber");
895 Status
= ZwSetValueKey(InstanceKey
,
899 &DeviceCaps
->UINumber
,
903 ZwClose(InstanceKey
);
912 IopDeviceActionWorker(
915 PLIST_ENTRY ListEntry
;
916 PDEVICE_ACTION_DATA Data
;
919 KeAcquireSpinLock(&IopDeviceActionLock
, &OldIrql
);
920 while (!IsListEmpty(&IopDeviceActionRequestList
))
922 ListEntry
= RemoveHeadList(&IopDeviceActionRequestList
);
923 KeReleaseSpinLock(&IopDeviceActionLock
, OldIrql
);
924 Data
= CONTAINING_RECORD(ListEntry
,
928 IoSynchronousInvalidateDeviceRelations(Data
->DeviceObject
,
931 ObDereferenceObject(Data
->DeviceObject
);
932 ExFreePoolWithTag(Data
, TAG_IO
);
933 KeAcquireSpinLock(&IopDeviceActionLock
, &OldIrql
);
935 IopDeviceActionInProgress
= FALSE
;
936 KeReleaseSpinLock(&IopDeviceActionLock
, OldIrql
);
940 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
944 if (PopSystemPowerDeviceNode
)
946 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
947 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
948 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
950 return STATUS_SUCCESS
;
953 return STATUS_UNSUCCESSFUL
;
958 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
960 USHORT i
= 0, FoundIndex
= 0xFFFF;
964 /* Acquire the lock */
965 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
967 /* Loop all entries */
968 while (i
< PnpBusTypeGuidList
->GuidCount
)
970 /* Try to find a match */
971 if (RtlCompareMemory(BusTypeGuid
,
972 &PnpBusTypeGuidList
->Guids
[i
],
973 sizeof(GUID
)) == sizeof(GUID
))
982 /* Check if we have to grow the list */
983 if (PnpBusTypeGuidList
->GuidCount
)
985 /* Calculate the new size */
986 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
987 (sizeof(GUID
) * PnpBusTypeGuidList
->GuidCount
);
989 /* Allocate the new copy */
990 NewList
= ExAllocatePool(PagedPool
, NewSize
);
995 ExFreePool(PnpBusTypeGuidList
);
999 /* Now copy them, decrease the size too */
1000 NewSize
-= sizeof(GUID
);
1001 RtlCopyMemory(NewList
, PnpBusTypeGuidList
, NewSize
);
1003 /* Free the old list */
1004 ExFreePool(PnpBusTypeGuidList
);
1006 /* Use the new buffer */
1007 PnpBusTypeGuidList
= NewList
;
1010 /* Copy the new GUID */
1011 RtlCopyMemory(&PnpBusTypeGuidList
->Guids
[PnpBusTypeGuidList
->GuidCount
],
1015 /* The new entry is the index */
1016 FoundIndex
= (USHORT
)PnpBusTypeGuidList
->GuidCount
;
1017 PnpBusTypeGuidList
->GuidCount
++;
1020 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
1026 * Creates a device node
1029 * ParentNode = Pointer to parent device node
1030 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
1031 * to have the root device node create one
1032 * (eg. for legacy drivers)
1033 * DeviceNode = Pointer to storage for created device node
1039 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
1040 PDEVICE_OBJECT PhysicalDeviceObject
,
1041 PUNICODE_STRING ServiceName
,
1042 PDEVICE_NODE
*DeviceNode
)
1047 UNICODE_STRING FullServiceName
;
1048 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
1049 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
1050 UNICODE_STRING KeyName
, ClassName
;
1051 PUNICODE_STRING ServiceName1
;
1053 UNICODE_STRING ClassGUID
;
1054 HANDLE InstanceHandle
;
1056 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
1057 ParentNode
, PhysicalDeviceObject
, ServiceName
);
1059 Node
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(DEVICE_NODE
), TAG_IO_DEVNODE
);
1062 return STATUS_INSUFFICIENT_RESOURCES
;
1065 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
1068 ServiceName1
= &UnknownDeviceName
;
1070 ServiceName1
= ServiceName
;
1072 if (!PhysicalDeviceObject
)
1074 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName1
->Length
+ sizeof(UNICODE_NULL
);
1075 FullServiceName
.Length
= 0;
1076 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
1077 if (!FullServiceName
.Buffer
)
1079 ExFreePoolWithTag(Node
, TAG_IO_DEVNODE
);
1080 return STATUS_INSUFFICIENT_RESOURCES
;
1083 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
1084 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName1
);
1085 RtlUpcaseUnicodeString(&FullServiceName
, &FullServiceName
, FALSE
);
1087 Status
= PnpRootCreateDevice(&FullServiceName
, NULL
, &PhysicalDeviceObject
, &Node
->InstancePath
);
1088 if (!NT_SUCCESS(Status
))
1090 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
1091 ExFreePool(FullServiceName
.Buffer
);
1092 ExFreePoolWithTag(Node
, TAG_IO_DEVNODE
);
1096 /* Create the device key for legacy drivers */
1097 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, REG_OPTION_VOLATILE
, &InstanceHandle
);
1098 if (!NT_SUCCESS(Status
))
1100 ExFreePool(FullServiceName
.Buffer
);
1101 ExFreePoolWithTag(Node
, TAG_IO_DEVNODE
);
1105 Node
->ServiceName
.MaximumLength
= ServiceName1
->Length
+ sizeof(UNICODE_NULL
);
1106 Node
->ServiceName
.Length
= 0;
1107 Node
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, Node
->ServiceName
.MaximumLength
);
1108 if (!Node
->ServiceName
.Buffer
)
1110 ZwClose(InstanceHandle
);
1111 ExFreePool(FullServiceName
.Buffer
);
1112 ExFreePoolWithTag(Node
, TAG_IO_DEVNODE
);
1116 RtlCopyUnicodeString(&Node
->ServiceName
, ServiceName1
);
1120 RtlInitUnicodeString(&KeyName
, L
"Service");
1121 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName
->Buffer
, ServiceName
->Length
+ sizeof(UNICODE_NULL
));
1124 if (NT_SUCCESS(Status
))
1126 RtlInitUnicodeString(&KeyName
, L
"Legacy");
1128 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_DWORD
, &LegacyValue
, sizeof(LegacyValue
));
1130 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1132 ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_DWORD
, &LegacyValue
, sizeof(LegacyValue
));
1134 if (NT_SUCCESS(Status
))
1136 RtlInitUnicodeString(&KeyName
, L
"Class");
1137 RtlInitUnicodeString(&ClassName
, L
"LegacyDriver");
1138 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassName
.Buffer
, ClassName
.Length
+ sizeof(UNICODE_NULL
));
1139 if (NT_SUCCESS(Status
))
1141 RtlInitUnicodeString(&KeyName
, L
"ClassGUID");
1142 RtlInitUnicodeString(&ClassGUID
, L
"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
1143 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassGUID
.Buffer
, ClassGUID
.Length
+ sizeof(UNICODE_NULL
));
1144 if (NT_SUCCESS(Status
))
1146 // FIXME: Retrieve the real "description" by looking at the "DisplayName" string
1147 // of the corresponding CurrentControlSet\Services\xxx entry for this driver.
1148 RtlInitUnicodeString(&KeyName
, L
"DeviceDesc");
1149 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName1
->Buffer
, ServiceName1
->Length
+ sizeof(UNICODE_NULL
));
1155 ZwClose(InstanceHandle
);
1156 ExFreePool(FullServiceName
.Buffer
);
1158 if (!NT_SUCCESS(Status
))
1160 ExFreePool(Node
->ServiceName
.Buffer
);
1161 ExFreePoolWithTag(Node
, TAG_IO_DEVNODE
);
1165 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
1166 IopDeviceNodeSetFlag(Node
, DNF_PROCESSED
);
1167 IopDeviceNodeSetFlag(Node
, DNF_ADDED
);
1168 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
1171 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
1173 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
1177 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
1178 Node
->Parent
= ParentNode
;
1179 Node
->Sibling
= NULL
;
1180 if (ParentNode
->LastChild
== NULL
)
1182 ParentNode
->Child
= Node
;
1183 ParentNode
->LastChild
= Node
;
1187 ParentNode
->LastChild
->Sibling
= Node
;
1188 ParentNode
->LastChild
= Node
;
1190 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
1191 Node
->Level
= ParentNode
->Level
+ 1;
1194 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1198 return STATUS_SUCCESS
;
1202 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
1205 PDEVICE_NODE PrevSibling
= NULL
;
1207 /* All children must be deleted before a parent is deleted */
1208 ASSERT(!DeviceNode
->Child
);
1209 ASSERT(DeviceNode
->PhysicalDeviceObject
);
1211 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
1213 /* Get previous sibling */
1214 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
1216 PrevSibling
= DeviceNode
->Parent
->Child
;
1217 while (PrevSibling
->Sibling
!= DeviceNode
)
1218 PrevSibling
= PrevSibling
->Sibling
;
1221 /* Unlink from parent if it exists */
1222 if (DeviceNode
->Parent
)
1224 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
1226 DeviceNode
->Parent
->LastChild
= PrevSibling
;
1228 PrevSibling
->Sibling
= NULL
;
1230 if (DeviceNode
->Parent
->Child
== DeviceNode
)
1231 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
1234 /* Unlink from sibling list */
1236 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
1238 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
1240 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
1242 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
1244 if (DeviceNode
->ResourceList
)
1246 ExFreePool(DeviceNode
->ResourceList
);
1249 if (DeviceNode
->ResourceListTranslated
)
1251 ExFreePool(DeviceNode
->ResourceListTranslated
);
1254 if (DeviceNode
->ResourceRequirements
)
1256 ExFreePool(DeviceNode
->ResourceRequirements
);
1259 if (DeviceNode
->BootResources
)
1261 ExFreePool(DeviceNode
->BootResources
);
1264 ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceNode
->PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= NULL
;
1265 ExFreePoolWithTag(DeviceNode
, TAG_IO_DEVNODE
);
1267 return STATUS_SUCCESS
;
1272 IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject
,
1273 IN PIO_STACK_LOCATION IoStackLocation
,
1274 OUT PVOID
*Information
)
1277 PIO_STACK_LOCATION IrpStack
;
1278 IO_STATUS_BLOCK IoStatusBlock
;
1281 PDEVICE_OBJECT TopDeviceObject
;
1284 /* Call the top of the device stack */
1285 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
1287 /* Allocate an IRP */
1288 Irp
= IoAllocateIrp(TopDeviceObject
->StackSize
, FALSE
);
1289 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
1291 /* Initialize to failure */
1292 Irp
->IoStatus
.Status
= IoStatusBlock
.Status
= STATUS_NOT_SUPPORTED
;
1293 Irp
->IoStatus
.Information
= IoStatusBlock
.Information
= 0;
1295 /* Special case for IRP_MN_FILTER_RESOURCE_REQUIREMENTS */
1296 if (IoStackLocation
->MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
)
1298 /* Copy the resource requirements list into the IOSB */
1299 Irp
->IoStatus
.Information
=
1300 IoStatusBlock
.Information
= (ULONG_PTR
)IoStackLocation
->Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
1303 /* Initialize the event */
1304 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1307 Irp
->UserIosb
= &IoStatusBlock
;
1308 Irp
->UserEvent
= &Event
;
1311 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1312 IoQueueThreadIrp(Irp
);
1314 /* Copy-in the stack */
1315 IrpStack
= IoGetNextIrpStackLocation(Irp
);
1316 *IrpStack
= *IoStackLocation
;
1318 /* Call the driver */
1319 Status
= IoCallDriver(TopDeviceObject
, Irp
);
1320 if (Status
== STATUS_PENDING
)
1323 KeWaitForSingleObject(&Event
,
1328 Status
= IoStatusBlock
.Status
;
1331 /* Remove the reference */
1332 ObDereferenceObject(TopDeviceObject
);
1334 /* Return the information */
1335 *Information
= (PVOID
)IoStatusBlock
.Information
;
1341 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject
,
1342 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
1343 IN UCHAR MinorFunction
,
1344 IN PIO_STACK_LOCATION Stack OPTIONAL
)
1346 IO_STACK_LOCATION IoStackLocation
;
1348 /* Fill out the stack information */
1349 RtlZeroMemory(&IoStackLocation
, sizeof(IO_STACK_LOCATION
));
1350 IoStackLocation
.MajorFunction
= IRP_MJ_PNP
;
1351 IoStackLocation
.MinorFunction
= MinorFunction
;
1355 RtlCopyMemory(&IoStackLocation
.Parameters
,
1357 sizeof(Stack
->Parameters
));
1360 /* Do the PnP call */
1361 IoStatusBlock
->Status
= IopSynchronousCall(DeviceObject
,
1363 (PVOID
)&IoStatusBlock
->Information
);
1364 return IoStatusBlock
->Status
;
1368 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1370 PDEVICE_NODE ParentDeviceNode
;
1371 PDEVICE_NODE ChildDeviceNode
;
1374 /* Copy context data so we don't overwrite it in subsequent calls to this function */
1375 ParentDeviceNode
= Context
->DeviceNode
;
1377 /* Call the action routine */
1378 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
1379 if (!NT_SUCCESS(Status
))
1384 /* Traversal of all children nodes */
1385 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
1386 ChildDeviceNode
!= NULL
;
1387 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
1389 /* Pass the current device node to the action routine */
1390 Context
->DeviceNode
= ChildDeviceNode
;
1392 Status
= IopTraverseDeviceTreeNode(Context
);
1393 if (!NT_SUCCESS(Status
))
1404 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1408 DPRINT("Context 0x%p\n", Context
);
1410 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %p Context 0x%p)\n",
1411 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
1413 /* Start from the specified device node */
1414 Context
->DeviceNode
= Context
->FirstDeviceNode
;
1416 /* Recursively traverse the device tree */
1417 Status
= IopTraverseDeviceTreeNode(Context
);
1418 if (Status
== STATUS_UNSUCCESSFUL
)
1420 /* The action routine just wanted to terminate the traversal with status
1421 code STATUS_SUCCESS */
1422 Status
= STATUS_SUCCESS
;
1430 * IopCreateDeviceKeyPath
1432 * Creates a registry key
1436 * Name of the key to be created.
1438 * Handle to the newly created key
1441 * This method can create nested trees, so parent of RegistryPath can
1442 * be not existant, and will be created if needed.
1446 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
1447 IN ULONG CreateOptions
,
1450 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
1451 HANDLE hParent
= NULL
, hKey
;
1452 OBJECT_ATTRIBUTES ObjectAttributes
;
1453 UNICODE_STRING KeyName
;
1454 PCWSTR Current
, Last
;
1458 /* Assume failure */
1461 /* Create a volatile device tree in 1st stage so we have a clean slate
1462 * for enumeration using the correct HAL (chosen in 1st stage setup) */
1463 if (ExpInTextModeSetup
) CreateOptions
|= REG_OPTION_VOLATILE
;
1465 /* Open root key for device instances */
1466 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
1467 if (!NT_SUCCESS(Status
))
1469 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
1473 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
1474 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
1476 /* Go up to the end of the string */
1477 while (Current
<= Last
)
1479 if (Current
!= Last
&& *Current
!= L
'\\')
1481 /* Not the end of the string and not a separator */
1486 /* Prepare relative key name */
1487 Length
= (USHORT
)((ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
);
1488 KeyName
.MaximumLength
= KeyName
.Length
= Length
;
1489 DPRINT("Create '%wZ'\n", &KeyName
);
1492 InitializeObjectAttributes(&ObjectAttributes
,
1494 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1497 Status
= ZwCreateKey(&hKey
,
1498 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
1505 /* Close parent key handle, we don't need it anymore */
1509 /* Key opening/creating failed? */
1510 if (!NT_SUCCESS(Status
))
1512 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
1516 /* Check if it is the end of the string */
1517 if (Current
== Last
)
1519 /* Yes, return success */
1521 return STATUS_SUCCESS
;
1524 /* Start with this new parent key */
1527 KeyName
.Buffer
= (PWSTR
)Current
;
1530 return STATUS_UNSUCCESSFUL
;
1534 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1535 PDEVICE_NODE DeviceNode
)
1537 OBJECT_ATTRIBUTES ObjectAttributes
;
1538 UNICODE_STRING KeyName
;
1539 HANDLE LogConfKey
, ControlKey
, DeviceParamsKey
;
1544 DPRINT("IopSetDeviceInstanceData() called\n");
1546 /* Create the 'LogConf' key */
1547 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1548 InitializeObjectAttributes(&ObjectAttributes
,
1550 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1553 Status
= ZwCreateKey(&LogConfKey
,
1558 REG_OPTION_VOLATILE
,
1560 if (NT_SUCCESS(Status
))
1562 /* Set 'BootConfig' value */
1563 if (DeviceNode
->BootResources
!= NULL
)
1565 ResCount
= DeviceNode
->BootResources
->Count
;
1568 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1569 Status
= ZwSetValueKey(LogConfKey
,
1573 DeviceNode
->BootResources
,
1574 PnpDetermineResourceListSize(DeviceNode
->BootResources
));
1578 /* Set 'BasicConfigVector' value */
1579 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1580 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1582 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1583 Status
= ZwSetValueKey(LogConfKey
,
1586 REG_RESOURCE_REQUIREMENTS_LIST
,
1587 DeviceNode
->ResourceRequirements
,
1588 DeviceNode
->ResourceRequirements
->ListSize
);
1591 ZwClose(LogConfKey
);
1594 /* Set the 'ConfigFlags' value */
1595 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1596 Status
= ZwQueryValueKey(InstanceKey
,
1598 KeyValueBasicInformation
,
1602 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1604 /* Write the default value */
1605 ULONG DefaultConfigFlags
= 0;
1606 Status
= ZwSetValueKey(InstanceKey
,
1610 &DefaultConfigFlags
,
1611 sizeof(DefaultConfigFlags
));
1614 /* Create the 'Control' key */
1615 RtlInitUnicodeString(&KeyName
, L
"Control");
1616 InitializeObjectAttributes(&ObjectAttributes
,
1618 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1621 Status
= ZwCreateKey(&ControlKey
,
1626 REG_OPTION_VOLATILE
,
1628 if (NT_SUCCESS(Status
))
1629 ZwClose(ControlKey
);
1631 /* Create the 'Device Parameters' key and set the 'FirmwareIdentified' value for all ACPI-enumerated devices */
1632 if (_wcsnicmp(DeviceNode
->InstancePath
.Buffer
, L
"ACPI\\", 5) == 0)
1634 RtlInitUnicodeString(&KeyName
, L
"Device Parameters");
1635 InitializeObjectAttributes(&ObjectAttributes
,
1637 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1640 Status
= ZwCreateKey(&DeviceParamsKey
,
1645 REG_OPTION_NON_VOLATILE
,
1647 if (NT_SUCCESS(Status
))
1649 ULONG FirmwareIdentified
= 1;
1650 RtlInitUnicodeString(&KeyName
, L
"FirmwareIdentified");
1651 Status
= ZwSetValueKey(DeviceParamsKey
,
1655 &FirmwareIdentified
,
1656 sizeof(FirmwareIdentified
));
1658 ZwClose(DeviceParamsKey
);
1662 DPRINT("IopSetDeviceInstanceData() done\n");
1668 * IopGetParentIdPrefix
1670 * Retrieve (or create) a string which identifies a device.
1674 * Pointer to device node.
1676 * Pointer to the string where is returned the parent node identifier
1679 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1680 * valid and its Buffer field is NULL-terminated. The caller needs to
1681 * to free the string with RtlFreeUnicodeString when it is no longer
1686 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1687 PUNICODE_STRING ParentIdPrefix
)
1689 const UNICODE_STRING EnumKeyPath
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1690 ULONG KeyNameBufferLength
;
1691 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1692 UNICODE_STRING KeyName
= {0, 0, NULL
};
1693 UNICODE_STRING KeyValue
;
1694 UNICODE_STRING ValueName
;
1699 /* HACK: As long as some devices have a NULL device
1700 * instance path, the following test is required :(
1702 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1704 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1705 &DeviceNode
->InstancePath
);
1706 return STATUS_UNSUCCESSFUL
;
1709 /* 1. Try to retrieve ParentIdPrefix from registry */
1710 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1711 ParentIdPrefixInformation
= ExAllocatePoolWithTag(PagedPool
,
1712 KeyNameBufferLength
+ sizeof(UNICODE_NULL
),
1714 if (!ParentIdPrefixInformation
)
1716 return STATUS_INSUFFICIENT_RESOURCES
;
1720 KeyName
.MaximumLength
= EnumKeyPath
.Length
+
1721 DeviceNode
->Parent
->InstancePath
.Length
+
1722 sizeof(UNICODE_NULL
);
1723 KeyName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
1724 KeyName
.MaximumLength
,
1726 if (!KeyName
.Buffer
)
1728 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1732 RtlCopyUnicodeString(&KeyName
, &EnumKeyPath
);
1733 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1735 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1736 if (!NT_SUCCESS(Status
))
1740 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1741 Status
= ZwQueryValueKey(hKey
,
1743 KeyValuePartialInformation
,
1744 ParentIdPrefixInformation
,
1745 KeyNameBufferLength
,
1746 &KeyNameBufferLength
);
1747 if (NT_SUCCESS(Status
))
1749 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1751 Status
= STATUS_UNSUCCESSFUL
;
1755 KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1756 KeyValue
.Length
= KeyValue
.MaximumLength
- sizeof(UNICODE_NULL
);
1757 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1758 ASSERT(KeyValue
.Buffer
[KeyValue
.Length
/ sizeof(WCHAR
)] == UNICODE_NULL
);
1762 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1764 /* FIXME how do we get here and why is ParentIdPrefixInformation valid? */
1765 KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1766 KeyValue
.Length
= KeyValue
.MaximumLength
- sizeof(UNICODE_NULL
);
1767 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1768 ASSERT(KeyValue
.Buffer
[KeyValue
.Length
/ sizeof(WCHAR
)] == UNICODE_NULL
);
1772 /* 2. Create the ParentIdPrefix value */
1773 crc32
= RtlComputeCrc32(0,
1774 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1775 DeviceNode
->Parent
->InstancePath
.Length
);
1777 RtlStringCbPrintfW((PWSTR
)ParentIdPrefixInformation
,
1778 KeyNameBufferLength
,
1780 DeviceNode
->Parent
->Level
,
1782 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
);
1784 /* 3. Try to write the ParentIdPrefix to registry */
1785 Status
= ZwSetValueKey(hKey
,
1790 ((ULONG
)wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1793 if (NT_SUCCESS(Status
))
1795 /* Duplicate the string to return it */
1796 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
,
1800 ExFreePoolWithTag(ParentIdPrefixInformation
, TAG_IO
);
1801 RtlFreeUnicodeString(&KeyName
);
1813 _In_ BUS_QUERY_ID_TYPE QueryType
)
1818 ULONG SeparatorsCount
= 0;
1819 PWCHAR PtrPrevChar
= NULL
;
1820 ULONG MaxSeparators
;
1827 case BusQueryDeviceID
:
1828 MaxSeparators
= MAX_SEPARATORS_DEVICEID
;
1831 case BusQueryInstanceID
:
1832 MaxSeparators
= MAX_SEPARATORS_INSTANCEID
;
1836 case BusQueryHardwareIDs
:
1837 case BusQueryCompatibleIDs
:
1838 MaxSeparators
= MAX_SEPARATORS_DEVICEID
;
1843 DPRINT1("IopValidateID: Not handled QueryType - %x\n", QueryType
);
1847 StringEnd
= Id
+ MAX_DEVICE_ID_LEN
;
1849 for (PtrChar
= Id
; PtrChar
< StringEnd
; PtrChar
++)
1853 if (Char
== UNICODE_NULL
)
1855 if (!IsMultiSz
|| (PtrPrevChar
&& PtrChar
== PtrPrevChar
+ 1))
1857 if (MaxSeparators
== SeparatorsCount
|| IsMultiSz
)
1862 DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators - %lu\n",
1863 SeparatorsCount
, MaxSeparators
);
1867 StringEnd
= PtrChar
+ MAX_DEVICE_ID_LEN
+ 1;
1868 PtrPrevChar
= PtrChar
;
1869 SeparatorsCount
= 0;
1871 else if (Char
< ' ' || Char
> 0x7F || Char
== ',')
1873 DPRINT1("IopValidateID: Invalid character - %04X\n", Char
);
1876 else if (Char
== ' ')
1880 else if (Char
== '\\')
1884 if (SeparatorsCount
> MaxSeparators
)
1886 DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators - %lu\n",
1887 SeparatorsCount
, MaxSeparators
);
1893 DPRINT1("IopValidateID: Not terminated ID\n");
1901 IopQueryHardwareIds(PDEVICE_NODE DeviceNode
,
1904 IO_STACK_LOCATION Stack
;
1905 IO_STATUS_BLOCK IoStatusBlock
;
1907 UNICODE_STRING ValueName
;
1909 ULONG Length
, TotalLength
;
1912 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1914 RtlZeroMemory(&Stack
, sizeof(Stack
));
1915 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1916 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1920 if (NT_SUCCESS(Status
))
1922 IsValidID
= IopValidateID((PWCHAR
)IoStatusBlock
.Information
, BusQueryHardwareIDs
);
1926 DPRINT1("Invalid HardwareIDs. DeviceNode - %p\n", DeviceNode
);
1931 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1932 DPRINT("Hardware IDs:\n");
1935 DPRINT(" %S\n", Ptr
);
1936 Length
= (ULONG
)wcslen(Ptr
) + 1;
1939 TotalLength
+= Length
;
1941 DPRINT("TotalLength: %hu\n", TotalLength
);
1944 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1945 Status
= ZwSetValueKey(InstanceKey
,
1949 (PVOID
)IoStatusBlock
.Information
,
1950 (TotalLength
+ 1) * sizeof(WCHAR
));
1951 if (!NT_SUCCESS(Status
))
1953 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1958 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1965 IopQueryCompatibleIds(PDEVICE_NODE DeviceNode
,
1968 IO_STACK_LOCATION Stack
;
1969 IO_STATUS_BLOCK IoStatusBlock
;
1971 UNICODE_STRING ValueName
;
1973 ULONG Length
, TotalLength
;
1976 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1978 RtlZeroMemory(&Stack
, sizeof(Stack
));
1979 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1980 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1984 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1986 IsValidID
= IopValidateID((PWCHAR
)IoStatusBlock
.Information
, BusQueryCompatibleIDs
);
1990 DPRINT1("Invalid CompatibleIDs. DeviceNode - %p\n", DeviceNode
);
1995 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1996 DPRINT("Compatible IDs:\n");
1999 DPRINT(" %S\n", Ptr
);
2000 Length
= (ULONG
)wcslen(Ptr
) + 1;
2003 TotalLength
+= Length
;
2005 DPRINT("TotalLength: %hu\n", TotalLength
);
2008 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
2009 Status
= ZwSetValueKey(InstanceKey
,
2013 (PVOID
)IoStatusBlock
.Information
,
2014 (TotalLength
+ 1) * sizeof(WCHAR
));
2015 if (!NT_SUCCESS(Status
))
2017 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
2022 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2029 IopCreateDeviceInstancePath(
2030 _In_ PDEVICE_NODE DeviceNode
,
2031 _Out_ PUNICODE_STRING InstancePath
)
2033 IO_STATUS_BLOCK IoStatusBlock
;
2034 UNICODE_STRING DeviceId
;
2035 UNICODE_STRING InstanceId
;
2036 IO_STACK_LOCATION Stack
;
2038 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
2039 DEVICE_CAPABILITIES DeviceCapabilities
;
2042 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
2044 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
2045 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2049 if (!NT_SUCCESS(Status
))
2051 DPRINT1("IopInitiatePnpIrp(BusQueryDeviceID) failed (Status %x)\n", Status
);
2055 IsValidID
= IopValidateID((PWCHAR
)IoStatusBlock
.Information
, BusQueryDeviceID
);
2059 DPRINT1("Invalid DeviceID. DeviceNode - %p\n", DeviceNode
);
2062 /* Save the device id string */
2063 RtlInitUnicodeString(&DeviceId
, (PWSTR
)IoStatusBlock
.Information
);
2065 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n");
2067 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
2068 if (!NT_SUCCESS(Status
))
2070 DPRINT1("IopQueryDeviceCapabilities() failed (Status 0x%08lx)\n", Status
);
2071 RtlFreeUnicodeString(&DeviceId
);
2075 /* This bit is only check after enumeration */
2076 if (DeviceCapabilities
.HardwareDisabled
)
2078 /* FIXME: Cleanup device */
2079 DeviceNode
->Flags
|= DNF_DISABLED
;
2080 RtlFreeUnicodeString(&DeviceId
);
2081 return STATUS_PLUGPLAY_NO_DEVICE
;
2085 DeviceNode
->Flags
&= ~DNF_DISABLED
;
2088 if (!DeviceCapabilities
.UniqueID
)
2090 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
2091 DPRINT("Instance ID is not unique\n");
2092 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
2093 if (!NT_SUCCESS(Status
))
2095 DPRINT1("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
2096 RtlFreeUnicodeString(&DeviceId
);
2101 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
2103 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
2104 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2108 if (!NT_SUCCESS(Status
))
2110 DPRINT("IopInitiatePnpIrp(BusQueryInstanceID) failed (Status %lx)\n", Status
);
2111 ASSERT(IoStatusBlock
.Information
== 0);
2114 if (IoStatusBlock
.Information
)
2116 IsValidID
= IopValidateID((PWCHAR
)IoStatusBlock
.Information
, BusQueryInstanceID
);
2120 DPRINT1("Invalid InstanceID. DeviceNode - %p\n", DeviceNode
);
2124 RtlInitUnicodeString(&InstanceId
,
2125 (PWSTR
)IoStatusBlock
.Information
);
2127 InstancePath
->Length
= 0;
2128 InstancePath
->MaximumLength
= DeviceId
.Length
+ sizeof(WCHAR
) +
2129 ParentIdPrefix
.Length
+
2131 sizeof(UNICODE_NULL
);
2132 if (ParentIdPrefix
.Length
&& InstanceId
.Length
)
2134 InstancePath
->MaximumLength
+= sizeof(WCHAR
);
2137 InstancePath
->Buffer
= ExAllocatePoolWithTag(PagedPool
,
2138 InstancePath
->MaximumLength
,
2140 if (!InstancePath
->Buffer
)
2142 RtlFreeUnicodeString(&InstanceId
);
2143 RtlFreeUnicodeString(&ParentIdPrefix
);
2144 RtlFreeUnicodeString(&DeviceId
);
2145 return STATUS_INSUFFICIENT_RESOURCES
;
2148 /* Start with the device id */
2149 RtlCopyUnicodeString(InstancePath
, &DeviceId
);
2150 RtlAppendUnicodeToString(InstancePath
, L
"\\");
2152 /* Add information from parent bus device to InstancePath */
2153 RtlAppendUnicodeStringToString(InstancePath
, &ParentIdPrefix
);
2154 if (ParentIdPrefix
.Length
&& InstanceId
.Length
)
2156 RtlAppendUnicodeToString(InstancePath
, L
"&");
2159 /* Finally, add the id returned by the driver stack */
2160 RtlAppendUnicodeStringToString(InstancePath
, &InstanceId
);
2163 * FIXME: Check for valid characters, if there is invalid characters
2167 RtlFreeUnicodeString(&InstanceId
);
2168 RtlFreeUnicodeString(&DeviceId
);
2169 RtlFreeUnicodeString(&ParentIdPrefix
);
2171 return STATUS_SUCCESS
;
2175 * IopActionInterrogateDeviceStack
2177 * Retrieve information for all (direct) child nodes of a parent node.
2181 * Pointer to device node.
2183 * Pointer to parent node to retrieve child node information for.
2186 * Any errors that occur are logged instead so that all child services have a chance
2187 * of being interrogated.
2191 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
2194 IO_STATUS_BLOCK IoStatusBlock
;
2195 PWSTR DeviceDescription
;
2196 PWSTR LocationInformation
;
2197 PDEVICE_NODE ParentDeviceNode
;
2198 IO_STACK_LOCATION Stack
;
2200 ULONG RequiredLength
;
2202 HANDLE InstanceKey
= NULL
;
2203 UNICODE_STRING ValueName
;
2204 UNICODE_STRING InstancePathU
;
2205 PDEVICE_OBJECT OldDeviceObject
;
2207 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
2208 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
2210 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2213 * We are called for the parent too, but we don't need to do special
2214 * handling for this node
2216 if (DeviceNode
== ParentDeviceNode
)
2218 DPRINT("Success\n");
2219 return STATUS_SUCCESS
;
2223 * Make sure this device node is a direct child of the parent device node
2224 * that is given as an argument
2226 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2228 DPRINT("Skipping 2+ level child\n");
2229 return STATUS_SUCCESS
;
2232 /* Skip processing if it was already completed before */
2233 if (DeviceNode
->Flags
& DNF_PROCESSED
)
2236 return STATUS_SUCCESS
;
2240 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
2241 if (!NT_SUCCESS(Status
))
2243 DPRINT1("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
2248 * FIXME: For critical errors, cleanup and disable device, but always
2249 * return STATUS_SUCCESS.
2252 Status
= IopCreateDeviceInstancePath(DeviceNode
, &InstancePathU
);
2253 if (!NT_SUCCESS(Status
))
2255 if (Status
!= STATUS_PLUGPLAY_NO_DEVICE
)
2257 DPRINT1("IopCreateDeviceInstancePath() failed with status 0x%lx\n", Status
);
2260 /* We have to return success otherwise we abort the traverse operation */
2261 return STATUS_SUCCESS
;
2264 /* Verify that this is not a duplicate */
2265 OldDeviceObject
= IopGetDeviceObjectFromDeviceInstance(&InstancePathU
);
2266 if (OldDeviceObject
!= NULL
)
2268 PDEVICE_NODE OldDeviceNode
= IopGetDeviceNode(OldDeviceObject
);
2270 DPRINT1("Duplicate device instance '%wZ'\n", &InstancePathU
);
2271 DPRINT1("Current instance parent: '%wZ'\n", &DeviceNode
->Parent
->InstancePath
);
2272 DPRINT1("Old instance parent: '%wZ'\n", &OldDeviceNode
->Parent
->InstancePath
);
2274 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR
,
2276 (ULONG_PTR
)DeviceNode
->PhysicalDeviceObject
,
2277 (ULONG_PTR
)OldDeviceObject
,
2281 DeviceNode
->InstancePath
= InstancePathU
;
2283 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
2286 * Create registry key for the instance id, if it doesn't exist yet
2288 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, REG_OPTION_NON_VOLATILE
, &InstanceKey
);
2289 if (!NT_SUCCESS(Status
))
2291 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2293 /* We have to return success otherwise we abort the traverse operation */
2294 return STATUS_SUCCESS
;
2297 IopQueryHardwareIds(DeviceNode
, InstanceKey
);
2299 IopQueryCompatibleIds(DeviceNode
, InstanceKey
);
2301 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
2303 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
2304 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2305 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2307 IRP_MN_QUERY_DEVICE_TEXT
,
2309 DeviceDescription
= NT_SUCCESS(Status
) ? (PWSTR
)IoStatusBlock
.Information
2311 /* This key is mandatory, so even if the Irp fails, we still write it */
2312 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2313 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2315 if (DeviceDescription
&&
2316 *DeviceDescription
!= UNICODE_NULL
)
2318 /* This key is overriden when a driver is installed. Don't write the
2319 * new description if another one already exists */
2320 Status
= ZwSetValueKey(InstanceKey
,
2325 ((ULONG
)wcslen(DeviceDescription
) + 1) * sizeof(WCHAR
));
2329 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2330 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2332 Status
= ZwSetValueKey(InstanceKey
,
2337 DeviceDesc
.MaximumLength
);
2338 if (!NT_SUCCESS(Status
))
2340 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2346 if (DeviceDescription
)
2348 ExFreePoolWithTag(DeviceDescription
, 0);
2351 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2353 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2354 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2355 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2357 IRP_MN_QUERY_DEVICE_TEXT
,
2359 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2361 LocationInformation
= (PWSTR
)IoStatusBlock
.Information
;
2362 DPRINT("LocationInformation: %S\n", LocationInformation
);
2363 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2364 Status
= ZwSetValueKey(InstanceKey
,
2368 LocationInformation
,
2369 ((ULONG
)wcslen(LocationInformation
) + 1) * sizeof(WCHAR
));
2370 if (!NT_SUCCESS(Status
))
2372 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2375 ExFreePoolWithTag(LocationInformation
, 0);
2379 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2382 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2384 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2386 IRP_MN_QUERY_BUS_INFORMATION
,
2388 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2390 PPNP_BUS_INFORMATION BusInformation
= (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2392 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2393 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2394 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2395 ExFreePoolWithTag(BusInformation
, 0);
2399 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2401 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2402 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2403 DeviceNode
->ChildBusTypeIndex
= -1;
2406 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2408 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2410 IRP_MN_QUERY_RESOURCES
,
2412 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2414 DeviceNode
->BootResources
= (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2415 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
2419 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2420 DeviceNode
->BootResources
= NULL
;
2423 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2425 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
2427 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2429 if (NT_SUCCESS(Status
))
2431 DeviceNode
->ResourceRequirements
= (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2435 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2436 DeviceNode
->ResourceRequirements
= NULL
;
2439 if (InstanceKey
!= NULL
)
2441 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2444 ZwClose(InstanceKey
);
2446 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
2448 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
2450 /* Report the device to the user-mode pnp manager */
2451 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
2452 &DeviceNode
->InstancePath
);
2455 return STATUS_SUCCESS
;
2460 IopHandleDeviceRemoval(
2461 IN PDEVICE_NODE DeviceNode
,
2462 IN PDEVICE_RELATIONS DeviceRelations
)
2464 PDEVICE_NODE Child
= DeviceNode
->Child
, NextChild
;
2468 if (DeviceNode
== IopRootDeviceNode
)
2471 while (Child
!= NULL
)
2473 NextChild
= Child
->Sibling
;
2476 for (i
= 0; DeviceRelations
&& i
< DeviceRelations
->Count
; i
++)
2478 if (IopGetDeviceNode(DeviceRelations
->Objects
[i
]) == Child
)
2485 if (!Found
&& !(Child
->Flags
& DNF_WILL_BE_REMOVED
))
2487 /* Send removal IRPs to all of its children */
2488 IopPrepareDeviceForRemoval(Child
->PhysicalDeviceObject
, TRUE
);
2490 /* Send the surprise removal IRP */
2491 IopSendSurpriseRemoval(Child
->PhysicalDeviceObject
);
2493 /* Tell the user-mode PnP manager that a device was removed */
2494 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL
,
2495 &Child
->InstancePath
);
2497 /* Send the remove device IRP */
2498 IopSendRemoveDevice(Child
->PhysicalDeviceObject
);
2507 IN PDEVICE_OBJECT DeviceObject
)
2509 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2510 DEVICETREE_TRAVERSE_CONTEXT Context
;
2511 PDEVICE_RELATIONS DeviceRelations
;
2512 PDEVICE_OBJECT ChildDeviceObject
;
2513 IO_STATUS_BLOCK IoStatusBlock
;
2514 PDEVICE_NODE ChildDeviceNode
;
2515 IO_STACK_LOCATION Stack
;
2519 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2521 if (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
)
2523 DeviceNode
->Flags
&= ~DNF_NEED_ENUMERATION_ONLY
;
2525 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
2526 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2527 &DeviceNode
->InstancePath
);
2530 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2532 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
2534 Status
= IopInitiatePnpIrp(
2537 IRP_MN_QUERY_DEVICE_RELATIONS
,
2539 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
2541 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2545 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2548 * Send removal IRPs for devices that have disappeared
2549 * NOTE: This code handles the case where no relations are specified
2551 IopHandleDeviceRemoval(DeviceNode
, DeviceRelations
);
2553 /* Now we bail if nothing was returned */
2554 if (!DeviceRelations
)
2556 /* We're all done */
2557 DPRINT("No PDOs\n");
2558 return STATUS_SUCCESS
;
2561 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
2564 * Create device nodes for all discovered devices
2566 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2568 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
2569 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
2571 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
2572 if (!ChildDeviceNode
)
2574 /* One doesn't exist, create it */
2575 Status
= IopCreateDeviceNode(
2580 if (NT_SUCCESS(Status
))
2582 /* Mark the node as enumerated */
2583 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2585 /* Mark the DO as bus enumerated */
2586 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2590 /* Ignore this DO */
2591 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
2592 ObDereferenceObject(ChildDeviceObject
);
2597 /* Mark it as enumerated */
2598 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2599 ObDereferenceObject(ChildDeviceObject
);
2602 ExFreePool(DeviceRelations
);
2605 * Retrieve information about all discovered children from the bus driver
2607 IopInitDeviceTreeTraverseContext(
2610 IopActionInterrogateDeviceStack
,
2613 Status
= IopTraverseDeviceTree(&Context
);
2614 if (!NT_SUCCESS(Status
))
2616 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2621 * Retrieve configuration from the registry for discovered children
2623 IopInitDeviceTreeTraverseContext(
2626 IopActionConfigureChildServices
,
2629 Status
= IopTraverseDeviceTree(&Context
);
2630 if (!NT_SUCCESS(Status
))
2632 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2637 * Initialize services for discovered children.
2639 Status
= IopInitializePnpServices(DeviceNode
);
2640 if (!NT_SUCCESS(Status
))
2642 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2646 DPRINT("IopEnumerateDevice() finished\n");
2647 return STATUS_SUCCESS
;
2652 * IopActionConfigureChildServices
2654 * Retrieve configuration for all (direct) child nodes of a parent node.
2658 * Pointer to device node.
2660 * Pointer to parent node to retrieve child node configuration for.
2663 * Any errors that occur are logged instead so that all child services have a chance of beeing
2668 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2671 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2672 PDEVICE_NODE ParentDeviceNode
;
2673 PUNICODE_STRING Service
;
2674 UNICODE_STRING ClassGUID
;
2676 DEVICE_CAPABILITIES DeviceCaps
;
2678 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2680 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2683 * We are called for the parent too, but we don't need to do special
2684 * handling for this node
2686 if (DeviceNode
== ParentDeviceNode
)
2688 DPRINT("Success\n");
2689 return STATUS_SUCCESS
;
2693 * Make sure this device node is a direct child of the parent device node
2694 * that is given as an argument
2697 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2699 DPRINT("Skipping 2+ level child\n");
2700 return STATUS_SUCCESS
;
2703 if (!(DeviceNode
->Flags
& DNF_PROCESSED
))
2705 DPRINT1("Child not ready to be configured\n");
2706 return STATUS_SUCCESS
;
2709 if (!(DeviceNode
->Flags
& (DNF_DISABLED
| DNF_STARTED
| DNF_ADDED
)))
2711 WCHAR RegKeyBuffer
[MAX_PATH
];
2712 UNICODE_STRING RegKey
;
2714 /* Install the service for this if it's in the CDDB */
2715 IopInstallCriticalDevice(DeviceNode
);
2718 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2719 RegKey
.Buffer
= RegKeyBuffer
;
2722 * Retrieve configuration from Enum key
2725 Service
= &DeviceNode
->ServiceName
;
2727 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2728 RtlInitUnicodeString(Service
, NULL
);
2729 RtlInitUnicodeString(&ClassGUID
, NULL
);
2731 QueryTable
[0].Name
= L
"Service";
2732 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2733 QueryTable
[0].EntryContext
= Service
;
2735 QueryTable
[1].Name
= L
"ClassGUID";
2736 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2737 QueryTable
[1].EntryContext
= &ClassGUID
;
2738 QueryTable
[1].DefaultType
= REG_SZ
;
2739 QueryTable
[1].DefaultData
= L
"";
2740 QueryTable
[1].DefaultLength
= 0;
2742 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2743 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2745 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2746 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2748 if (!NT_SUCCESS(Status
))
2750 /* FIXME: Log the error */
2751 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2752 &DeviceNode
->InstancePath
, Status
);
2753 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2754 return STATUS_SUCCESS
;
2757 if (Service
->Buffer
== NULL
)
2759 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
2760 DeviceCaps
.RawDeviceOK
)
2762 DPRINT("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
2763 RtlInitEmptyUnicodeString(&DeviceNode
->ServiceName
, NULL
, 0);
2765 else if (ClassGUID
.Length
!= 0)
2767 /* Device has a ClassGUID value, but no Service value.
2768 * Suppose it is using the NULL driver, so state the
2769 * device is started */
2770 DPRINT("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2771 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2775 DeviceNode
->Problem
= CM_PROB_FAILED_INSTALL
;
2776 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2778 return STATUS_SUCCESS
;
2781 DPRINT("Got Service %S\n", Service
->Buffer
);
2784 return STATUS_SUCCESS
;
2788 * IopActionInitChildServices
2790 * Initialize the service for all (direct) child nodes of a parent node
2794 * Pointer to device node.
2796 * Pointer to parent node to initialize child node services for.
2799 * If the driver image for a service is not loaded and initialized
2800 * it is done here too. Any errors that occur are logged instead so
2801 * that all child services have a chance of being initialized.
2805 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2808 PDEVICE_NODE ParentDeviceNode
;
2810 BOOLEAN BootDrivers
= !PnpSystemInit
;
2812 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
2814 ParentDeviceNode
= Context
;
2817 * We are called for the parent too, but we don't need to do special
2818 * handling for this node
2820 if (DeviceNode
== ParentDeviceNode
)
2822 DPRINT("Success\n");
2823 return STATUS_SUCCESS
;
2827 * We don't want to check for a direct child because
2828 * this function is called during boot to reinitialize
2829 * devices with drivers that couldn't load yet due to
2830 * stage 0 limitations (ie can't load from disk yet).
2833 if (!(DeviceNode
->Flags
& DNF_PROCESSED
))
2835 DPRINT1("Child not ready to be added\n");
2836 return STATUS_SUCCESS
;
2839 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
) ||
2840 IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) ||
2841 IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2842 return STATUS_SUCCESS
;
2844 if (DeviceNode
->ServiceName
.Buffer
== NULL
)
2846 /* We don't need to worry about loading the driver because we're
2847 * being driven in raw mode so our parent must be loaded to get here */
2848 Status
= IopInitializeDevice(DeviceNode
, NULL
);
2849 if (NT_SUCCESS(Status
))
2851 Status
= IopStartDevice(DeviceNode
);
2852 if (!NT_SUCCESS(Status
))
2854 DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
2855 &DeviceNode
->InstancePath
, Status
);
2861 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2862 PDRIVER_OBJECT DriverObject
;
2864 KeEnterCriticalRegion();
2865 ExAcquireResourceExclusiveLite(&IopDriverLoadResource
, TRUE
);
2866 /* Get existing DriverObject pointer (in case the driver has
2867 already been loaded and initialized) */
2868 Status
= IopGetDriverObject(
2870 &DeviceNode
->ServiceName
,
2873 if (!NT_SUCCESS(Status
))
2875 /* Driver is not initialized, try to load it */
2876 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2878 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2880 /* Initialize the driver */
2881 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2882 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2883 if (!NT_SUCCESS(Status
)) DeviceNode
->Problem
= CM_PROB_FAILED_DRIVER_ENTRY
;
2885 else if (Status
== STATUS_DRIVER_UNABLE_TO_LOAD
)
2887 DPRINT1("Service '%wZ' is disabled\n", &DeviceNode
->ServiceName
);
2888 DeviceNode
->Problem
= CM_PROB_DISABLED_SERVICE
;
2892 DPRINT("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2893 &DeviceNode
->ServiceName
, Status
);
2894 if (!BootDrivers
) DeviceNode
->Problem
= CM_PROB_DRIVER_FAILED_LOAD
;
2897 ExReleaseResourceLite(&IopDriverLoadResource
);
2898 KeLeaveCriticalRegion();
2900 /* Driver is loaded and initialized at this point */
2901 if (NT_SUCCESS(Status
))
2903 /* Initialize the device, including all filters */
2904 Status
= PipCallDriverAddDevice(DeviceNode
, FALSE
, DriverObject
);
2906 /* Remove the extra reference */
2907 ObDereferenceObject(DriverObject
);
2912 * Don't disable when trying to load only boot drivers
2916 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2921 return STATUS_SUCCESS
;
2925 * IopInitializePnpServices
2927 * Initialize services for discovered children
2931 * Top device node to start initializing services.
2937 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2939 DEVICETREE_TRAVERSE_CONTEXT Context
;
2941 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2943 IopInitDeviceTreeTraverseContext(
2946 IopActionInitChildServices
,
2949 return IopTraverseDeviceTree(&Context
);
2952 static NTSTATUS INIT_FUNCTION
2953 IopEnumerateDetectedDevices(
2955 IN PUNICODE_STRING RelativePath OPTIONAL
,
2957 IN BOOLEAN EnumerateSubKeys
,
2958 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2959 IN ULONG ParentBootResourcesLength
)
2961 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2962 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2963 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2964 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2965 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2966 OBJECT_ATTRIBUTES ObjectAttributes
;
2967 HANDLE hDevicesKey
= NULL
;
2968 HANDLE hDeviceKey
= NULL
;
2969 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2970 UNICODE_STRING Level2NameU
;
2971 WCHAR Level2Name
[5];
2972 ULONG IndexDevice
= 0;
2974 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2975 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2976 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2977 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2978 UNICODE_STRING DeviceName
, ValueName
;
2980 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2981 ULONG BootResourcesLength
;
2984 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2985 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2986 static ULONG DeviceIndexSerial
= 0;
2987 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2988 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2989 static ULONG DeviceIndexKeyboard
= 0;
2990 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2991 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2992 static ULONG DeviceIndexMouse
= 0;
2993 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
2994 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
2995 static ULONG DeviceIndexParallel
= 0;
2996 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
2997 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
2998 static ULONG DeviceIndexFloppy
= 0;
2999 UNICODE_STRING HardwareIdKey
;
3000 PUNICODE_STRING pHardwareId
;
3001 ULONG DeviceIndex
= 0;
3002 PUCHAR CmResourceList
;
3007 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
3008 if (!NT_SUCCESS(Status
))
3010 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3015 hDevicesKey
= hBaseKey
;
3017 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3018 if (!pDeviceInformation
)
3020 DPRINT("ExAllocatePool() failed\n");
3021 Status
= STATUS_NO_MEMORY
;
3025 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3026 if (!pValueInformation
)
3028 DPRINT("ExAllocatePool() failed\n");
3029 Status
= STATUS_NO_MEMORY
;
3035 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3036 if (Status
== STATUS_NO_MORE_ENTRIES
)
3038 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3040 ExFreePool(pDeviceInformation
);
3041 DeviceInfoLength
= RequiredSize
;
3042 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3043 if (!pDeviceInformation
)
3045 DPRINT("ExAllocatePool() failed\n");
3046 Status
= STATUS_NO_MEMORY
;
3049 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3051 if (!NT_SUCCESS(Status
))
3053 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3058 /* Open device key */
3059 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
3060 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3062 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
3063 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
3064 if (!NT_SUCCESS(Status
))
3066 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3070 /* Read boot resources, and add then to parent ones */
3071 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3072 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3074 ExFreePool(pValueInformation
);
3075 ValueInfoLength
= RequiredSize
;
3076 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3077 if (!pValueInformation
)
3079 DPRINT("ExAllocatePool() failed\n");
3080 ZwDeleteKey(hLevel2Key
);
3081 Status
= STATUS_NO_MEMORY
;
3084 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3086 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
3088 BootResources
= ParentBootResources
;
3089 BootResourcesLength
= ParentBootResourcesLength
;
3091 else if (!NT_SUCCESS(Status
))
3093 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3096 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
3098 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
3103 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
3105 /* Concatenate current resources and parent ones */
3106 if (ParentBootResourcesLength
== 0)
3107 BootResourcesLength
= pValueInformation
->DataLength
;
3109 BootResourcesLength
= ParentBootResourcesLength
3110 + pValueInformation
->DataLength
3112 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
3115 DPRINT("ExAllocatePool() failed\n");
3118 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
3120 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
3122 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
3124 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
3126 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
3127 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
3128 ParentBootResourcesLength
- Header
);
3129 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
3133 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
3135 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
3136 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
3137 ParentBootResourcesLength
- Header
);
3139 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
3140 pValueInformation
->Data
+ Header
,
3141 pValueInformation
->DataLength
- Header
);
3142 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
3146 if (EnumerateSubKeys
)
3151 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3152 if (Status
== STATUS_NO_MORE_ENTRIES
)
3154 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3156 ExFreePool(pDeviceInformation
);
3157 DeviceInfoLength
= RequiredSize
;
3158 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
3159 if (!pDeviceInformation
)
3161 DPRINT("ExAllocatePool() failed\n");
3162 Status
= STATUS_NO_MEMORY
;
3165 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
3167 if (!NT_SUCCESS(Status
))
3169 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
3173 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
3174 DeviceName
.Buffer
= pDeviceInformation
->Name
;
3176 Status
= IopEnumerateDetectedDevices(
3182 BootResourcesLength
);
3183 if (!NT_SUCCESS(Status
))
3188 /* Read identifier */
3189 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3190 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
3192 ExFreePool(pValueInformation
);
3193 ValueInfoLength
= RequiredSize
;
3194 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
3195 if (!pValueInformation
)
3197 DPRINT("ExAllocatePool() failed\n");
3198 Status
= STATUS_NO_MEMORY
;
3201 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
3203 if (!NT_SUCCESS(Status
))
3205 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
3207 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
3210 ValueName
.Length
= ValueName
.MaximumLength
= 0;
3212 else if (pValueInformation
->Type
!= REG_SZ
)
3214 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
3219 /* Assign hardware id to this device */
3220 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
3221 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
3222 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
3223 ValueName
.Length
-= sizeof(WCHAR
);
3226 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
3228 pHardwareId
= &HardwareIdSerial
;
3229 DeviceIndex
= DeviceIndexSerial
++;
3231 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
3233 pHardwareId
= &HardwareIdKeyboard
;
3234 DeviceIndex
= DeviceIndexKeyboard
++;
3236 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
3238 pHardwareId
= &HardwareIdMouse
;
3239 DeviceIndex
= DeviceIndexMouse
++;
3241 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
3243 pHardwareId
= &HardwareIdParallel
;
3244 DeviceIndex
= DeviceIndexParallel
++;
3246 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
3248 pHardwareId
= &HardwareIdFloppy
;
3249 DeviceIndex
= DeviceIndexFloppy
++;
3253 /* Unknown key path */
3254 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
3258 /* Prepare hardware id key (hardware id value without final \0) */
3259 HardwareIdKey
= *pHardwareId
;
3260 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
3262 /* Add the detected device to Root key */
3263 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
3264 Status
= ZwCreateKey(
3270 ExpInTextModeSetup
? REG_OPTION_VOLATILE
: 0,
3272 if (!NT_SUCCESS(Status
))
3274 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3277 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
3278 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
3279 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
3280 Status
= ZwCreateKey(
3282 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
3286 ExpInTextModeSetup
? REG_OPTION_VOLATILE
: 0,
3288 ZwClose(hLevel1Key
);
3289 if (!NT_SUCCESS(Status
))
3291 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3294 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
3295 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3296 if (!NT_SUCCESS(Status
))
3298 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3299 ZwDeleteKey(hLevel2Key
);
3302 /* Create 'LogConf' subkey */
3303 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3304 Status
= ZwCreateKey(
3310 REG_OPTION_VOLATILE
,
3312 if (!NT_SUCCESS(Status
))
3314 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3315 ZwDeleteKey(hLevel2Key
);
3318 if (BootResourcesLength
>= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
3320 CmResourceList
= ExAllocatePool(PagedPool
, BootResourcesLength
+ sizeof(ULONG
));
3321 if (!CmResourceList
)
3324 ZwDeleteKey(hLevel2Key
);
3328 /* Add the list count (1st member of CM_RESOURCE_LIST) */
3330 RtlCopyMemory(CmResourceList
,
3334 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
3335 RtlCopyMemory(CmResourceList
+ sizeof(ULONG
),
3337 BootResourcesLength
);
3339 /* Save boot resources to 'LogConf\BootConfig' */
3340 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_RESOURCE_LIST
, CmResourceList
, BootResourcesLength
+ sizeof(ULONG
));
3341 if (!NT_SUCCESS(Status
))
3343 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3345 ZwDeleteKey(hLevel2Key
);
3352 if (BootResources
&& BootResources
!= ParentBootResources
)
3354 ExFreePool(BootResources
);
3355 BootResources
= NULL
;
3359 ZwClose(hLevel2Key
);
3364 ZwClose(hDeviceKey
);
3369 Status
= STATUS_SUCCESS
;
3372 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
3373 ZwClose(hDevicesKey
);
3375 ZwClose(hDeviceKey
);
3376 if (pDeviceInformation
)
3377 ExFreePool(pDeviceInformation
);
3378 if (pValueInformation
)
3379 ExFreePool(pValueInformation
);
3383 static BOOLEAN INIT_FUNCTION
3384 IopIsFirmwareMapperDisabled(VOID
)
3386 UNICODE_STRING KeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CURRENTCONTROLSET\\Control\\Pnp");
3387 UNICODE_STRING KeyNameU
= RTL_CONSTANT_STRING(L
"DisableFirmwareMapper");
3388 OBJECT_ATTRIBUTES ObjectAttributes
;
3390 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
;
3391 ULONG DesiredLength
, Length
;
3395 InitializeObjectAttributes(&ObjectAttributes
, &KeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3396 Status
= ZwOpenKey(&hPnpKey
, KEY_QUERY_VALUE
, &ObjectAttributes
);
3397 if (NT_SUCCESS(Status
))
3399 Status
= ZwQueryValueKey(hPnpKey
,
3401 KeyValuePartialInformation
,
3405 if ((Status
== STATUS_BUFFER_TOO_SMALL
) ||
3406 (Status
== STATUS_BUFFER_OVERFLOW
))
3408 Length
= DesiredLength
;
3409 KeyInformation
= ExAllocatePool(PagedPool
, Length
);
3412 Status
= ZwQueryValueKey(hPnpKey
,
3414 KeyValuePartialInformation
,
3418 if (NT_SUCCESS(Status
) && KeyInformation
->DataLength
== sizeof(ULONG
))
3420 KeyValue
= (ULONG
)(*KeyInformation
->Data
);
3424 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed\n", &KeyPathU
, &KeyNameU
);
3427 ExFreePool(KeyInformation
);
3431 DPRINT1("Failed to allocate memory for registry query\n");
3436 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed with status 0x%08lx\n", &KeyPathU
, &KeyNameU
, Status
);
3443 DPRINT1("ZwOpenKey(%wZ) failed with status 0x%08lx\n", &KeyPathU
, Status
);
3446 DPRINT("Firmware mapper is %s\n", KeyValue
!= 0 ? "disabled" : "enabled");
3448 return (KeyValue
!= 0) ? TRUE
: FALSE
;
3454 IopUpdateRootKey(VOID
)
3456 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
3457 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
3458 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3459 OBJECT_ATTRIBUTES ObjectAttributes
;
3460 HANDLE hEnum
, hRoot
;
3463 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3464 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3465 if (!NT_SUCCESS(Status
))
3467 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3471 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
3472 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3474 if (!NT_SUCCESS(Status
))
3476 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3480 if (!IopIsFirmwareMapperDisabled())
3482 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
3483 if (!NT_SUCCESS(Status
))
3485 /* Nothing to do, don't return with an error status */
3486 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3488 return STATUS_SUCCESS
;
3490 Status
= IopEnumerateDetectedDevices(
3501 /* Enumeration is disabled */
3502 Status
= STATUS_SUCCESS
;
3512 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
3514 PUNICODE_STRING Name
,
3515 ACCESS_MASK DesiredAccess
)
3517 OBJECT_ATTRIBUTES ObjectAttributes
;
3524 InitializeObjectAttributes(&ObjectAttributes
,
3526 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3530 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
3537 IopCreateRegistryKeyEx(OUT PHANDLE Handle
,
3538 IN HANDLE RootHandle OPTIONAL
,
3539 IN PUNICODE_STRING KeyName
,
3540 IN ACCESS_MASK DesiredAccess
,
3541 IN ULONG CreateOptions
,
3542 OUT PULONG Disposition OPTIONAL
)
3544 OBJECT_ATTRIBUTES ObjectAttributes
;
3545 ULONG KeyDisposition
, RootHandleIndex
= 0, i
= 1, NestedCloseLevel
= 0;
3547 HANDLE HandleArray
[2];
3548 BOOLEAN Recursing
= TRUE
;
3550 UNICODE_STRING KeyString
;
3551 NTSTATUS Status
= STATUS_SUCCESS
;
3554 /* P1 is start, pp is end */
3555 p1
= KeyName
->Buffer
;
3556 pp
= (PVOID
)((ULONG_PTR
)p1
+ KeyName
->Length
);
3558 /* Create the target key */
3559 InitializeObjectAttributes(&ObjectAttributes
,
3561 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3564 Status
= ZwCreateKey(&HandleArray
[i
],
3572 /* Now we check if this failed */
3573 if ((Status
== STATUS_OBJECT_NAME_NOT_FOUND
) && (RootHandle
))
3575 /* Target key failed, so we'll need to create its parent. Setup array */
3576 HandleArray
[0] = NULL
;
3577 HandleArray
[1] = RootHandle
;
3579 /* Keep recursing for each missing parent */
3582 /* And if we're deep enough, close the last handle */
3583 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
3585 /* We're setup to ping-pong between the two handle array entries */
3586 RootHandleIndex
= i
;
3589 /* Clear the one we're attempting to open now */
3590 HandleArray
[i
] = NULL
;
3592 /* Process the parent key name */
3593 for (p
= p1
; ((p
< pp
) && (*p
!= OBJ_NAME_PATH_SEPARATOR
)); p
++);
3594 Length
= (USHORT
)(p
- p1
) * sizeof(WCHAR
);
3596 /* Is there a parent name? */
3599 /* Build the unicode string for it */
3600 KeyString
.Buffer
= p1
;
3601 KeyString
.Length
= KeyString
.MaximumLength
= Length
;
3603 /* Now try opening the parent */
3604 InitializeObjectAttributes(&ObjectAttributes
,
3606 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3607 HandleArray
[RootHandleIndex
],
3609 Status
= ZwCreateKey(&HandleArray
[i
],
3616 if (NT_SUCCESS(Status
))
3618 /* It worked, we have one more handle */
3623 /* Parent key creation failed, abandon loop */
3630 /* We don't have a parent name, probably corrupted key name */
3631 Status
= STATUS_INVALID_PARAMETER
;
3636 /* Now see if there's more parents to create */
3638 if ((p
== pp
) || (p1
== pp
))
3640 /* We're done, hopefully successfully, so stop */
3645 /* Outer loop check for handle nesting that requires closing the top handle */
3646 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
3649 /* Check if we broke out of the loop due to success */
3650 if (NT_SUCCESS(Status
))
3652 /* Return the target handle (we closed all the parent ones) and disposition */
3653 *Handle
= HandleArray
[i
];
3654 if (Disposition
) *Disposition
= KeyDisposition
;
3657 /* Return the success state */
3663 IopGetRegistryValue(IN HANDLE Handle
,
3665 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
3667 UNICODE_STRING ValueString
;
3669 PKEY_VALUE_FULL_INFORMATION FullInformation
;
3673 RtlInitUnicodeString(&ValueString
, ValueName
);
3675 Status
= ZwQueryValueKey(Handle
,
3677 KeyValueFullInformation
,
3681 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
3682 (Status
!= STATUS_BUFFER_TOO_SMALL
))
3687 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
3688 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
3690 Status
= ZwQueryValueKey(Handle
,
3692 KeyValueFullInformation
,
3696 if (!NT_SUCCESS(Status
))
3698 ExFreePool(FullInformation
);
3702 *Information
= FullInformation
;
3703 return STATUS_SUCCESS
;
3706 RTL_GENERIC_COMPARE_RESULTS
3708 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3709 IN PVOID FirstStruct
,
3710 IN PVOID SecondStruct
)
3718 // The allocation function is called by the generic table package whenever
3719 // it needs to allocate memory for the table.
3724 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3734 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3743 PpInitializeDeviceReferenceTable(VOID
)
3745 /* Setup the guarded mutex and AVL table */
3746 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3747 RtlInitializeGenericTableAvl(
3748 &PpDeviceReferenceTable
,
3749 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3750 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3751 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3759 /* Initialize the resource when accessing device registry data */
3760 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3762 /* Setup the device reference AVL table */
3763 PpInitializeDeviceReferenceTable();
3771 /* Check the initialization phase */
3772 switch (ExpInitializationPhase
)
3777 return PiInitPhase0();
3783 //return PiInitPhase1();
3787 /* Don't know any other phase! Bugcheck! */
3788 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
3793 LONG IopNumberDeviceNodes
;
3797 PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3799 PDEVICE_NODE DeviceNode
;
3803 DeviceNode
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(DEVICE_NODE
), TAG_IO_DEVNODE
);
3804 if (!DeviceNode
) return DeviceNode
;
3807 InterlockedIncrement(&IopNumberDeviceNodes
);
3810 RtlZeroMemory(DeviceNode
, sizeof(DEVICE_NODE
));
3811 DeviceNode
->InterfaceType
= InterfaceTypeUndefined
;
3812 DeviceNode
->BusNumber
= -1;
3813 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
3814 DeviceNode
->ChildBusNumber
= -1;
3815 DeviceNode
->ChildBusTypeIndex
= -1;
3816 // KeInitializeEvent(&DeviceNode->EnumerationMutex, SynchronizationEvent, TRUE);
3817 InitializeListHead(&DeviceNode
->DeviceArbiterList
);
3818 InitializeListHead(&DeviceNode
->DeviceTranslatorList
);
3819 InitializeListHead(&DeviceNode
->TargetDeviceNotify
);
3820 InitializeListHead(&DeviceNode
->DockInfo
.ListEntry
);
3821 InitializeListHead(&DeviceNode
->PendedSetInterfaceState
);
3823 /* Check if there is a PDO */
3824 if (PhysicalDeviceObject
)
3826 /* Link it and remove the init flag */
3827 DeviceNode
->PhysicalDeviceObject
= PhysicalDeviceObject
;
3828 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= DeviceNode
;
3829 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3832 /* Return the node */
3836 /* PUBLIC FUNCTIONS **********************************************************/
3840 PnpBusTypeGuidGet(IN USHORT Index
,
3841 IN LPGUID BusTypeGuid
)
3843 NTSTATUS Status
= STATUS_SUCCESS
;
3845 /* Acquire the lock */
3846 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
3849 if (Index
< PnpBusTypeGuidList
->GuidCount
)
3852 RtlCopyMemory(BusTypeGuid
, &PnpBusTypeGuidList
->Guids
[Index
], sizeof(GUID
));
3857 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
3860 /* Release lock and return status */
3861 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
3867 PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject
,
3868 IN PHANDLE DeviceInstanceHandle
,
3869 IN ACCESS_MASK DesiredAccess
)
3873 PDEVICE_NODE DeviceNode
;
3874 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
3877 /* Open the enum key */
3878 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
3882 if (!NT_SUCCESS(Status
)) return Status
;
3884 /* Make sure we have an instance path */
3885 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3886 if ((DeviceNode
) && (DeviceNode
->InstancePath
.Length
))
3888 /* Get the instance key */
3889 Status
= IopOpenRegistryKeyEx(DeviceInstanceHandle
,
3891 &DeviceNode
->InstancePath
,
3897 Status
= STATUS_INVALID_DEVICE_REQUEST
;
3900 /* Close the handle and return status */
3907 PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList
)
3909 ULONG FinalSize
, PartialSize
, EntrySize
, i
, j
;
3910 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
3911 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
3913 /* If we don't have one, that's easy */
3914 if (!ResourceList
) return 0;
3916 /* Start with the minimum size possible */
3917 FinalSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
3919 /* Loop each full descriptor */
3920 FullDescriptor
= ResourceList
->List
;
3921 for (i
= 0; i
< ResourceList
->Count
; i
++)
3923 /* Start with the minimum size possible */
3924 PartialSize
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
) +
3925 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
);
3927 /* Loop each partial descriptor */
3928 PartialDescriptor
= FullDescriptor
->PartialResourceList
.PartialDescriptors
;
3929 for (j
= 0; j
< FullDescriptor
->PartialResourceList
.Count
; j
++)
3931 /* Start with the minimum size possible */
3932 EntrySize
= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
3934 /* Check if there is extra data */
3935 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
3938 EntrySize
+= PartialDescriptor
->u
.DeviceSpecificData
.DataSize
;
3941 /* The size of partial descriptors is bigger */
3942 PartialSize
+= EntrySize
;
3944 /* Go to the next partial descriptor */
3945 PartialDescriptor
= (PVOID
)((ULONG_PTR
)PartialDescriptor
+ EntrySize
);
3948 /* The size of full descriptors is bigger */
3949 FinalSize
+= PartialSize
;
3951 /* Go to the next full descriptor */
3952 FullDescriptor
= (PVOID
)((ULONG_PTR
)FullDescriptor
+ PartialSize
);
3955 /* Return the final size */
3961 PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject
,
3966 IN PULONG BufferLength
)
3969 HANDLE KeyHandle
, SubHandle
;
3970 UNICODE_STRING KeyString
;
3971 PKEY_VALUE_FULL_INFORMATION KeyValueInfo
= NULL
;
3975 /* Find the instance key */
3976 Status
= PnpDeviceObjectToDeviceInstance(DeviceObject
, &KeyHandle
, KEY_READ
);
3977 if (NT_SUCCESS(Status
))
3979 /* Check for name given by caller */
3983 RtlInitUnicodeString(&KeyString
, KeyName
);
3984 Status
= IopOpenRegistryKeyEx(&SubHandle
,
3988 if (NT_SUCCESS(Status
))
3990 /* And use this handle instead */
3992 KeyHandle
= SubHandle
;
3996 /* Check if sub-key handle succeeded (or no-op if no key name given) */
3997 if (NT_SUCCESS(Status
))
3999 /* Now get the size of the property */
4000 Status
= IopGetRegistryValue(KeyHandle
,
4009 /* Fail if any of the registry operations failed */
4010 if (!NT_SUCCESS(Status
)) return Status
;
4012 /* Check how much data we have to copy */
4013 Length
= KeyValueInfo
->DataLength
;
4014 if (*BufferLength
>= Length
)
4016 /* Check for a match in the value type */
4017 if (KeyValueInfo
->Type
== ValueType
)
4020 RtlCopyMemory(Buffer
,
4021 (PVOID
)((ULONG_PTR
)KeyValueInfo
+
4022 KeyValueInfo
->DataOffset
),
4027 /* Invalid registry property type, fail */
4028 Status
= STATUS_INVALID_PARAMETER_2
;
4033 /* Buffer is too small to hold data */
4034 Status
= STATUS_BUFFER_TOO_SMALL
;
4037 /* Return the required buffer length, free the buffer, and return status */
4038 *BufferLength
= Length
;
4039 ExFreePool(KeyValueInfo
);
4043 #define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;}
4044 #define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;}
4045 #define PIP_UNIMPLEMENTED() {UNIMPLEMENTED_DBGBREAK(); break;}
4052 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
4053 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
4054 IN ULONG BufferLength
,
4055 OUT PVOID PropertyBuffer
,
4056 OUT PULONG ResultLength
)
4058 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
4059 DEVICE_CAPABILITIES DeviceCaps
;
4060 ULONG ReturnLength
= 0, Length
= 0, ValueType
;
4061 PWCHAR ValueName
= NULL
, EnumeratorNameEnd
, DeviceInstanceName
;
4063 NTSTATUS Status
= STATUS_BUFFER_TOO_SMALL
;
4065 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
4066 BOOLEAN NullTerminate
= FALSE
;
4068 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
4070 /* Assume failure */
4073 /* Only PDOs can call this */
4074 if (!DeviceNode
) return STATUS_INVALID_DEVICE_REQUEST
;
4076 /* Handle all properties */
4077 switch (DeviceProperty
)
4079 case DevicePropertyBusTypeGuid
:
4081 /* Get the GUID from the internal cache */
4082 Status
= PnpBusTypeGuidGet(DeviceNode
->ChildBusTypeIndex
, &BusTypeGuid
);
4083 if (!NT_SUCCESS(Status
)) return Status
;
4085 /* This is the format of the returned data */
4086 PIP_RETURN_DATA(sizeof(GUID
), &BusTypeGuid
);
4088 case DevicePropertyLegacyBusType
:
4090 /* Validate correct interface type */
4091 if (DeviceNode
->ChildInterfaceType
== InterfaceTypeUndefined
)
4092 return STATUS_OBJECT_NAME_NOT_FOUND
;
4094 /* This is the format of the returned data */
4095 PIP_RETURN_DATA(sizeof(INTERFACE_TYPE
), &DeviceNode
->ChildInterfaceType
);
4097 case DevicePropertyBusNumber
:
4099 /* Validate correct bus number */
4100 if ((DeviceNode
->ChildBusNumber
& 0x80000000) == 0x80000000)
4101 return STATUS_OBJECT_NAME_NOT_FOUND
;
4103 /* This is the format of the returned data */
4104 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceNode
->ChildBusNumber
);
4106 case DevicePropertyEnumeratorName
:
4108 /* Get the instance path */
4109 DeviceInstanceName
= DeviceNode
->InstancePath
.Buffer
;
4112 ASSERT((BufferLength
& 1) == 0);
4113 ASSERT(DeviceInstanceName
!= NULL
);
4115 /* Get the name from the path */
4116 EnumeratorNameEnd
= wcschr(DeviceInstanceName
, OBJ_NAME_PATH_SEPARATOR
);
4117 ASSERT(EnumeratorNameEnd
);
4119 /* This string needs to be NULL-terminated */
4120 NullTerminate
= TRUE
;
4122 /* This is the format of the returned data */
4123 PIP_RETURN_DATA((ULONG
)(EnumeratorNameEnd
- DeviceInstanceName
) * sizeof(WCHAR
),
4124 DeviceInstanceName
);
4126 case DevicePropertyAddress
:
4128 /* Query the device caps */
4129 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
4130 if (!NT_SUCCESS(Status
) || (DeviceCaps
.Address
== MAXULONG
))
4131 return STATUS_OBJECT_NAME_NOT_FOUND
;
4133 /* This is the format of the returned data */
4134 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceCaps
.Address
);
4136 case DevicePropertyBootConfigurationTranslated
:
4138 /* Validate we have resources */
4139 if (!DeviceNode
->BootResources
)
4140 // if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field
4142 /* No resources will still fake success, but with 0 bytes */
4144 return STATUS_SUCCESS
;
4147 /* This is the format of the returned data */
4148 PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode
->BootResources
), // FIXFIX: Should use BootResourcesTranslated
4149 DeviceNode
->BootResources
); // FIXFIX: Should use BootResourcesTranslated
4151 case DevicePropertyPhysicalDeviceObjectName
:
4153 /* Sanity check for Unicode-sized string */
4154 ASSERT((BufferLength
& 1) == 0);
4156 /* Allocate name buffer */
4157 Length
= BufferLength
+ sizeof(OBJECT_NAME_INFORMATION
);
4158 ObjectNameInfo
= ExAllocatePool(PagedPool
, Length
);
4159 if (!ObjectNameInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
4161 /* Query the PDO name */
4162 Status
= ObQueryNameString(DeviceObject
,
4166 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
4168 /* It's up to the caller to try again */
4169 Status
= STATUS_BUFFER_TOO_SMALL
;
4172 /* This string needs to be NULL-terminated */
4173 NullTerminate
= TRUE
;
4175 /* Return if successful */
4176 if (NT_SUCCESS(Status
)) PIP_RETURN_DATA(ObjectNameInfo
->Name
.Length
,
4177 ObjectNameInfo
->Name
.Buffer
);
4179 /* Let the caller know how big the name is */
4180 *ResultLength
-= sizeof(OBJECT_NAME_INFORMATION
);
4183 case DevicePropertyRemovalPolicy
:
4184 PIP_RETURN_DATA(sizeof(UCHAR
), &DeviceNode
->RemovalPolicy
);
4186 /* Handle the registry-based properties */
4187 case DevicePropertyUINumber
:
4188 PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER
, REG_DWORD
);
4189 case DevicePropertyLocationInformation
:
4190 PIP_REGISTRY_DATA(REGSTR_VAL_LOCATION_INFORMATION
, REG_SZ
);
4191 case DevicePropertyDeviceDescription
:
4192 PIP_REGISTRY_DATA(REGSTR_VAL_DEVDESC
, REG_SZ
);
4193 case DevicePropertyHardwareID
:
4194 PIP_REGISTRY_DATA(REGSTR_VAL_HARDWAREID
, REG_MULTI_SZ
);
4195 case DevicePropertyCompatibleIDs
:
4196 PIP_REGISTRY_DATA(REGSTR_VAL_COMPATIBLEIDS
, REG_MULTI_SZ
);
4197 case DevicePropertyBootConfiguration
:
4198 PIP_REGISTRY_DATA(REGSTR_VAL_BOOTCONFIG
, REG_RESOURCE_LIST
);
4199 case DevicePropertyClassName
:
4200 PIP_REGISTRY_DATA(REGSTR_VAL_CLASS
, REG_SZ
);
4201 case DevicePropertyClassGuid
:
4202 PIP_REGISTRY_DATA(REGSTR_VAL_CLASSGUID
, REG_SZ
);
4203 case DevicePropertyDriverKeyName
:
4204 PIP_REGISTRY_DATA(REGSTR_VAL_DRIVER
, REG_SZ
);
4205 case DevicePropertyManufacturer
:
4206 PIP_REGISTRY_DATA(REGSTR_VAL_MFG
, REG_SZ
);
4207 case DevicePropertyFriendlyName
:
4208 PIP_REGISTRY_DATA(REGSTR_VAL_FRIENDLYNAME
, REG_SZ
);
4209 case DevicePropertyContainerID
:
4210 //PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7
4211 PIP_UNIMPLEMENTED();
4213 case DevicePropertyInstallState
:
4214 PIP_REGISTRY_DATA(REGSTR_VAL_CONFIGFLAGS
, REG_DWORD
);
4216 case DevicePropertyResourceRequirements
:
4217 PIP_UNIMPLEMENTED();
4218 case DevicePropertyAllocatedResources
:
4219 PIP_UNIMPLEMENTED();
4221 return STATUS_INVALID_PARAMETER_2
;
4224 /* Having a registry value name implies registry data */
4227 /* We know up-front how much data to expect */
4228 *ResultLength
= BufferLength
;
4230 /* Go get the data, use the LogConf subkey if necessary */
4231 Status
= PiGetDeviceRegistryProperty(DeviceObject
,
4235 DevicePropertyBootConfiguration
) ?
4240 else if (NT_SUCCESS(Status
))
4242 /* We know up-front how much data to expect, check the caller's buffer */
4243 *ResultLength
= ReturnLength
+ (NullTerminate
? sizeof(UNICODE_NULL
) : 0);
4244 if (*ResultLength
<= BufferLength
)
4246 /* Buffer is all good, copy the data */
4247 RtlCopyMemory(PropertyBuffer
, Data
, ReturnLength
);
4249 /* Check if we need to NULL-terminate the string */
4252 /* Terminate the string */
4253 ((PWCHAR
)PropertyBuffer
)[ReturnLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
4256 /* This is the success path */
4257 Status
= STATUS_SUCCESS
;
4262 Status
= STATUS_BUFFER_TOO_SMALL
;
4266 /* Free any allocation we may have made, and return the status code */
4267 if (ObjectNameInfo
) ExFreePool(ObjectNameInfo
);
4276 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4278 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(PhysicalDeviceObject
);
4279 IO_STACK_LOCATION Stack
;
4282 IO_STATUS_BLOCK IoStatusBlock
;
4284 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
4285 Stack
.MajorFunction
= IRP_MJ_PNP
;
4286 Stack
.MinorFunction
= IRP_MN_QUERY_PNP_DEVICE_STATE
;
4288 Status
= IopSynchronousCall(PhysicalDeviceObject
, &Stack
, (PVOID
*)&PnPFlags
);
4289 if (!NT_SUCCESS(Status
))
4291 if (Status
!= STATUS_NOT_SUPPORTED
)
4293 DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE failed with status 0x%lx\n", Status
);
4298 if (PnPFlags
& PNP_DEVICE_NOT_DISABLEABLE
)
4299 DeviceNode
->UserFlags
|= DNUF_NOT_DISABLEABLE
;
4301 DeviceNode
->UserFlags
&= ~DNUF_NOT_DISABLEABLE
;
4303 if (PnPFlags
& PNP_DEVICE_DONT_DISPLAY_IN_UI
)
4304 DeviceNode
->UserFlags
|= DNUF_DONT_SHOW_IN_UI
;
4306 DeviceNode
->UserFlags
&= ~DNUF_DONT_SHOW_IN_UI
;
4308 if ((PnPFlags
& PNP_DEVICE_REMOVED
) ||
4309 ((PnPFlags
& PNP_DEVICE_FAILED
) && !(PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
)))
4311 /* Flag it if it's failed */
4312 if (PnPFlags
& PNP_DEVICE_FAILED
) DeviceNode
->Problem
= CM_PROB_FAILED_POST_START
;
4314 /* Send removal IRPs to all of its children */
4315 IopPrepareDeviceForRemoval(PhysicalDeviceObject
, TRUE
);
4317 /* Send surprise removal */
4318 IopSendSurpriseRemoval(PhysicalDeviceObject
);
4320 /* Tell the user-mode PnP manager that a device was removed */
4321 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL
,
4322 &DeviceNode
->InstancePath
);
4324 IopSendRemoveDevice(PhysicalDeviceObject
);
4326 else if ((PnPFlags
& PNP_DEVICE_FAILED
) && (PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
))
4328 /* Stop for resource rebalance */
4329 Status
= IopStopDevice(DeviceNode
);
4330 if (!NT_SUCCESS(Status
))
4332 DPRINT1("Failed to stop device for rebalancing\n");
4334 /* Stop failed so don't rebalance */
4335 PnPFlags
&= ~PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
;
4339 /* Resource rebalance */
4340 if (PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
)
4342 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
4344 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
4346 IRP_MN_QUERY_RESOURCES
,
4348 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
4350 DeviceNode
->BootResources
=
4351 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
4352 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
4356 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
4357 DeviceNode
->BootResources
= NULL
;
4360 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
4362 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
4364 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
4366 if (NT_SUCCESS(Status
))
4368 DeviceNode
->ResourceRequirements
=
4369 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
4373 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
4374 DeviceNode
->ResourceRequirements
= NULL
;
4377 /* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by IopStartDevice */
4378 if (IopStartDevice(DeviceNode
) != STATUS_SUCCESS
)
4380 DPRINT1("Restart after resource rebalance failed\n");
4382 DeviceNode
->Flags
&= ~(DNF_STARTED
| DNF_START_REQUEST_PENDING
);
4383 DeviceNode
->Flags
|= DNF_START_FAILED
;
4385 IopRemoveDevice(DeviceNode
);
4391 * @name IoOpenDeviceRegistryKey
4393 * Open a registry key unique for a specified driver or device instance.
4395 * @param DeviceObject Device to get the registry key for.
4396 * @param DevInstKeyType Type of the key to return.
4397 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
4398 * @param DevInstRegKey Handle to the opened registry key on
4399 * successful return.
4407 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
4408 IN ULONG DevInstKeyType
,
4409 IN ACCESS_MASK DesiredAccess
,
4410 OUT PHANDLE DevInstRegKey
)
4412 static WCHAR RootKeyName
[] =
4413 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
4414 static WCHAR ProfileKeyName
[] =
4415 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
4416 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
4417 static WCHAR EnumKeyName
[] = L
"Enum\\";
4418 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
4419 ULONG KeyNameLength
;
4420 PWSTR KeyNameBuffer
;
4421 UNICODE_STRING KeyName
;
4422 ULONG DriverKeyLength
;
4423 OBJECT_ATTRIBUTES ObjectAttributes
;
4424 PDEVICE_NODE DeviceNode
= NULL
;
4427 DPRINT("IoOpenDeviceRegistryKey() called\n");
4429 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
4431 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
4432 return STATUS_INVALID_PARAMETER
;
4435 if (!IopIsValidPhysicalDeviceObject(DeviceObject
))
4436 return STATUS_INVALID_DEVICE_REQUEST
;
4437 DeviceNode
= IopGetDeviceNode(DeviceObject
);
4440 * Calculate the length of the base key name. This is the full
4441 * name for driver key or the name excluding "Device Parameters"
4442 * subkey for device key.
4445 KeyNameLength
= sizeof(RootKeyName
);
4446 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
4447 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
4448 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4450 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
4451 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
4452 0, NULL
, &DriverKeyLength
);
4453 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
4455 KeyNameLength
+= DriverKeyLength
;
4459 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
4460 DeviceNode
->InstancePath
.Length
;
4464 * Now allocate the buffer for the key name...
4467 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
4468 if (KeyNameBuffer
== NULL
)
4469 return STATUS_INSUFFICIENT_RESOURCES
;
4472 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
4473 KeyName
.Buffer
= KeyNameBuffer
;
4476 * ...and build the key name.
4479 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
4480 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
4482 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
4483 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
4485 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4487 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
4488 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
4489 DriverKeyLength
, KeyNameBuffer
+
4490 (KeyName
.Length
/ sizeof(WCHAR
)),
4492 if (!NT_SUCCESS(Status
))
4494 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
4495 ExFreePool(KeyNameBuffer
);
4498 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
4502 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
4503 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
4504 if (DeviceNode
->InstancePath
.Length
== 0)
4506 ExFreePool(KeyNameBuffer
);
4512 * Open the base key.
4514 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
4515 if (!NT_SUCCESS(Status
))
4517 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
4518 ExFreePool(KeyNameBuffer
);
4521 ExFreePool(KeyNameBuffer
);
4524 * For driver key we're done now.
4527 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4531 * Let's go further. For device key we must open "Device Parameters"
4532 * subkey and create it if it doesn't exist yet.
4535 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
4536 InitializeObjectAttributes(&ObjectAttributes
,
4538 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
4541 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
4542 0, NULL
, ExpInTextModeSetup
? REG_OPTION_VOLATILE
: 0, NULL
);
4543 ZwClose(ObjectAttributes
.RootDirectory
);
4550 IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
, BOOLEAN Force
)
4552 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
, FailedRemoveDevice
;
4556 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4557 ChildDeviceNode
= ParentDeviceNode
->Child
;
4558 while (ChildDeviceNode
!= NULL
)
4560 NextDeviceNode
= ChildDeviceNode
->Sibling
;
4561 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4563 Status
= IopPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
, Force
);
4564 if (!NT_SUCCESS(Status
))
4566 FailedRemoveDevice
= ChildDeviceNode
;
4570 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4571 ChildDeviceNode
= NextDeviceNode
;
4573 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4575 return STATUS_SUCCESS
;
4578 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4579 ChildDeviceNode
= ParentDeviceNode
->Child
;
4580 while (ChildDeviceNode
!= NULL
)
4582 NextDeviceNode
= ChildDeviceNode
->Sibling
;
4583 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4585 IopCancelPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
);
4587 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
4588 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
4589 if (ChildDeviceNode
== FailedRemoveDevice
)
4592 ChildDeviceNode
= NextDeviceNode
;
4594 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4596 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4603 IopSendRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
)
4605 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
;
4608 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4609 ChildDeviceNode
= ParentDeviceNode
->Child
;
4610 while (ChildDeviceNode
!= NULL
)
4612 NextDeviceNode
= ChildDeviceNode
->Sibling
;
4613 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4615 IopSendRemoveDevice(ChildDeviceNode
->PhysicalDeviceObject
);
4617 ChildDeviceNode
= NextDeviceNode
;
4619 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4621 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4626 IopCancelRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
)
4628 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
;
4631 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4632 ChildDeviceNode
= ParentDeviceNode
->Child
;
4633 while (ChildDeviceNode
!= NULL
)
4635 NextDeviceNode
= ChildDeviceNode
->Sibling
;
4636 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4638 IopCancelPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
);
4640 ChildDeviceNode
= NextDeviceNode
;
4642 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4644 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4649 IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
, BOOLEAN Force
)
4651 /* This function DOES NOT dereference the device objects on SUCCESS
4652 * but it DOES dereference device objects on FAILURE */
4657 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4659 Status
= IopPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
], Force
);
4660 if (!NT_SUCCESS(Status
))
4667 return STATUS_SUCCESS
;
4670 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
4671 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
4672 for (i
= 0; i
<= j
; i
++)
4674 IopCancelPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
]);
4675 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4676 DeviceRelations
->Objects
[i
] = NULL
;
4678 for (; i
< DeviceRelations
->Count
; i
++)
4680 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4681 DeviceRelations
->Objects
[i
] = NULL
;
4683 ExFreePool(DeviceRelations
);
4690 IopSendRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
)
4692 /* This function DOES dereference the device objects in all cases */
4696 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4698 IopSendRemoveDevice(DeviceRelations
->Objects
[i
]);
4699 DeviceRelations
->Objects
[i
] = NULL
;
4702 ExFreePool(DeviceRelations
);
4707 IopCancelRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
)
4709 /* This function DOES dereference the device objects in all cases */
4713 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4715 IopCancelPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
]);
4716 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4717 DeviceRelations
->Objects
[i
] = NULL
;
4720 ExFreePool(DeviceRelations
);
4724 IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
)
4726 IO_STACK_LOCATION Stack
;
4727 IO_STATUS_BLOCK IoStatusBlock
;
4728 PDEVICE_RELATIONS DeviceRelations
;
4731 IopCancelRemoveDevice(DeviceObject
);
4733 Stack
.Parameters
.QueryDeviceRelations
.Type
= RemovalRelations
;
4735 Status
= IopInitiatePnpIrp(DeviceObject
,
4737 IRP_MN_QUERY_DEVICE_RELATIONS
,
4739 if (!NT_SUCCESS(Status
))
4741 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4742 DeviceRelations
= NULL
;
4746 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4749 if (DeviceRelations
)
4750 IopCancelRemoveDeviceRelations(DeviceRelations
);
4754 IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject
, BOOLEAN Force
)
4756 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
4757 IO_STACK_LOCATION Stack
;
4758 IO_STATUS_BLOCK IoStatusBlock
;
4759 PDEVICE_RELATIONS DeviceRelations
;
4762 if ((DeviceNode
->UserFlags
& DNUF_NOT_DISABLEABLE
) && !Force
)
4764 DPRINT1("Removal not allowed for %wZ\n", &DeviceNode
->InstancePath
);
4765 return STATUS_UNSUCCESSFUL
;
4768 if (!Force
&& IopQueryRemoveDevice(DeviceObject
) != STATUS_SUCCESS
)
4770 DPRINT1("Removal vetoed by failing the query remove request\n");
4772 IopCancelRemoveDevice(DeviceObject
);
4774 return STATUS_UNSUCCESSFUL
;
4777 Stack
.Parameters
.QueryDeviceRelations
.Type
= RemovalRelations
;
4779 Status
= IopInitiatePnpIrp(DeviceObject
,
4781 IRP_MN_QUERY_DEVICE_RELATIONS
,
4783 if (!NT_SUCCESS(Status
))
4785 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4786 DeviceRelations
= NULL
;
4790 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4793 if (DeviceRelations
)
4795 Status
= IopQueryRemoveDeviceRelations(DeviceRelations
, Force
);
4796 if (!NT_SUCCESS(Status
))
4800 Status
= IopQueryRemoveChildDevices(DeviceNode
, Force
);
4801 if (!NT_SUCCESS(Status
))
4803 if (DeviceRelations
)
4804 IopCancelRemoveDeviceRelations(DeviceRelations
);
4808 if (DeviceRelations
)
4809 IopSendRemoveDeviceRelations(DeviceRelations
);
4810 IopSendRemoveChildDevices(DeviceNode
);
4812 return STATUS_SUCCESS
;
4816 IopRemoveDevice(PDEVICE_NODE DeviceNode
)
4820 DPRINT("Removing device: %wZ\n", &DeviceNode
->InstancePath
);
4822 Status
= IopPrepareDeviceForRemoval(DeviceNode
->PhysicalDeviceObject
, FALSE
);
4823 if (NT_SUCCESS(Status
))
4825 IopSendRemoveDevice(DeviceNode
->PhysicalDeviceObject
);
4826 IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL
,
4827 &DeviceNode
->InstancePath
);
4828 return STATUS_SUCCESS
;
4839 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4841 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(PhysicalDeviceObject
);
4842 PDEVICE_RELATIONS DeviceRelations
;
4843 IO_STATUS_BLOCK IoStatusBlock
;
4844 IO_STACK_LOCATION Stack
;
4845 DEVICE_CAPABILITIES Capabilities
;
4848 IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT
,
4849 &DeviceNode
->InstancePath
);
4851 if (IopQueryDeviceCapabilities(DeviceNode
, &Capabilities
) != STATUS_SUCCESS
)
4856 Stack
.Parameters
.QueryDeviceRelations
.Type
= EjectionRelations
;
4858 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
4860 IRP_MN_QUERY_DEVICE_RELATIONS
,
4862 if (!NT_SUCCESS(Status
))
4864 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4865 DeviceRelations
= NULL
;
4869 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4872 if (DeviceRelations
)
4874 Status
= IopQueryRemoveDeviceRelations(DeviceRelations
, FALSE
);
4875 if (!NT_SUCCESS(Status
))
4879 Status
= IopQueryRemoveChildDevices(DeviceNode
, FALSE
);
4880 if (!NT_SUCCESS(Status
))
4882 if (DeviceRelations
)
4883 IopCancelRemoveDeviceRelations(DeviceRelations
);
4887 if (IopPrepareDeviceForRemoval(PhysicalDeviceObject
, FALSE
) != STATUS_SUCCESS
)
4889 if (DeviceRelations
)
4890 IopCancelRemoveDeviceRelations(DeviceRelations
);
4891 IopCancelRemoveChildDevices(DeviceNode
);
4895 if (DeviceRelations
)
4896 IopSendRemoveDeviceRelations(DeviceRelations
);
4897 IopSendRemoveChildDevices(DeviceNode
);
4899 DeviceNode
->Problem
= CM_PROB_HELD_FOR_EJECT
;
4900 if (Capabilities
.EjectSupported
)
4902 if (IopSendEject(PhysicalDeviceObject
) != STATUS_SUCCESS
)
4909 DeviceNode
->Flags
|= DNF_DISABLED
;
4912 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT
,
4913 &DeviceNode
->InstancePath
);
4918 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED
,
4919 &DeviceNode
->InstancePath
);
4927 IoInvalidateDeviceRelations(
4928 IN PDEVICE_OBJECT DeviceObject
,
4929 IN DEVICE_RELATION_TYPE Type
)
4931 PDEVICE_ACTION_DATA Data
;
4934 Data
= ExAllocatePoolWithTag(NonPagedPool
,
4935 sizeof(DEVICE_ACTION_DATA
),
4940 ObReferenceObject(DeviceObject
);
4941 Data
->DeviceObject
= DeviceObject
;
4944 KeAcquireSpinLock(&IopDeviceActionLock
, &OldIrql
);
4945 InsertTailList(&IopDeviceActionRequestList
, &Data
->RequestListEntry
);
4946 if (IopDeviceActionInProgress
)
4948 KeReleaseSpinLock(&IopDeviceActionLock
, OldIrql
);
4951 IopDeviceActionInProgress
= TRUE
;
4952 KeReleaseSpinLock(&IopDeviceActionLock
, OldIrql
);
4954 ExInitializeWorkItem(&IopDeviceActionWorkItem
,
4955 IopDeviceActionWorker
,
4957 ExQueueWorkItem(&IopDeviceActionWorkItem
,
4966 IoSynchronousInvalidateDeviceRelations(
4967 IN PDEVICE_OBJECT DeviceObject
,
4968 IN DEVICE_RELATION_TYPE Type
)
4975 /* Enumerate the device */
4976 return IopEnumerateDevice(DeviceObject
);
4977 case PowerRelations
:
4978 /* Not handled yet */
4979 return STATUS_NOT_IMPLEMENTED
;
4980 case TargetDeviceRelation
:
4982 return STATUS_SUCCESS
;
4984 /* Ejection relations are not supported */
4985 return STATUS_NOT_SUPPORTED
;
4994 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
4996 IN PHYSICAL_ADDRESS BusAddress
,
4997 IN OUT PULONG AddressSpace
,
4998 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
5000 /* FIXME: Notify the resource arbiter */
5002 return HalTranslateBusAddress(InterfaceType
,