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 ULONG ExpInitializationPhase
;
25 extern BOOLEAN ExpInTextModeSetup
;
26 extern BOOLEAN PnpSystemInit
;
28 /* DATA **********************************************************************/
30 PDRIVER_OBJECT IopRootDriverObject
;
31 PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList
= NULL
;
33 typedef struct _INVALIDATE_DEVICE_RELATION_DATA
35 PDEVICE_OBJECT DeviceObject
;
36 DEVICE_RELATION_TYPE Type
;
37 PIO_WORKITEM WorkItem
;
38 } INVALIDATE_DEVICE_RELATION_DATA
, *PINVALIDATE_DEVICE_RELATION_DATA
;
40 /* FUNCTIONS *****************************************************************/
43 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
44 IN ULONG CreateOptions
,
48 IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
);
51 IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
, BOOLEAN Force
);
54 IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance
);
58 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject
)
60 return ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
)->DeviceNode
;
64 IopFixupDeviceId(PWCHAR String
)
66 SIZE_T Length
= wcslen(String
), i
;
68 for (i
= 0; i
< Length
; i
++)
70 if (String
[i
] == L
'\\')
77 IopInstallCriticalDevice(PDEVICE_NODE DeviceNode
)
80 HANDLE CriticalDeviceKey
, InstanceKey
;
81 OBJECT_ATTRIBUTES ObjectAttributes
;
82 UNICODE_STRING CriticalDeviceKeyU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\CriticalDeviceDatabase");
83 UNICODE_STRING CompatibleIdU
= RTL_CONSTANT_STRING(L
"CompatibleIDs");
84 UNICODE_STRING HardwareIdU
= RTL_CONSTANT_STRING(L
"HardwareID");
85 UNICODE_STRING ServiceU
= RTL_CONSTANT_STRING(L
"Service");
86 UNICODE_STRING ClassGuidU
= RTL_CONSTANT_STRING(L
"ClassGUID");
87 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
88 ULONG HidLength
= 0, CidLength
= 0, BufferLength
;
89 PWCHAR IdBuffer
, OriginalIdBuffer
;
91 /* Open the device instance key */
92 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
93 if (Status
!= STATUS_SUCCESS
)
96 Status
= ZwQueryValueKey(InstanceKey
,
98 KeyValuePartialInformation
,
102 if (Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_BUFFER_TOO_SMALL
)
104 ZwClose(InstanceKey
);
108 Status
= ZwQueryValueKey(InstanceKey
,
110 KeyValuePartialInformation
,
114 if (Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_BUFFER_TOO_SMALL
)
119 BufferLength
= HidLength
+ CidLength
;
120 BufferLength
-= (((CidLength
!= 0) ? 2 : 1) * FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
));
122 /* Allocate a buffer to hold data from both */
123 OriginalIdBuffer
= IdBuffer
= ExAllocatePool(PagedPool
, BufferLength
);
126 ZwClose(InstanceKey
);
130 /* Compute the buffer size */
131 if (HidLength
> CidLength
)
132 BufferLength
= HidLength
;
134 BufferLength
= CidLength
;
136 PartialInfo
= ExAllocatePool(PagedPool
, BufferLength
);
139 ZwClose(InstanceKey
);
140 ExFreePool(OriginalIdBuffer
);
144 Status
= ZwQueryValueKey(InstanceKey
,
146 KeyValuePartialInformation
,
150 if (Status
!= STATUS_SUCCESS
)
152 ExFreePool(PartialInfo
);
153 ExFreePool(OriginalIdBuffer
);
154 ZwClose(InstanceKey
);
158 /* Copy in HID info first (without 2nd terminating NULL if CID is present) */
159 HidLength
= PartialInfo
->DataLength
- ((CidLength
!= 0) ? sizeof(WCHAR
) : 0);
160 RtlCopyMemory(IdBuffer
, PartialInfo
->Data
, HidLength
);
164 Status
= ZwQueryValueKey(InstanceKey
,
166 KeyValuePartialInformation
,
170 if (Status
!= STATUS_SUCCESS
)
172 ExFreePool(PartialInfo
);
173 ExFreePool(OriginalIdBuffer
);
174 ZwClose(InstanceKey
);
179 CidLength
= PartialInfo
->DataLength
;
180 RtlCopyMemory(((PUCHAR
)IdBuffer
) + HidLength
, PartialInfo
->Data
, CidLength
);
183 /* Free our temp buffer */
184 ExFreePool(PartialInfo
);
186 InitializeObjectAttributes(&ObjectAttributes
,
188 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
191 Status
= ZwOpenKey(&CriticalDeviceKey
,
192 KEY_ENUMERATE_SUB_KEYS
,
194 if (!NT_SUCCESS(Status
))
196 /* The critical device database doesn't exist because
197 * we're probably in 1st stage setup, but it's ok */
198 ExFreePool(OriginalIdBuffer
);
199 ZwClose(InstanceKey
);
205 USHORT StringLength
= (USHORT
)wcslen(IdBuffer
) + 1, Index
;
207 IopFixupDeviceId(IdBuffer
);
209 /* Look through all subkeys for a match */
210 for (Index
= 0; TRUE
; Index
++)
213 PKEY_BASIC_INFORMATION BasicInfo
;
215 Status
= ZwEnumerateKey(CriticalDeviceKey
,
221 if (Status
== STATUS_NO_MORE_ENTRIES
)
223 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
225 UNICODE_STRING ChildIdNameU
, RegKeyNameU
;
227 BasicInfo
= ExAllocatePool(PagedPool
, NeededLength
);
231 ExFreePool(OriginalIdBuffer
);
232 ZwClose(CriticalDeviceKey
);
233 ZwClose(InstanceKey
);
237 Status
= ZwEnumerateKey(CriticalDeviceKey
,
243 if (Status
!= STATUS_SUCCESS
)
245 /* This shouldn't happen */
246 ExFreePool(BasicInfo
);
250 ChildIdNameU
.Buffer
= IdBuffer
;
251 ChildIdNameU
.MaximumLength
= ChildIdNameU
.Length
= (StringLength
- 1) * sizeof(WCHAR
);
252 RegKeyNameU
.Buffer
= BasicInfo
->Name
;
253 RegKeyNameU
.MaximumLength
= RegKeyNameU
.Length
= (USHORT
)BasicInfo
->NameLength
;
255 if (RtlEqualUnicodeString(&ChildIdNameU
, &RegKeyNameU
, TRUE
))
257 HANDLE ChildKeyHandle
;
259 InitializeObjectAttributes(&ObjectAttributes
,
261 OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
,
265 Status
= ZwOpenKey(&ChildKeyHandle
,
268 if (Status
!= STATUS_SUCCESS
)
270 ExFreePool(BasicInfo
);
274 /* Check if there's already a driver installed */
275 Status
= ZwQueryValueKey(InstanceKey
,
277 KeyValuePartialInformation
,
281 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
283 ExFreePool(BasicInfo
);
287 Status
= ZwQueryValueKey(ChildKeyHandle
,
289 KeyValuePartialInformation
,
293 if (Status
!= STATUS_BUFFER_OVERFLOW
&& Status
!= STATUS_BUFFER_TOO_SMALL
)
295 ExFreePool(BasicInfo
);
299 PartialInfo
= ExAllocatePool(PagedPool
, NeededLength
);
302 ExFreePool(OriginalIdBuffer
);
303 ExFreePool(BasicInfo
);
304 ZwClose(InstanceKey
);
305 ZwClose(ChildKeyHandle
);
306 ZwClose(CriticalDeviceKey
);
310 /* Read ClassGUID entry in the CDDB */
311 Status
= ZwQueryValueKey(ChildKeyHandle
,
313 KeyValuePartialInformation
,
317 if (Status
!= STATUS_SUCCESS
)
319 ExFreePool(BasicInfo
);
323 /* Write it to the ENUM key */
324 Status
= ZwSetValueKey(InstanceKey
,
329 PartialInfo
->DataLength
);
330 if (Status
!= STATUS_SUCCESS
)
332 ExFreePool(BasicInfo
);
333 ExFreePool(PartialInfo
);
334 ZwClose(ChildKeyHandle
);
338 Status
= ZwQueryValueKey(ChildKeyHandle
,
340 KeyValuePartialInformation
,
344 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
346 ExFreePool(PartialInfo
);
347 PartialInfo
= ExAllocatePool(PagedPool
, NeededLength
);
350 ExFreePool(OriginalIdBuffer
);
351 ExFreePool(BasicInfo
);
352 ZwClose(InstanceKey
);
353 ZwClose(ChildKeyHandle
);
354 ZwClose(CriticalDeviceKey
);
358 /* Read the service entry from the CDDB */
359 Status
= ZwQueryValueKey(ChildKeyHandle
,
361 KeyValuePartialInformation
,
365 if (Status
!= STATUS_SUCCESS
)
367 ExFreePool(BasicInfo
);
368 ExFreePool(PartialInfo
);
369 ZwClose(ChildKeyHandle
);
373 /* Write it to the ENUM key */
374 Status
= ZwSetValueKey(InstanceKey
,
379 PartialInfo
->DataLength
);
380 if (Status
!= STATUS_SUCCESS
)
382 ExFreePool(BasicInfo
);
383 ExFreePool(PartialInfo
);
384 ZwClose(ChildKeyHandle
);
388 DPRINT1("Installed service '%S' for critical device '%wZ'\n", PartialInfo
->Data
, &ChildIdNameU
);
392 DPRINT1("Installed NULL service for critical device '%wZ'\n", &ChildIdNameU
);
395 ExFreePool(OriginalIdBuffer
);
396 ExFreePool(PartialInfo
);
397 ExFreePool(BasicInfo
);
398 ZwClose(InstanceKey
);
399 ZwClose(ChildKeyHandle
);
400 ZwClose(CriticalDeviceKey
);
406 ExFreePool(BasicInfo
);
410 /* Umm, not sure what happened here */
415 /* Advance to the next ID */
416 IdBuffer
+= StringLength
;
419 ExFreePool(OriginalIdBuffer
);
420 ZwClose(InstanceKey
);
421 ZwClose(CriticalDeviceKey
);
426 IopInitializeDevice(PDEVICE_NODE DeviceNode
,
427 PDRIVER_OBJECT DriverObject
)
434 /* Special case for bus driven devices */
435 DeviceNode
->Flags
|= DNF_ADDED
;
436 return STATUS_SUCCESS
;
439 if (!DriverObject
->DriverExtension
->AddDevice
)
441 DeviceNode
->Flags
|= DNF_LEGACY_DRIVER
;
444 if (DeviceNode
->Flags
& DNF_LEGACY_DRIVER
)
446 DeviceNode
->Flags
|= DNF_ADDED
+ DNF_STARTED
;
447 return STATUS_SUCCESS
;
450 /* This is a Plug and Play driver */
451 DPRINT("Plug and Play driver found\n");
452 ASSERT(DeviceNode
->PhysicalDeviceObject
);
454 DPRINT("Calling %wZ->AddDevice(%wZ)\n",
455 &DriverObject
->DriverName
,
456 &DeviceNode
->InstancePath
);
457 Status
= DriverObject
->DriverExtension
->AddDevice(
458 DriverObject
, DeviceNode
->PhysicalDeviceObject
);
459 if (!NT_SUCCESS(Status
))
461 DPRINT1("%wZ->AddDevice(%wZ) failed with status 0x%x\n",
462 &DriverObject
->DriverName
,
463 &DeviceNode
->InstancePath
,
465 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
466 DeviceNode
->Problem
= CM_PROB_FAILED_ADD
;
470 Fdo
= IoGetAttachedDeviceReference(DeviceNode
->PhysicalDeviceObject
);
472 /* Check if we have a ACPI device (needed for power management) */
473 if (Fdo
->DeviceType
== FILE_DEVICE_ACPI
)
475 static BOOLEAN SystemPowerDeviceNodeCreated
= FALSE
;
477 /* There can be only one system power device */
478 if (!SystemPowerDeviceNodeCreated
)
480 PopSystemPowerDeviceNode
= DeviceNode
;
481 ObReferenceObject(PopSystemPowerDeviceNode
->PhysicalDeviceObject
);
482 SystemPowerDeviceNodeCreated
= TRUE
;
486 ObDereferenceObject(Fdo
);
488 IopDeviceNodeSetFlag(DeviceNode
, DNF_ADDED
);
490 return STATUS_SUCCESS
;
496 IopSendEject(IN PDEVICE_OBJECT DeviceObject
)
498 IO_STACK_LOCATION Stack
;
501 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
502 Stack
.MajorFunction
= IRP_MJ_PNP
;
503 Stack
.MinorFunction
= IRP_MN_EJECT
;
505 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
511 IopSendSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject
)
513 IO_STACK_LOCATION Stack
;
516 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
517 Stack
.MajorFunction
= IRP_MJ_PNP
;
518 Stack
.MinorFunction
= IRP_MN_SURPRISE_REMOVAL
;
520 /* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
521 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
527 IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
529 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
530 IO_STACK_LOCATION Stack
;
536 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING
,
537 &DeviceNode
->InstancePath
);
539 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
540 Stack
.MajorFunction
= IRP_MJ_PNP
;
541 Stack
.MinorFunction
= IRP_MN_QUERY_REMOVE_DEVICE
;
543 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
545 IopNotifyPlugPlayNotification(DeviceObject
,
546 EventCategoryTargetDeviceChange
,
547 &GUID_TARGET_DEVICE_QUERY_REMOVE
,
551 if (!NT_SUCCESS(Status
))
553 DPRINT1("Removal vetoed by %wZ\n", &DeviceNode
->InstancePath
);
554 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED
,
555 &DeviceNode
->InstancePath
);
564 IopQueryStopDevice(IN PDEVICE_OBJECT DeviceObject
)
566 IO_STACK_LOCATION Stack
;
569 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
570 Stack
.MajorFunction
= IRP_MJ_PNP
;
571 Stack
.MinorFunction
= IRP_MN_QUERY_STOP_DEVICE
;
573 return IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
579 IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
581 IO_STACK_LOCATION Stack
;
583 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
585 /* Drop all our state for this device in case it isn't really going away */
586 DeviceNode
->Flags
&= DNF_ENUMERATED
| DNF_PROCESSED
;
588 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
589 Stack
.MajorFunction
= IRP_MJ_PNP
;
590 Stack
.MinorFunction
= IRP_MN_REMOVE_DEVICE
;
592 /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
593 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
595 IopNotifyPlugPlayNotification(DeviceObject
,
596 EventCategoryTargetDeviceChange
,
597 &GUID_TARGET_DEVICE_REMOVE_COMPLETE
,
600 ObDereferenceObject(DeviceObject
);
606 IopCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject
)
608 IO_STACK_LOCATION Stack
;
611 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
612 Stack
.MajorFunction
= IRP_MJ_PNP
;
613 Stack
.MinorFunction
= IRP_MN_CANCEL_REMOVE_DEVICE
;
615 /* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
616 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
618 IopNotifyPlugPlayNotification(DeviceObject
,
619 EventCategoryTargetDeviceChange
,
620 &GUID_TARGET_DEVICE_REMOVE_CANCELLED
,
628 IopSendStopDevice(IN PDEVICE_OBJECT DeviceObject
)
630 IO_STACK_LOCATION Stack
;
633 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
634 Stack
.MajorFunction
= IRP_MJ_PNP
;
635 Stack
.MinorFunction
= IRP_MN_STOP_DEVICE
;
637 /* Drivers should never fail a IRP_MN_STOP_DEVICE request */
638 IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
643 IopStartDevice2(IN PDEVICE_OBJECT DeviceObject
)
645 IO_STACK_LOCATION Stack
;
646 PDEVICE_NODE DeviceNode
;
649 DEVICE_CAPABILITIES DeviceCapabilities
;
651 /* Get the device node */
652 DeviceNode
= IopGetDeviceNode(DeviceObject
);
654 ASSERT(!(DeviceNode
->Flags
& DNF_DISABLED
));
656 /* Build the I/O stack location */
657 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
658 Stack
.MajorFunction
= IRP_MJ_PNP
;
659 Stack
.MinorFunction
= IRP_MN_START_DEVICE
;
661 Stack
.Parameters
.StartDevice
.AllocatedResources
=
662 DeviceNode
->ResourceList
;
663 Stack
.Parameters
.StartDevice
.AllocatedResourcesTranslated
=
664 DeviceNode
->ResourceListTranslated
;
667 Status
= IopSynchronousCall(DeviceObject
, &Stack
, &Dummy
);
668 if (!NT_SUCCESS(Status
))
670 /* Send an IRP_MN_REMOVE_DEVICE request */
671 IopRemoveDevice(DeviceNode
);
673 /* Set the appropriate flag */
674 DeviceNode
->Flags
|= DNF_START_FAILED
;
675 DeviceNode
->Problem
= CM_PROB_FAILED_START
;
677 DPRINT1("Warning: PnP Start failed (%wZ) [Status: 0x%x]\n", &DeviceNode
->InstancePath
, Status
);
681 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n");
683 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
684 if (!NT_SUCCESS(Status
))
686 DPRINT1("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
689 /* Invalidate device state so IRP_MN_QUERY_PNP_DEVICE_STATE is sent */
690 IoInvalidateDeviceState(DeviceObject
);
692 /* Otherwise, mark us as started */
693 DeviceNode
->Flags
|= DNF_STARTED
;
694 DeviceNode
->Flags
&= ~DNF_STOPPED
;
696 /* We now need enumeration */
697 DeviceNode
->Flags
|= DNF_NEED_ENUMERATION_ONLY
;
702 IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode
)
704 PDEVICE_OBJECT DeviceObject
;
709 ASSERT((DeviceNode
->Flags
& DNF_ADDED
));
710 ASSERT((DeviceNode
->Flags
& (DNF_RESOURCE_ASSIGNED
|
711 DNF_RESOURCE_REPORTED
|
712 DNF_NO_RESOURCE_REQUIRED
)));
714 /* Get the device object */
715 DeviceObject
= DeviceNode
->PhysicalDeviceObject
;
717 /* Check if we're not started yet */
718 if (!(DeviceNode
->Flags
& DNF_STARTED
))
721 IopStartDevice2(DeviceObject
);
724 /* Do we need to query IDs? This happens in the case of manual reporting */
726 if (DeviceNode
->Flags
& DNF_NEED_QUERY_IDS
)
728 DPRINT1("Warning: Device node has DNF_NEED_QUERY_IDS\n");
729 /* And that case shouldn't happen yet */
734 /* Make sure we're started, and check if we need enumeration */
735 if ((DeviceNode
->Flags
& DNF_STARTED
) &&
736 (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
))
739 IoSynchronousInvalidateDeviceRelations(DeviceObject
, BusRelations
);
740 Status
= STATUS_SUCCESS
;
745 Status
= STATUS_SUCCESS
;
754 PDEVICE_NODE DeviceNode
)
758 DPRINT("Stopping device: %wZ\n", &DeviceNode
->InstancePath
);
760 Status
= IopQueryStopDevice(DeviceNode
->PhysicalDeviceObject
);
761 if (NT_SUCCESS(Status
))
763 IopSendStopDevice(DeviceNode
->PhysicalDeviceObject
);
765 DeviceNode
->Flags
&= ~(DNF_STARTED
| DNF_START_REQUEST_PENDING
);
766 DeviceNode
->Flags
|= DNF_STOPPED
;
768 return STATUS_SUCCESS
;
776 PDEVICE_NODE DeviceNode
)
779 HANDLE InstanceHandle
= INVALID_HANDLE_VALUE
, ControlHandle
= INVALID_HANDLE_VALUE
;
780 UNICODE_STRING KeyName
;
781 OBJECT_ATTRIBUTES ObjectAttributes
;
783 if (DeviceNode
->Flags
& DNF_DISABLED
)
784 return STATUS_SUCCESS
;
786 Status
= IopAssignDeviceResources(DeviceNode
);
787 if (!NT_SUCCESS(Status
))
791 IopStartAndEnumerateDevice(DeviceNode
);
793 /* FIX: Should be done in new device instance code */
794 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceHandle
);
795 if (!NT_SUCCESS(Status
))
798 /* FIX: Should be done in IoXxxPrepareDriverLoading */
800 RtlInitUnicodeString(&KeyName
, L
"Control");
801 InitializeObjectAttributes(&ObjectAttributes
,
803 OBJ_CASE_INSENSITIVE
,
806 Status
= ZwCreateKey(&ControlHandle
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
807 if (!NT_SUCCESS(Status
))
810 RtlInitUnicodeString(&KeyName
, L
"ActiveService");
811 Status
= ZwSetValueKey(ControlHandle
, &KeyName
, 0, REG_SZ
, DeviceNode
->ServiceName
.Buffer
, DeviceNode
->ServiceName
.Length
);
815 if (ControlHandle
!= INVALID_HANDLE_VALUE
)
816 ZwClose(ControlHandle
);
818 if (InstanceHandle
!= INVALID_HANDLE_VALUE
)
819 ZwClose(InstanceHandle
);
826 IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode
,
827 PDEVICE_CAPABILITIES DeviceCaps
)
829 IO_STATUS_BLOCK StatusBlock
;
830 IO_STACK_LOCATION Stack
;
833 UNICODE_STRING ValueName
;
835 /* Set up the Header */
836 RtlZeroMemory(DeviceCaps
, sizeof(DEVICE_CAPABILITIES
));
837 DeviceCaps
->Size
= sizeof(DEVICE_CAPABILITIES
);
838 DeviceCaps
->Version
= 1;
839 DeviceCaps
->Address
= -1;
840 DeviceCaps
->UINumber
= -1;
842 /* Set up the Stack */
843 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
844 Stack
.Parameters
.DeviceCapabilities
.Capabilities
= DeviceCaps
;
847 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
849 IRP_MN_QUERY_CAPABILITIES
,
851 if (!NT_SUCCESS(Status
))
853 DPRINT1("IRP_MN_QUERY_CAPABILITIES failed with status 0x%x\n", Status
);
857 DeviceNode
->CapabilityFlags
= *(PULONG
)((ULONG_PTR
)&DeviceCaps
->Version
+ sizeof(DeviceCaps
->Version
));
859 if (DeviceCaps
->NoDisplayInUI
)
860 DeviceNode
->UserFlags
|= DNUF_DONT_SHOW_IN_UI
;
862 DeviceNode
->UserFlags
&= ~DNUF_DONT_SHOW_IN_UI
;
864 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
865 if (NT_SUCCESS(Status
))
867 /* Set 'Capabilities' value */
868 RtlInitUnicodeString(&ValueName
, L
"Capabilities");
869 Status
= ZwSetValueKey(InstanceKey
,
873 (PVOID
)&DeviceNode
->CapabilityFlags
,
876 /* Set 'UINumber' value */
877 if (DeviceCaps
->UINumber
!= MAXULONG
)
879 RtlInitUnicodeString(&ValueName
, L
"UINumber");
880 Status
= ZwSetValueKey(InstanceKey
,
884 &DeviceCaps
->UINumber
,
893 IopAsynchronousInvalidateDeviceRelations(
894 IN PDEVICE_OBJECT DeviceObject
,
895 IN PVOID InvalidateContext
)
897 PINVALIDATE_DEVICE_RELATION_DATA Data
= InvalidateContext
;
899 IoSynchronousInvalidateDeviceRelations(
903 ObDereferenceObject(Data
->DeviceObject
);
904 IoFreeWorkItem(Data
->WorkItem
);
909 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
913 if (PopSystemPowerDeviceNode
)
915 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
916 *DeviceObject
= PopSystemPowerDeviceNode
->PhysicalDeviceObject
;
917 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
919 return STATUS_SUCCESS
;
922 return STATUS_UNSUCCESSFUL
;
927 IopGetBusTypeGuidIndex(LPGUID BusTypeGuid
)
929 USHORT i
= 0, FoundIndex
= 0xFFFF;
933 /* Acquire the lock */
934 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
936 /* Loop all entries */
937 while (i
< PnpBusTypeGuidList
->GuidCount
)
939 /* Try to find a match */
940 if (RtlCompareMemory(BusTypeGuid
,
941 &PnpBusTypeGuidList
->Guids
[i
],
942 sizeof(GUID
)) == sizeof(GUID
))
951 /* Check if we have to grow the list */
952 if (PnpBusTypeGuidList
->GuidCount
)
954 /* Calculate the new size */
955 NewSize
= sizeof(IO_BUS_TYPE_GUID_LIST
) +
956 (sizeof(GUID
) * PnpBusTypeGuidList
->GuidCount
);
958 /* Allocate the new copy */
959 NewList
= ExAllocatePool(PagedPool
, NewSize
);
963 ExFreePool(PnpBusTypeGuidList
);
967 /* Now copy them, decrease the size too */
968 NewSize
-= sizeof(GUID
);
969 RtlCopyMemory(NewList
, PnpBusTypeGuidList
, NewSize
);
971 /* Free the old list */
972 ExFreePool(PnpBusTypeGuidList
);
974 /* Use the new buffer */
975 PnpBusTypeGuidList
= NewList
;
978 /* Copy the new GUID */
979 RtlCopyMemory(&PnpBusTypeGuidList
->Guids
[PnpBusTypeGuidList
->GuidCount
],
983 /* The new entry is the index */
984 FoundIndex
= (USHORT
)PnpBusTypeGuidList
->GuidCount
;
985 PnpBusTypeGuidList
->GuidCount
++;
988 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
994 * Creates a device node
997 * ParentNode = Pointer to parent device node
998 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
999 * to have the root device node create one
1000 * (eg. for legacy drivers)
1001 * DeviceNode = Pointer to storage for created device node
1007 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
1008 PDEVICE_OBJECT PhysicalDeviceObject
,
1009 PUNICODE_STRING ServiceName
,
1010 PDEVICE_NODE
*DeviceNode
)
1015 UNICODE_STRING FullServiceName
;
1016 UNICODE_STRING LegacyPrefix
= RTL_CONSTANT_STRING(L
"LEGACY_");
1017 UNICODE_STRING UnknownDeviceName
= RTL_CONSTANT_STRING(L
"UNKNOWN");
1018 UNICODE_STRING KeyName
, ClassName
;
1019 PUNICODE_STRING ServiceName1
;
1021 UNICODE_STRING ClassGUID
;
1022 HANDLE InstanceHandle
;
1024 DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
1025 ParentNode
, PhysicalDeviceObject
, ServiceName
);
1027 Node
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(DEVICE_NODE
), TAG_IO_DEVNODE
);
1030 return STATUS_INSUFFICIENT_RESOURCES
;
1033 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
1036 ServiceName1
= &UnknownDeviceName
;
1038 ServiceName1
= ServiceName
;
1040 if (!PhysicalDeviceObject
)
1042 FullServiceName
.MaximumLength
= LegacyPrefix
.Length
+ ServiceName1
->Length
;
1043 FullServiceName
.Length
= 0;
1044 FullServiceName
.Buffer
= ExAllocatePool(PagedPool
, FullServiceName
.MaximumLength
);
1045 if (!FullServiceName
.Buffer
)
1047 ExFreePoolWithTag(Node
, TAG_IO_DEVNODE
);
1048 return STATUS_INSUFFICIENT_RESOURCES
;
1051 RtlAppendUnicodeStringToString(&FullServiceName
, &LegacyPrefix
);
1052 RtlAppendUnicodeStringToString(&FullServiceName
, ServiceName1
);
1054 Status
= PnpRootCreateDevice(&FullServiceName
, NULL
, &PhysicalDeviceObject
, &Node
->InstancePath
);
1055 if (!NT_SUCCESS(Status
))
1057 DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status
);
1058 ExFreePoolWithTag(Node
, TAG_IO_DEVNODE
);
1062 /* Create the device key for legacy drivers */
1063 Status
= IopCreateDeviceKeyPath(&Node
->InstancePath
, REG_OPTION_VOLATILE
, &InstanceHandle
);
1064 if (!NT_SUCCESS(Status
))
1066 ZwClose(InstanceHandle
);
1067 ExFreePoolWithTag(Node
, TAG_IO_DEVNODE
);
1068 ExFreePool(FullServiceName
.Buffer
);
1072 Node
->ServiceName
.Buffer
= ExAllocatePool(PagedPool
, ServiceName1
->Length
);
1073 if (!Node
->ServiceName
.Buffer
)
1075 ZwClose(InstanceHandle
);
1076 ExFreePoolWithTag(Node
, TAG_IO_DEVNODE
);
1077 ExFreePool(FullServiceName
.Buffer
);
1081 Node
->ServiceName
.MaximumLength
= ServiceName1
->Length
;
1082 Node
->ServiceName
.Length
= 0;
1084 RtlAppendUnicodeStringToString(&Node
->ServiceName
, ServiceName1
);
1088 RtlInitUnicodeString(&KeyName
, L
"Service");
1089 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName
->Buffer
, ServiceName
->Length
);
1092 if (NT_SUCCESS(Status
))
1094 RtlInitUnicodeString(&KeyName
, L
"Legacy");
1097 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_DWORD
, &LegacyValue
, sizeof(LegacyValue
));
1098 if (NT_SUCCESS(Status
))
1100 RtlInitUnicodeString(&KeyName
, L
"Class");
1102 RtlInitUnicodeString(&ClassName
, L
"LegacyDriver\0");
1103 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassName
.Buffer
, ClassName
.Length
+ sizeof(UNICODE_NULL
));
1104 if (NT_SUCCESS(Status
))
1106 RtlInitUnicodeString(&KeyName
, L
"ClassGUID");
1108 RtlInitUnicodeString(&ClassGUID
, L
"{8ECC055D-047F-11D1-A537-0000F8753ED1}\0");
1109 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ClassGUID
.Buffer
, ClassGUID
.Length
+ sizeof(UNICODE_NULL
));
1110 if (NT_SUCCESS(Status
))
1112 RtlInitUnicodeString(&KeyName
, L
"DeviceDesc");
1114 Status
= ZwSetValueKey(InstanceHandle
, &KeyName
, 0, REG_SZ
, ServiceName1
->Buffer
, ServiceName1
->Length
+ sizeof(UNICODE_NULL
));
1120 ZwClose(InstanceHandle
);
1121 ExFreePool(FullServiceName
.Buffer
);
1123 if (!NT_SUCCESS(Status
))
1125 ExFreePoolWithTag(Node
, TAG_IO_DEVNODE
);
1129 IopDeviceNodeSetFlag(Node
, DNF_LEGACY_DRIVER
);
1130 IopDeviceNodeSetFlag(Node
, DNF_PROCESSED
);
1131 IopDeviceNodeSetFlag(Node
, DNF_ADDED
);
1132 IopDeviceNodeSetFlag(Node
, DNF_STARTED
);
1135 Node
->PhysicalDeviceObject
= PhysicalDeviceObject
;
1137 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= Node
;
1141 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
1142 Node
->Parent
= ParentNode
;
1143 Node
->Sibling
= NULL
;
1144 if (ParentNode
->LastChild
== NULL
)
1146 ParentNode
->Child
= Node
;
1147 ParentNode
->LastChild
= Node
;
1151 ParentNode
->LastChild
->Sibling
= Node
;
1152 ParentNode
->LastChild
= Node
;
1154 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
1155 Node
->Level
= ParentNode
->Level
+ 1;
1158 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1162 return STATUS_SUCCESS
;
1166 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
1169 PDEVICE_NODE PrevSibling
= NULL
;
1171 /* All children must be deleted before a parent is deleted */
1172 ASSERT(!DeviceNode
->Child
);
1173 ASSERT(DeviceNode
->PhysicalDeviceObject
);
1175 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
1177 /* Get previous sibling */
1178 if (DeviceNode
->Parent
&& DeviceNode
->Parent
->Child
!= DeviceNode
)
1180 PrevSibling
= DeviceNode
->Parent
->Child
;
1181 while (PrevSibling
->Sibling
!= DeviceNode
)
1182 PrevSibling
= PrevSibling
->Sibling
;
1185 /* Unlink from parent if it exists */
1186 if (DeviceNode
->Parent
)
1188 if (DeviceNode
->Parent
->LastChild
== DeviceNode
)
1190 DeviceNode
->Parent
->LastChild
= PrevSibling
;
1192 PrevSibling
->Sibling
= NULL
;
1194 if (DeviceNode
->Parent
->Child
== DeviceNode
)
1195 DeviceNode
->Parent
->Child
= DeviceNode
->Sibling
;
1198 /* Unlink from sibling list */
1200 PrevSibling
->Sibling
= DeviceNode
->Sibling
;
1202 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
1204 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
1206 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
1208 if (DeviceNode
->ResourceList
)
1210 ExFreePool(DeviceNode
->ResourceList
);
1213 if (DeviceNode
->ResourceListTranslated
)
1215 ExFreePool(DeviceNode
->ResourceListTranslated
);
1218 if (DeviceNode
->ResourceRequirements
)
1220 ExFreePool(DeviceNode
->ResourceRequirements
);
1223 if (DeviceNode
->BootResources
)
1225 ExFreePool(DeviceNode
->BootResources
);
1228 ((PEXTENDED_DEVOBJ_EXTENSION
)DeviceNode
->PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= NULL
;
1229 ExFreePoolWithTag(DeviceNode
, TAG_IO_DEVNODE
);
1231 return STATUS_SUCCESS
;
1236 IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject
,
1237 IN PIO_STACK_LOCATION IoStackLocation
,
1238 OUT PVOID
*Information
)
1241 PIO_STACK_LOCATION IrpStack
;
1242 IO_STATUS_BLOCK IoStatusBlock
;
1245 PDEVICE_OBJECT TopDeviceObject
;
1248 /* Call the top of the device stack */
1249 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
1251 /* Allocate an IRP */
1252 Irp
= IoAllocateIrp(TopDeviceObject
->StackSize
, FALSE
);
1253 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
1255 /* Initialize to failure */
1256 Irp
->IoStatus
.Status
= IoStatusBlock
.Status
= STATUS_NOT_SUPPORTED
;
1257 Irp
->IoStatus
.Information
= IoStatusBlock
.Information
= 0;
1259 /* Special case for IRP_MN_FILTER_RESOURCE_REQUIREMENTS */
1260 if (IoStackLocation
->MinorFunction
== IRP_MN_FILTER_RESOURCE_REQUIREMENTS
)
1262 /* Copy the resource requirements list into the IOSB */
1263 Irp
->IoStatus
.Information
=
1264 IoStatusBlock
.Information
= (ULONG_PTR
)IoStackLocation
->Parameters
.FilterResourceRequirements
.IoResourceRequirementList
;
1267 /* Initialize the event */
1268 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
1271 Irp
->UserIosb
= &IoStatusBlock
;
1272 Irp
->UserEvent
= &Event
;
1275 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
1276 IoQueueThreadIrp(Irp
);
1278 /* Copy-in the stack */
1279 IrpStack
= IoGetNextIrpStackLocation(Irp
);
1280 *IrpStack
= *IoStackLocation
;
1282 /* Call the driver */
1283 Status
= IoCallDriver(TopDeviceObject
, Irp
);
1284 if (Status
== STATUS_PENDING
)
1287 KeWaitForSingleObject(&Event
,
1292 Status
= IoStatusBlock
.Status
;
1295 /* Remove the reference */
1296 ObDereferenceObject(TopDeviceObject
);
1298 /* Return the information */
1299 *Information
= (PVOID
)IoStatusBlock
.Information
;
1305 IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject
,
1306 IN OUT PIO_STATUS_BLOCK IoStatusBlock
,
1307 IN UCHAR MinorFunction
,
1308 IN PIO_STACK_LOCATION Stack OPTIONAL
)
1310 IO_STACK_LOCATION IoStackLocation
;
1312 /* Fill out the stack information */
1313 RtlZeroMemory(&IoStackLocation
, sizeof(IO_STACK_LOCATION
));
1314 IoStackLocation
.MajorFunction
= IRP_MJ_PNP
;
1315 IoStackLocation
.MinorFunction
= MinorFunction
;
1319 RtlCopyMemory(&IoStackLocation
.Parameters
,
1321 sizeof(Stack
->Parameters
));
1324 /* Do the PnP call */
1325 IoStatusBlock
->Status
= IopSynchronousCall(DeviceObject
,
1327 (PVOID
)&IoStatusBlock
->Information
);
1328 return IoStatusBlock
->Status
;
1332 IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1334 PDEVICE_NODE ParentDeviceNode
;
1335 PDEVICE_NODE ChildDeviceNode
;
1338 /* Copy context data so we don't overwrite it in subsequent calls to this function */
1339 ParentDeviceNode
= Context
->DeviceNode
;
1341 /* Call the action routine */
1342 Status
= (Context
->Action
)(ParentDeviceNode
, Context
->Context
);
1343 if (!NT_SUCCESS(Status
))
1348 /* Traversal of all children nodes */
1349 for (ChildDeviceNode
= ParentDeviceNode
->Child
;
1350 ChildDeviceNode
!= NULL
;
1351 ChildDeviceNode
= ChildDeviceNode
->Sibling
)
1353 /* Pass the current device node to the action routine */
1354 Context
->DeviceNode
= ChildDeviceNode
;
1356 Status
= IopTraverseDeviceTreeNode(Context
);
1357 if (!NT_SUCCESS(Status
))
1368 IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context
)
1372 DPRINT("Context 0x%p\n", Context
);
1374 DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %p Context 0x%p)\n",
1375 Context
->DeviceNode
, Context
->FirstDeviceNode
, Context
->Action
, Context
->Context
);
1377 /* Start from the specified device node */
1378 Context
->DeviceNode
= Context
->FirstDeviceNode
;
1380 /* Recursively traverse the device tree */
1381 Status
= IopTraverseDeviceTreeNode(Context
);
1382 if (Status
== STATUS_UNSUCCESSFUL
)
1384 /* The action routine just wanted to terminate the traversal with status
1385 code STATUS_SUCCESS */
1386 Status
= STATUS_SUCCESS
;
1394 * IopCreateDeviceKeyPath
1396 * Creates a registry key
1400 * Name of the key to be created.
1402 * Handle to the newly created key
1405 * This method can create nested trees, so parent of RegistryPath can
1406 * be not existant, and will be created if needed.
1410 IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath
,
1411 IN ULONG CreateOptions
,
1414 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(ENUM_ROOT
);
1415 HANDLE hParent
= NULL
, hKey
;
1416 OBJECT_ATTRIBUTES ObjectAttributes
;
1417 UNICODE_STRING KeyName
;
1418 LPCWSTR Current
, Last
;
1422 /* Assume failure */
1425 /* Create a volatile device tree in 1st stage so we have a clean slate
1426 * for enumeration using the correct HAL (chosen in 1st stage setup) */
1427 if (ExpInTextModeSetup
) CreateOptions
|= REG_OPTION_VOLATILE
;
1429 /* Open root key for device instances */
1430 Status
= IopOpenRegistryKeyEx(&hParent
, NULL
, &EnumU
, KEY_CREATE_SUB_KEY
);
1431 if (!NT_SUCCESS(Status
))
1433 DPRINT1("ZwOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
1437 Current
= KeyName
.Buffer
= RegistryPath
->Buffer
;
1438 Last
= &RegistryPath
->Buffer
[RegistryPath
->Length
/ sizeof(WCHAR
)];
1440 /* Go up to the end of the string */
1441 while (Current
<= Last
)
1443 if (Current
!= Last
&& *Current
!= '\\')
1445 /* Not the end of the string and not a separator */
1450 /* Prepare relative key name */
1451 Length
= (USHORT
)((ULONG_PTR
)Current
- (ULONG_PTR
)KeyName
.Buffer
);
1452 KeyName
.MaximumLength
= KeyName
.Length
= Length
;
1453 DPRINT("Create '%wZ'\n", &KeyName
);
1456 InitializeObjectAttributes(&ObjectAttributes
,
1458 OBJ_CASE_INSENSITIVE
,
1461 Status
= ZwCreateKey(&hKey
,
1462 Current
== Last
? KEY_ALL_ACCESS
: KEY_CREATE_SUB_KEY
,
1469 /* Close parent key handle, we don't need it anymore */
1473 /* Key opening/creating failed? */
1474 if (!NT_SUCCESS(Status
))
1476 DPRINT1("ZwCreateKey('%wZ') failed with status 0x%08lx\n", &KeyName
, Status
);
1480 /* Check if it is the end of the string */
1481 if (Current
== Last
)
1483 /* Yes, return success */
1485 return STATUS_SUCCESS
;
1488 /* Start with this new parent key */
1491 KeyName
.Buffer
= (LPWSTR
)Current
;
1494 return STATUS_UNSUCCESSFUL
;
1498 IopSetDeviceInstanceData(HANDLE InstanceKey
,
1499 PDEVICE_NODE DeviceNode
)
1501 OBJECT_ATTRIBUTES ObjectAttributes
;
1502 UNICODE_STRING KeyName
;
1507 HANDLE ControlHandle
;
1509 DPRINT("IopSetDeviceInstanceData() called\n");
1511 /* Create the 'LogConf' key */
1512 RtlInitUnicodeString(&KeyName
, L
"LogConf");
1513 InitializeObjectAttributes(&ObjectAttributes
,
1515 OBJ_CASE_INSENSITIVE
,
1518 Status
= ZwCreateKey(&LogConfKey
,
1523 REG_OPTION_VOLATILE
,
1525 if (NT_SUCCESS(Status
))
1527 /* Set 'BootConfig' value */
1528 if (DeviceNode
->BootResources
!= NULL
)
1530 ResCount
= DeviceNode
->BootResources
->Count
;
1533 RtlInitUnicodeString(&KeyName
, L
"BootConfig");
1534 Status
= ZwSetValueKey(LogConfKey
,
1538 DeviceNode
->BootResources
,
1539 PnpDetermineResourceListSize(DeviceNode
->BootResources
));
1543 /* Set 'BasicConfigVector' value */
1544 if (DeviceNode
->ResourceRequirements
!= NULL
&&
1545 DeviceNode
->ResourceRequirements
->ListSize
!= 0)
1547 RtlInitUnicodeString(&KeyName
, L
"BasicConfigVector");
1548 Status
= ZwSetValueKey(LogConfKey
,
1551 REG_RESOURCE_REQUIREMENTS_LIST
,
1552 DeviceNode
->ResourceRequirements
,
1553 DeviceNode
->ResourceRequirements
->ListSize
);
1556 ZwClose(LogConfKey
);
1559 /* Set the 'ConfigFlags' value */
1560 RtlInitUnicodeString(&KeyName
, L
"ConfigFlags");
1561 Status
= ZwQueryValueKey(InstanceKey
,
1563 KeyValueBasicInformation
,
1567 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1569 /* Write the default value */
1570 ULONG DefaultConfigFlags
= 0;
1571 Status
= ZwSetValueKey(InstanceKey
,
1575 &DefaultConfigFlags
,
1576 sizeof(DefaultConfigFlags
));
1579 /* Create the 'Control' key */
1580 RtlInitUnicodeString(&KeyName
, L
"Control");
1581 InitializeObjectAttributes(&ObjectAttributes
,
1583 OBJ_CASE_INSENSITIVE
,
1586 Status
= ZwCreateKey(&ControlHandle
, 0, &ObjectAttributes
, 0, NULL
, REG_OPTION_VOLATILE
, NULL
);
1588 if (NT_SUCCESS(Status
))
1589 ZwClose(ControlHandle
);
1591 DPRINT("IopSetDeviceInstanceData() done\n");
1597 * IopGetParentIdPrefix
1599 * Retrieve (or create) a string which identifies a device.
1603 * Pointer to device node.
1605 * Pointer to the string where is returned the parent node identifier
1608 * If the return code is STATUS_SUCCESS, the ParentIdPrefix string is
1609 * valid and its Buffer field is NULL-terminated. The caller needs to
1610 * to free the string with RtlFreeUnicodeString when it is no longer
1615 IopGetParentIdPrefix(PDEVICE_NODE DeviceNode
,
1616 PUNICODE_STRING ParentIdPrefix
)
1618 ULONG KeyNameBufferLength
;
1619 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation
= NULL
;
1620 UNICODE_STRING KeyName
= {0, 0, NULL
};
1621 UNICODE_STRING KeyValue
;
1622 UNICODE_STRING ValueName
;
1627 /* HACK: As long as some devices have a NULL device
1628 * instance path, the following test is required :(
1630 if (DeviceNode
->Parent
->InstancePath
.Length
== 0)
1632 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
1633 &DeviceNode
->InstancePath
);
1634 return STATUS_UNSUCCESSFUL
;
1637 /* 1. Try to retrieve ParentIdPrefix from registry */
1638 KeyNameBufferLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MAX_PATH
* sizeof(WCHAR
);
1639 ParentIdPrefixInformation
= ExAllocatePool(PagedPool
, KeyNameBufferLength
+ sizeof(WCHAR
));
1640 if (!ParentIdPrefixInformation
)
1642 return STATUS_INSUFFICIENT_RESOURCES
;
1645 KeyName
.Buffer
= ExAllocatePool(PagedPool
, (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
);
1646 if (!KeyName
.Buffer
)
1648 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1652 KeyName
.MaximumLength
= (49 * sizeof(WCHAR
)) + DeviceNode
->Parent
->InstancePath
.Length
;
1654 RtlAppendUnicodeToString(&KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1655 RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->Parent
->InstancePath
);
1657 Status
= IopOpenRegistryKeyEx(&hKey
, NULL
, &KeyName
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1658 if (!NT_SUCCESS(Status
))
1660 RtlInitUnicodeString(&ValueName
, L
"ParentIdPrefix");
1661 Status
= ZwQueryValueKey(
1663 KeyValuePartialInformation
, ParentIdPrefixInformation
,
1664 KeyNameBufferLength
, &KeyNameBufferLength
);
1665 if (NT_SUCCESS(Status
))
1667 if (ParentIdPrefixInformation
->Type
!= REG_SZ
)
1668 Status
= STATUS_UNSUCCESSFUL
;
1671 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1672 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1676 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
1678 KeyValue
.Length
= KeyValue
.MaximumLength
= (USHORT
)ParentIdPrefixInformation
->DataLength
;
1679 KeyValue
.Buffer
= (PWSTR
)ParentIdPrefixInformation
->Data
;
1683 /* 2. Create the ParentIdPrefix value */
1684 crc32
= RtlComputeCrc32(0,
1685 (PUCHAR
)DeviceNode
->Parent
->InstancePath
.Buffer
,
1686 DeviceNode
->Parent
->InstancePath
.Length
);
1688 swprintf((PWSTR
)ParentIdPrefixInformation
->Data
, L
"%lx&%lx", DeviceNode
->Parent
->Level
, crc32
);
1689 RtlInitUnicodeString(&KeyValue
, (PWSTR
)ParentIdPrefixInformation
->Data
);
1691 /* 3. Try to write the ParentIdPrefix to registry */
1692 Status
= ZwSetValueKey(hKey
,
1696 (PVOID
)KeyValue
.Buffer
,
1697 ((ULONG
)wcslen(KeyValue
.Buffer
) + 1) * sizeof(WCHAR
));
1700 if (NT_SUCCESS(Status
))
1702 /* Duplicate the string to return it */
1703 Status
= RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
, &KeyValue
, ParentIdPrefix
);
1705 ExFreePool(ParentIdPrefixInformation
);
1706 RtlFreeUnicodeString(&KeyName
);
1713 IopQueryHardwareIds(PDEVICE_NODE DeviceNode
,
1716 IO_STACK_LOCATION Stack
;
1717 IO_STATUS_BLOCK IoStatusBlock
;
1719 UNICODE_STRING ValueName
;
1721 ULONG Length
, TotalLength
;
1723 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1725 RtlZeroMemory(&Stack
, sizeof(Stack
));
1726 Stack
.Parameters
.QueryId
.IdType
= BusQueryHardwareIDs
;
1727 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1731 if (NT_SUCCESS(Status
))
1734 * FIXME: Check for valid characters, if there is invalid characters
1738 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1739 DPRINT("Hardware IDs:\n");
1742 DPRINT(" %S\n", Ptr
);
1743 Length
= (ULONG
)wcslen(Ptr
) + 1;
1746 TotalLength
+= Length
;
1748 DPRINT("TotalLength: %hu\n", TotalLength
);
1751 RtlInitUnicodeString(&ValueName
, L
"HardwareID");
1752 Status
= ZwSetValueKey(InstanceKey
,
1756 (PVOID
)IoStatusBlock
.Information
,
1757 (TotalLength
+ 1) * sizeof(WCHAR
));
1758 if (!NT_SUCCESS(Status
))
1760 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
1765 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1772 IopQueryCompatibleIds(PDEVICE_NODE DeviceNode
,
1775 IO_STACK_LOCATION Stack
;
1776 IO_STATUS_BLOCK IoStatusBlock
;
1778 UNICODE_STRING ValueName
;
1780 ULONG Length
, TotalLength
;
1782 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1784 RtlZeroMemory(&Stack
, sizeof(Stack
));
1785 Stack
.Parameters
.QueryId
.IdType
= BusQueryCompatibleIDs
;
1786 Status
= IopInitiatePnpIrp(
1787 DeviceNode
->PhysicalDeviceObject
,
1791 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
1794 * FIXME: Check for valid characters, if there is invalid characters
1798 Ptr
= (PWSTR
)IoStatusBlock
.Information
;
1799 DPRINT("Compatible IDs:\n");
1802 DPRINT(" %S\n", Ptr
);
1803 Length
= (ULONG
)wcslen(Ptr
) + 1;
1806 TotalLength
+= Length
;
1808 DPRINT("TotalLength: %hu\n", TotalLength
);
1811 RtlInitUnicodeString(&ValueName
, L
"CompatibleIDs");
1812 Status
= ZwSetValueKey(InstanceKey
,
1816 (PVOID
)IoStatusBlock
.Information
,
1817 (TotalLength
+ 1) * sizeof(WCHAR
));
1818 if (!NT_SUCCESS(Status
))
1820 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status
);
1825 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1833 * IopActionInterrogateDeviceStack
1835 * Retrieve information for all (direct) child nodes of a parent node.
1839 * Pointer to device node.
1841 * Pointer to parent node to retrieve child node information for.
1844 * Any errors that occur are logged instead so that all child services have a chance
1845 * of being interrogated.
1849 IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode
,
1852 IO_STATUS_BLOCK IoStatusBlock
;
1853 PDEVICE_NODE ParentDeviceNode
;
1854 WCHAR InstancePath
[MAX_PATH
];
1855 IO_STACK_LOCATION Stack
;
1857 ULONG RequiredLength
;
1859 HANDLE InstanceKey
= NULL
;
1860 UNICODE_STRING ValueName
;
1861 UNICODE_STRING ParentIdPrefix
= { 0, 0, NULL
};
1862 UNICODE_STRING InstancePathU
;
1863 DEVICE_CAPABILITIES DeviceCapabilities
;
1864 PDEVICE_OBJECT OldDeviceObject
;
1866 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode
, Context
);
1867 DPRINT("PDO 0x%p\n", DeviceNode
->PhysicalDeviceObject
);
1869 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
1872 * We are called for the parent too, but we don't need to do special
1873 * handling for this node
1876 if (DeviceNode
== ParentDeviceNode
)
1878 DPRINT("Success\n");
1879 return STATUS_SUCCESS
;
1883 * Make sure this device node is a direct child of the parent device node
1884 * that is given as an argument
1887 if (DeviceNode
->Parent
!= ParentDeviceNode
)
1889 DPRINT("Skipping 2+ level child\n");
1890 return STATUS_SUCCESS
;
1893 /* Skip processing if it was already completed before */
1894 if (DeviceNode
->Flags
& DNF_PROCESSED
)
1897 return STATUS_SUCCESS
;
1901 Status
= ZwQueryDefaultLocale(FALSE
, &LocaleId
);
1902 if (!NT_SUCCESS(Status
))
1904 DPRINT1("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status
);
1909 * FIXME: For critical errors, cleanup and disable device, but always
1910 * return STATUS_SUCCESS.
1913 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1915 Stack
.Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
1916 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1920 if (NT_SUCCESS(Status
))
1922 /* Copy the device id string */
1923 wcscpy(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1926 * FIXME: Check for valid characters, if there is invalid characters
1932 DPRINT1("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
1934 /* We have to return success otherwise we abort the traverse operation */
1935 return STATUS_SUCCESS
;
1938 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n");
1940 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCapabilities
);
1941 if (!NT_SUCCESS(Status
))
1943 DPRINT1("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status
);
1945 /* We have to return success otherwise we abort the traverse operation */
1946 return STATUS_SUCCESS
;
1949 /* This bit is only check after enumeration */
1950 if (DeviceCapabilities
.HardwareDisabled
)
1952 /* FIXME: Cleanup device */
1953 DeviceNode
->Flags
|= DNF_DISABLED
;
1954 return STATUS_SUCCESS
;
1957 DeviceNode
->Flags
&= ~DNF_DISABLED
;
1959 if (!DeviceCapabilities
.UniqueID
)
1961 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
1962 DPRINT("Instance ID is not unique\n");
1963 Status
= IopGetParentIdPrefix(DeviceNode
, &ParentIdPrefix
);
1964 if (!NT_SUCCESS(Status
))
1966 DPRINT1("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status
);
1968 /* We have to return success otherwise we abort the traverse operation */
1969 return STATUS_SUCCESS
;
1973 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1975 Stack
.Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
1976 Status
= IopInitiatePnpIrp(DeviceNode
->PhysicalDeviceObject
,
1980 if (NT_SUCCESS(Status
))
1982 /* Append the instance id string */
1983 wcscat(InstancePath
, L
"\\");
1984 if (ParentIdPrefix
.Length
> 0)
1986 /* Add information from parent bus device to InstancePath */
1987 wcscat(InstancePath
, ParentIdPrefix
.Buffer
);
1988 if (IoStatusBlock
.Information
&& *(PWSTR
)IoStatusBlock
.Information
)
1989 wcscat(InstancePath
, L
"&");
1991 if (IoStatusBlock
.Information
)
1992 wcscat(InstancePath
, (PWSTR
)IoStatusBlock
.Information
);
1995 * FIXME: Check for valid characters, if there is invalid characters
2001 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status
);
2003 RtlFreeUnicodeString(&ParentIdPrefix
);
2005 if (!RtlCreateUnicodeString(&InstancePathU
, InstancePath
))
2007 DPRINT("No resources\n");
2008 /* FIXME: Cleanup and disable device */
2011 /* Verify that this is not a duplicate */
2012 OldDeviceObject
= IopGetDeviceObjectFromDeviceInstance(&InstancePathU
);
2013 if (OldDeviceObject
!= NULL
)
2015 PDEVICE_NODE OldDeviceNode
= IopGetDeviceNode(OldDeviceObject
);
2017 DPRINT1("Duplicate device instance '%wZ'\n", &InstancePathU
);
2018 DPRINT1("Current instance parent: '%wZ'\n", &DeviceNode
->Parent
->InstancePath
);
2019 DPRINT1("Old instance parent: '%wZ'\n", &OldDeviceNode
->Parent
->InstancePath
);
2021 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR
,
2023 (ULONG_PTR
)DeviceNode
->PhysicalDeviceObject
,
2024 (ULONG_PTR
)OldDeviceObject
,
2028 DeviceNode
->InstancePath
= InstancePathU
;
2030 DPRINT("InstancePath is %S\n", DeviceNode
->InstancePath
.Buffer
);
2033 * Create registry key for the instance id, if it doesn't exist yet
2035 Status
= IopCreateDeviceKeyPath(&DeviceNode
->InstancePath
, 0, &InstanceKey
);
2036 if (!NT_SUCCESS(Status
))
2038 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status
);
2040 /* We have to return success otherwise we abort the traverse operation */
2041 return STATUS_SUCCESS
;
2044 IopQueryHardwareIds(DeviceNode
, InstanceKey
);
2046 IopQueryCompatibleIds(DeviceNode
, InstanceKey
);
2048 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
2050 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextDescription
;
2051 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2052 Status
= IopInitiatePnpIrp(
2053 DeviceNode
->PhysicalDeviceObject
,
2055 IRP_MN_QUERY_DEVICE_TEXT
,
2057 /* This key is mandatory, so even if the Irp fails, we still write it */
2058 RtlInitUnicodeString(&ValueName
, L
"DeviceDesc");
2059 if (ZwQueryValueKey(InstanceKey
, &ValueName
, KeyValueBasicInformation
, NULL
, 0, &RequiredLength
) == STATUS_OBJECT_NAME_NOT_FOUND
)
2061 if (NT_SUCCESS(Status
) &&
2062 IoStatusBlock
.Information
&&
2063 (*(PWSTR
)IoStatusBlock
.Information
!= 0))
2065 /* This key is overriden when a driver is installed. Don't write the
2066 * new description if another one already exists */
2067 Status
= ZwSetValueKey(InstanceKey
,
2071 (PVOID
)IoStatusBlock
.Information
,
2072 ((ULONG
)wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2076 UNICODE_STRING DeviceDesc
= RTL_CONSTANT_STRING(L
"Unknown device");
2077 DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status
);
2079 Status
= ZwSetValueKey(InstanceKey
,
2084 DeviceDesc
.MaximumLength
);
2086 if (!NT_SUCCESS(Status
))
2088 DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status
);
2094 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
2096 Stack
.Parameters
.QueryDeviceText
.DeviceTextType
= DeviceTextLocationInformation
;
2097 Stack
.Parameters
.QueryDeviceText
.LocaleId
= LocaleId
;
2098 Status
= IopInitiatePnpIrp(
2099 DeviceNode
->PhysicalDeviceObject
,
2101 IRP_MN_QUERY_DEVICE_TEXT
,
2103 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2105 DPRINT("LocationInformation: %S\n", (PWSTR
)IoStatusBlock
.Information
);
2106 RtlInitUnicodeString(&ValueName
, L
"LocationInformation");
2107 Status
= ZwSetValueKey(InstanceKey
,
2111 (PVOID
)IoStatusBlock
.Information
,
2112 ((ULONG
)wcslen((PWSTR
)IoStatusBlock
.Information
) + 1) * sizeof(WCHAR
));
2113 if (!NT_SUCCESS(Status
))
2115 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status
);
2120 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2123 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
2125 Status
= IopInitiatePnpIrp(
2126 DeviceNode
->PhysicalDeviceObject
,
2128 IRP_MN_QUERY_BUS_INFORMATION
,
2130 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2132 PPNP_BUS_INFORMATION BusInformation
=
2133 (PPNP_BUS_INFORMATION
)IoStatusBlock
.Information
;
2135 DeviceNode
->ChildBusNumber
= BusInformation
->BusNumber
;
2136 DeviceNode
->ChildInterfaceType
= BusInformation
->LegacyBusType
;
2137 DeviceNode
->ChildBusTypeIndex
= IopGetBusTypeGuidIndex(&BusInformation
->BusTypeGuid
);
2138 ExFreePool(BusInformation
);
2142 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2144 DeviceNode
->ChildBusNumber
= 0xFFFFFFF0;
2145 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
2146 DeviceNode
->ChildBusTypeIndex
= -1;
2149 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
2151 Status
= IopInitiatePnpIrp(
2152 DeviceNode
->PhysicalDeviceObject
,
2154 IRP_MN_QUERY_RESOURCES
,
2156 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
2158 DeviceNode
->BootResources
=
2159 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
2160 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
2164 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
2165 DeviceNode
->BootResources
= NULL
;
2168 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
2170 Status
= IopInitiatePnpIrp(
2171 DeviceNode
->PhysicalDeviceObject
,
2173 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
2175 if (NT_SUCCESS(Status
))
2177 DeviceNode
->ResourceRequirements
=
2178 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
2182 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
2183 DeviceNode
->ResourceRequirements
= NULL
;
2186 if (InstanceKey
!= NULL
)
2188 IopSetDeviceInstanceData(InstanceKey
, DeviceNode
);
2191 ZwClose(InstanceKey
);
2193 IopDeviceNodeSetFlag(DeviceNode
, DNF_PROCESSED
);
2195 if (!IopDeviceNodeHasFlag(DeviceNode
, DNF_LEGACY_DRIVER
))
2197 /* Report the device to the user-mode pnp manager */
2198 IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED
,
2199 &DeviceNode
->InstancePath
);
2202 return STATUS_SUCCESS
;
2207 IopHandleDeviceRemoval(
2208 IN PDEVICE_NODE DeviceNode
,
2209 IN PDEVICE_RELATIONS DeviceRelations
)
2211 PDEVICE_NODE Child
= DeviceNode
->Child
, NextChild
;
2215 if (DeviceNode
== IopRootDeviceNode
)
2218 while (Child
!= NULL
)
2220 NextChild
= Child
->Sibling
;
2223 for (i
= 0; DeviceRelations
&& i
< DeviceRelations
->Count
; i
++)
2225 if (IopGetDeviceNode(DeviceRelations
->Objects
[i
]) == Child
)
2232 if (!Found
&& !(Child
->Flags
& DNF_WILL_BE_REMOVED
))
2234 /* Send removal IRPs to all of its children */
2235 IopPrepareDeviceForRemoval(Child
->PhysicalDeviceObject
, TRUE
);
2237 /* Send the surprise removal IRP */
2238 IopSendSurpriseRemoval(Child
->PhysicalDeviceObject
);
2240 /* Tell the user-mode PnP manager that a device was removed */
2241 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL
,
2242 &Child
->InstancePath
);
2244 /* Send the remove device IRP */
2245 IopSendRemoveDevice(Child
->PhysicalDeviceObject
);
2254 IN PDEVICE_OBJECT DeviceObject
)
2256 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
2257 DEVICETREE_TRAVERSE_CONTEXT Context
;
2258 PDEVICE_RELATIONS DeviceRelations
;
2259 PDEVICE_OBJECT ChildDeviceObject
;
2260 IO_STATUS_BLOCK IoStatusBlock
;
2261 PDEVICE_NODE ChildDeviceNode
;
2262 IO_STACK_LOCATION Stack
;
2266 DPRINT("DeviceObject 0x%p\n", DeviceObject
);
2268 if (DeviceNode
->Flags
& DNF_NEED_ENUMERATION_ONLY
)
2270 DeviceNode
->Flags
&= ~DNF_NEED_ENUMERATION_ONLY
;
2272 DPRINT("Sending GUID_DEVICE_ARRIVAL\n");
2273 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
2274 &DeviceNode
->InstancePath
);
2277 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
2279 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
2281 Status
= IopInitiatePnpIrp(
2284 IRP_MN_QUERY_DEVICE_RELATIONS
,
2286 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
)
2288 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
2292 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
2295 * Send removal IRPs for devices that have disappeared
2296 * NOTE: This code handles the case where no relations are specified
2298 IopHandleDeviceRemoval(DeviceNode
, DeviceRelations
);
2300 /* Now we bail if nothing was returned */
2301 if (!DeviceRelations
)
2303 /* We're all done */
2304 DPRINT("No PDOs\n");
2305 return STATUS_SUCCESS
;
2308 DPRINT("Got %u PDOs\n", DeviceRelations
->Count
);
2311 * Create device nodes for all discovered devices
2313 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
2315 ChildDeviceObject
= DeviceRelations
->Objects
[i
];
2316 ASSERT((ChildDeviceObject
->Flags
& DO_DEVICE_INITIALIZING
) == 0);
2318 ChildDeviceNode
= IopGetDeviceNode(ChildDeviceObject
);
2319 if (!ChildDeviceNode
)
2321 /* One doesn't exist, create it */
2322 Status
= IopCreateDeviceNode(
2327 if (NT_SUCCESS(Status
))
2329 /* Mark the node as enumerated */
2330 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2332 /* Mark the DO as bus enumerated */
2333 ChildDeviceObject
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
2337 /* Ignore this DO */
2338 DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u\n", Status
, i
);
2339 ObDereferenceObject(ChildDeviceObject
);
2344 /* Mark it as enumerated */
2345 ChildDeviceNode
->Flags
|= DNF_ENUMERATED
;
2346 ObDereferenceObject(ChildDeviceObject
);
2349 ExFreePool(DeviceRelations
);
2352 * Retrieve information about all discovered children from the bus driver
2354 IopInitDeviceTreeTraverseContext(
2357 IopActionInterrogateDeviceStack
,
2360 Status
= IopTraverseDeviceTree(&Context
);
2361 if (!NT_SUCCESS(Status
))
2363 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2368 * Retrieve configuration from the registry for discovered children
2370 IopInitDeviceTreeTraverseContext(
2373 IopActionConfigureChildServices
,
2376 Status
= IopTraverseDeviceTree(&Context
);
2377 if (!NT_SUCCESS(Status
))
2379 DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status
);
2384 * Initialize services for discovered children.
2386 Status
= IopInitializePnpServices(DeviceNode
);
2387 if (!NT_SUCCESS(Status
))
2389 DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status
);
2393 DPRINT("IopEnumerateDevice() finished\n");
2394 return STATUS_SUCCESS
;
2399 * IopActionConfigureChildServices
2401 * Retrieve configuration for all (direct) child nodes of a parent node.
2405 * Pointer to device node.
2407 * Pointer to parent node to retrieve child node configuration for.
2410 * Any errors that occur are logged instead so that all child services have a chance of beeing
2415 IopActionConfigureChildServices(PDEVICE_NODE DeviceNode
,
2418 RTL_QUERY_REGISTRY_TABLE QueryTable
[3];
2419 PDEVICE_NODE ParentDeviceNode
;
2420 PUNICODE_STRING Service
;
2421 UNICODE_STRING ClassGUID
;
2423 DEVICE_CAPABILITIES DeviceCaps
;
2425 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode
, Context
);
2427 ParentDeviceNode
= (PDEVICE_NODE
)Context
;
2430 * We are called for the parent too, but we don't need to do special
2431 * handling for this node
2433 if (DeviceNode
== ParentDeviceNode
)
2435 DPRINT("Success\n");
2436 return STATUS_SUCCESS
;
2440 * Make sure this device node is a direct child of the parent device node
2441 * that is given as an argument
2444 if (DeviceNode
->Parent
!= ParentDeviceNode
)
2446 DPRINT("Skipping 2+ level child\n");
2447 return STATUS_SUCCESS
;
2450 if (!(DeviceNode
->Flags
& DNF_PROCESSED
))
2452 DPRINT1("Child not ready to be configured\n");
2453 return STATUS_SUCCESS
;
2456 if (!(DeviceNode
->Flags
& (DNF_DISABLED
| DNF_STARTED
| DNF_ADDED
)))
2458 WCHAR RegKeyBuffer
[MAX_PATH
];
2459 UNICODE_STRING RegKey
;
2461 /* Install the service for this if it's in the CDDB */
2462 IopInstallCriticalDevice(DeviceNode
);
2465 RegKey
.MaximumLength
= sizeof(RegKeyBuffer
);
2466 RegKey
.Buffer
= RegKeyBuffer
;
2469 * Retrieve configuration from Enum key
2472 Service
= &DeviceNode
->ServiceName
;
2474 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
2475 RtlInitUnicodeString(Service
, NULL
);
2476 RtlInitUnicodeString(&ClassGUID
, NULL
);
2478 QueryTable
[0].Name
= L
"Service";
2479 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2480 QueryTable
[0].EntryContext
= Service
;
2482 QueryTable
[1].Name
= L
"ClassGUID";
2483 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
2484 QueryTable
[1].EntryContext
= &ClassGUID
;
2485 QueryTable
[1].DefaultType
= REG_SZ
;
2486 QueryTable
[1].DefaultData
= L
"";
2487 QueryTable
[1].DefaultLength
= 0;
2489 RtlAppendUnicodeToString(&RegKey
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2490 RtlAppendUnicodeStringToString(&RegKey
, &DeviceNode
->InstancePath
);
2492 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
2493 RegKey
.Buffer
, QueryTable
, NULL
, NULL
);
2495 if (!NT_SUCCESS(Status
))
2497 /* FIXME: Log the error */
2498 DPRINT("Could not retrieve configuration for device %wZ (Status 0x%08x)\n",
2499 &DeviceNode
->InstancePath
, Status
);
2500 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2501 return STATUS_SUCCESS
;
2504 if (Service
->Buffer
== NULL
)
2506 if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
)) &&
2507 DeviceCaps
.RawDeviceOK
)
2509 DPRINT("%wZ is using parent bus driver (%wZ)\n", &DeviceNode
->InstancePath
, &ParentDeviceNode
->ServiceName
);
2511 DeviceNode
->ServiceName
.Length
= 0;
2512 DeviceNode
->ServiceName
.MaximumLength
= 0;
2513 DeviceNode
->ServiceName
.Buffer
= NULL
;
2515 else if (ClassGUID
.Length
!= 0)
2517 /* Device has a ClassGUID value, but no Service value.
2518 * Suppose it is using the NULL driver, so state the
2519 * device is started */
2520 DPRINT("%wZ is using NULL driver\n", &DeviceNode
->InstancePath
);
2521 IopDeviceNodeSetFlag(DeviceNode
, DNF_STARTED
);
2525 DeviceNode
->Problem
= CM_PROB_FAILED_INSTALL
;
2526 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2528 return STATUS_SUCCESS
;
2531 DPRINT("Got Service %S\n", Service
->Buffer
);
2534 return STATUS_SUCCESS
;
2538 * IopActionInitChildServices
2540 * Initialize the service for all (direct) child nodes of a parent node
2544 * Pointer to device node.
2546 * Pointer to parent node to initialize child node services for.
2549 * If the driver image for a service is not loaded and initialized
2550 * it is done here too. Any errors that occur are logged instead so
2551 * that all child services have a chance of being initialized.
2555 IopActionInitChildServices(PDEVICE_NODE DeviceNode
,
2558 PDEVICE_NODE ParentDeviceNode
;
2560 BOOLEAN BootDrivers
= !PnpSystemInit
;
2562 DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode
, Context
);
2564 ParentDeviceNode
= Context
;
2567 * We are called for the parent too, but we don't need to do special
2568 * handling for this node
2570 if (DeviceNode
== ParentDeviceNode
)
2572 DPRINT("Success\n");
2573 return STATUS_SUCCESS
;
2577 * We don't want to check for a direct child because
2578 * this function is called during boot to reinitialize
2579 * devices with drivers that couldn't load yet due to
2580 * stage 0 limitations (ie can't load from disk yet).
2583 if (!(DeviceNode
->Flags
& DNF_PROCESSED
))
2585 DPRINT1("Child not ready to be added\n");
2586 return STATUS_SUCCESS
;
2589 if (IopDeviceNodeHasFlag(DeviceNode
, DNF_STARTED
) ||
2590 IopDeviceNodeHasFlag(DeviceNode
, DNF_ADDED
) ||
2591 IopDeviceNodeHasFlag(DeviceNode
, DNF_DISABLED
))
2592 return STATUS_SUCCESS
;
2594 if (DeviceNode
->ServiceName
.Buffer
== NULL
)
2596 /* We don't need to worry about loading the driver because we're
2597 * being driven in raw mode so our parent must be loaded to get here */
2598 Status
= IopInitializeDevice(DeviceNode
, NULL
);
2599 if (NT_SUCCESS(Status
))
2601 Status
= IopStartDevice(DeviceNode
);
2602 if (!NT_SUCCESS(Status
))
2604 DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n",
2605 &DeviceNode
->InstancePath
, Status
);
2611 PLDR_DATA_TABLE_ENTRY ModuleObject
;
2612 PDRIVER_OBJECT DriverObject
;
2614 /* Get existing DriverObject pointer (in case the driver has
2615 already been loaded and initialized) */
2616 Status
= IopGetDriverObject(
2618 &DeviceNode
->ServiceName
,
2621 if (!NT_SUCCESS(Status
))
2623 /* Driver is not initialized, try to load it */
2624 Status
= IopLoadServiceModule(&DeviceNode
->ServiceName
, &ModuleObject
);
2626 if (NT_SUCCESS(Status
) || Status
== STATUS_IMAGE_ALREADY_LOADED
)
2628 /* Initialize the driver */
2629 Status
= IopInitializeDriverModule(DeviceNode
, ModuleObject
,
2630 &DeviceNode
->ServiceName
, FALSE
, &DriverObject
);
2631 if (!NT_SUCCESS(Status
)) DeviceNode
->Problem
= CM_PROB_FAILED_DRIVER_ENTRY
;
2633 else if (Status
== STATUS_DRIVER_UNABLE_TO_LOAD
)
2635 DPRINT1("Service '%wZ' is disabled\n", &DeviceNode
->ServiceName
);
2636 DeviceNode
->Problem
= CM_PROB_DISABLED_SERVICE
;
2640 DPRINT("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
2641 &DeviceNode
->ServiceName
, Status
);
2642 if (!BootDrivers
) DeviceNode
->Problem
= CM_PROB_DRIVER_FAILED_LOAD
;
2646 /* Driver is loaded and initialized at this point */
2647 if (NT_SUCCESS(Status
))
2649 /* Initialize the device, including all filters */
2650 Status
= PipCallDriverAddDevice(DeviceNode
, FALSE
, DriverObject
);
2652 /* Remove the extra reference */
2653 ObDereferenceObject(DriverObject
);
2658 * Don't disable when trying to load only boot drivers
2662 IopDeviceNodeSetFlag(DeviceNode
, DNF_DISABLED
);
2667 return STATUS_SUCCESS
;
2671 * IopInitializePnpServices
2673 * Initialize services for discovered children
2677 * Top device node to start initializing services.
2683 IopInitializePnpServices(IN PDEVICE_NODE DeviceNode
)
2685 DEVICETREE_TRAVERSE_CONTEXT Context
;
2687 DPRINT("IopInitializePnpServices(%p)\n", DeviceNode
);
2689 IopInitDeviceTreeTraverseContext(
2692 IopActionInitChildServices
,
2695 return IopTraverseDeviceTree(&Context
);
2698 static NTSTATUS INIT_FUNCTION
2699 IopEnumerateDetectedDevices(
2701 IN PUNICODE_STRING RelativePath OPTIONAL
,
2703 IN BOOLEAN EnumerateSubKeys
,
2704 IN PCM_FULL_RESOURCE_DESCRIPTOR ParentBootResources
,
2705 IN ULONG ParentBootResourcesLength
)
2707 UNICODE_STRING IdentifierU
= RTL_CONSTANT_STRING(L
"Identifier");
2708 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
2709 UNICODE_STRING ConfigurationDataU
= RTL_CONSTANT_STRING(L
"Configuration Data");
2710 UNICODE_STRING BootConfigU
= RTL_CONSTANT_STRING(L
"BootConfig");
2711 UNICODE_STRING LogConfU
= RTL_CONSTANT_STRING(L
"LogConf");
2712 OBJECT_ATTRIBUTES ObjectAttributes
;
2713 HANDLE hDevicesKey
= NULL
;
2714 HANDLE hDeviceKey
= NULL
;
2715 HANDLE hLevel1Key
, hLevel2Key
= NULL
, hLogConf
;
2716 UNICODE_STRING Level2NameU
;
2717 WCHAR Level2Name
[5];
2718 ULONG IndexDevice
= 0;
2720 PKEY_BASIC_INFORMATION pDeviceInformation
= NULL
;
2721 ULONG DeviceInfoLength
= sizeof(KEY_BASIC_INFORMATION
) + 50 * sizeof(WCHAR
);
2722 PKEY_VALUE_PARTIAL_INFORMATION pValueInformation
= NULL
;
2723 ULONG ValueInfoLength
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 50 * sizeof(WCHAR
);
2724 UNICODE_STRING DeviceName
, ValueName
;
2726 PCM_FULL_RESOURCE_DESCRIPTOR BootResources
= NULL
;
2727 ULONG BootResourcesLength
;
2730 const UNICODE_STRING IdentifierSerial
= RTL_CONSTANT_STRING(L
"SerialController");
2731 UNICODE_STRING HardwareIdSerial
= RTL_CONSTANT_STRING(L
"*PNP0501\0");
2732 static ULONG DeviceIndexSerial
= 0;
2733 const UNICODE_STRING IdentifierKeyboard
= RTL_CONSTANT_STRING(L
"KeyboardController");
2734 UNICODE_STRING HardwareIdKeyboard
= RTL_CONSTANT_STRING(L
"*PNP0303\0");
2735 static ULONG DeviceIndexKeyboard
= 0;
2736 const UNICODE_STRING IdentifierMouse
= RTL_CONSTANT_STRING(L
"PointerController");
2737 UNICODE_STRING HardwareIdMouse
= RTL_CONSTANT_STRING(L
"*PNP0F13\0");
2738 static ULONG DeviceIndexMouse
= 0;
2739 const UNICODE_STRING IdentifierParallel
= RTL_CONSTANT_STRING(L
"ParallelController");
2740 UNICODE_STRING HardwareIdParallel
= RTL_CONSTANT_STRING(L
"*PNP0400\0");
2741 static ULONG DeviceIndexParallel
= 0;
2742 const UNICODE_STRING IdentifierFloppy
= RTL_CONSTANT_STRING(L
"FloppyDiskPeripheral");
2743 UNICODE_STRING HardwareIdFloppy
= RTL_CONSTANT_STRING(L
"*PNP0700\0");
2744 static ULONG DeviceIndexFloppy
= 0;
2745 UNICODE_STRING HardwareIdKey
;
2746 PUNICODE_STRING pHardwareId
;
2747 ULONG DeviceIndex
= 0;
2748 PUCHAR CmResourceList
;
2753 Status
= IopOpenRegistryKeyEx(&hDevicesKey
, hBaseKey
, RelativePath
, KEY_ENUMERATE_SUB_KEYS
);
2754 if (!NT_SUCCESS(Status
))
2756 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2761 hDevicesKey
= hBaseKey
;
2763 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2764 if (!pDeviceInformation
)
2766 DPRINT("ExAllocatePool() failed\n");
2767 Status
= STATUS_NO_MEMORY
;
2771 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2772 if (!pValueInformation
)
2774 DPRINT("ExAllocatePool() failed\n");
2775 Status
= STATUS_NO_MEMORY
;
2781 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2782 if (Status
== STATUS_NO_MORE_ENTRIES
)
2784 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2786 ExFreePool(pDeviceInformation
);
2787 DeviceInfoLength
= RequiredSize
;
2788 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2789 if (!pDeviceInformation
)
2791 DPRINT("ExAllocatePool() failed\n");
2792 Status
= STATUS_NO_MEMORY
;
2795 Status
= ZwEnumerateKey(hDevicesKey
, IndexDevice
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2797 if (!NT_SUCCESS(Status
))
2799 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2804 /* Open device key */
2805 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2806 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2808 Status
= IopOpenRegistryKeyEx(&hDeviceKey
, hDevicesKey
, &DeviceName
,
2809 KEY_QUERY_VALUE
+ (EnumerateSubKeys
? KEY_ENUMERATE_SUB_KEYS
: 0));
2810 if (!NT_SUCCESS(Status
))
2812 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
2816 /* Read boot resources, and add then to parent ones */
2817 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2818 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2820 ExFreePool(pValueInformation
);
2821 ValueInfoLength
= RequiredSize
;
2822 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2823 if (!pValueInformation
)
2825 DPRINT("ExAllocatePool() failed\n");
2826 ZwDeleteKey(hLevel2Key
);
2827 Status
= STATUS_NO_MEMORY
;
2830 Status
= ZwQueryValueKey(hDeviceKey
, &ConfigurationDataU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2832 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
2834 BootResources
= ParentBootResources
;
2835 BootResourcesLength
= ParentBootResourcesLength
;
2837 else if (!NT_SUCCESS(Status
))
2839 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2842 else if (pValueInformation
->Type
!= REG_FULL_RESOURCE_DESCRIPTOR
)
2844 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_FULL_RESOURCE_DESCRIPTOR
);
2849 static const ULONG Header
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
.PartialDescriptors
);
2851 /* Concatenate current resources and parent ones */
2852 if (ParentBootResourcesLength
== 0)
2853 BootResourcesLength
= pValueInformation
->DataLength
;
2855 BootResourcesLength
= ParentBootResourcesLength
2856 + pValueInformation
->DataLength
2858 BootResources
= ExAllocatePool(PagedPool
, BootResourcesLength
);
2861 DPRINT("ExAllocatePool() failed\n");
2864 if (ParentBootResourcesLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
2866 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2868 else if (ParentBootResources
->PartialResourceList
.PartialDescriptors
[ParentBootResources
->PartialResourceList
.Count
- 1].Type
== CmResourceTypeDeviceSpecific
)
2870 RtlCopyMemory(BootResources
, pValueInformation
->Data
, pValueInformation
->DataLength
);
2872 (PVOID
)((ULONG_PTR
)BootResources
+ pValueInformation
->DataLength
),
2873 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2874 ParentBootResourcesLength
- Header
);
2875 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2879 RtlCopyMemory(BootResources
, pValueInformation
->Data
, Header
);
2881 (PVOID
)((ULONG_PTR
)BootResources
+ Header
),
2882 (PVOID
)((ULONG_PTR
)ParentBootResources
+ Header
),
2883 ParentBootResourcesLength
- Header
);
2885 (PVOID
)((ULONG_PTR
)BootResources
+ ParentBootResourcesLength
),
2886 pValueInformation
->Data
+ Header
,
2887 pValueInformation
->DataLength
- Header
);
2888 BootResources
->PartialResourceList
.Count
+= ParentBootResources
->PartialResourceList
.Count
;
2892 if (EnumerateSubKeys
)
2897 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2898 if (Status
== STATUS_NO_MORE_ENTRIES
)
2900 else if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2902 ExFreePool(pDeviceInformation
);
2903 DeviceInfoLength
= RequiredSize
;
2904 pDeviceInformation
= ExAllocatePool(PagedPool
, DeviceInfoLength
);
2905 if (!pDeviceInformation
)
2907 DPRINT("ExAllocatePool() failed\n");
2908 Status
= STATUS_NO_MEMORY
;
2911 Status
= ZwEnumerateKey(hDeviceKey
, IndexSubKey
, KeyBasicInformation
, pDeviceInformation
, DeviceInfoLength
, &RequiredSize
);
2913 if (!NT_SUCCESS(Status
))
2915 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status
);
2919 DeviceName
.Length
= DeviceName
.MaximumLength
= (USHORT
)pDeviceInformation
->NameLength
;
2920 DeviceName
.Buffer
= pDeviceInformation
->Name
;
2922 Status
= IopEnumerateDetectedDevices(
2928 BootResourcesLength
);
2929 if (!NT_SUCCESS(Status
))
2934 /* Read identifier */
2935 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2936 if (Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
2938 ExFreePool(pValueInformation
);
2939 ValueInfoLength
= RequiredSize
;
2940 pValueInformation
= ExAllocatePool(PagedPool
, ValueInfoLength
);
2941 if (!pValueInformation
)
2943 DPRINT("ExAllocatePool() failed\n");
2944 Status
= STATUS_NO_MEMORY
;
2947 Status
= ZwQueryValueKey(hDeviceKey
, &IdentifierU
, KeyValuePartialInformation
, pValueInformation
, ValueInfoLength
, &RequiredSize
);
2949 if (!NT_SUCCESS(Status
))
2951 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
2953 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status
);
2956 ValueName
.Length
= ValueName
.MaximumLength
= 0;
2958 else if (pValueInformation
->Type
!= REG_SZ
)
2960 DPRINT("Wrong registry type: got 0x%lx, expected 0x%lx\n", pValueInformation
->Type
, REG_SZ
);
2965 /* Assign hardware id to this device */
2966 ValueName
.Length
= ValueName
.MaximumLength
= (USHORT
)pValueInformation
->DataLength
;
2967 ValueName
.Buffer
= (PWCHAR
)pValueInformation
->Data
;
2968 if (ValueName
.Length
>= sizeof(WCHAR
) && ValueName
.Buffer
[ValueName
.Length
/ sizeof(WCHAR
) - 1] == UNICODE_NULL
)
2969 ValueName
.Length
-= sizeof(WCHAR
);
2972 if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierSerial
, FALSE
) == 0)
2974 pHardwareId
= &HardwareIdSerial
;
2975 DeviceIndex
= DeviceIndexSerial
++;
2977 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierKeyboard
, FALSE
) == 0)
2979 pHardwareId
= &HardwareIdKeyboard
;
2980 DeviceIndex
= DeviceIndexKeyboard
++;
2982 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierMouse
, FALSE
) == 0)
2984 pHardwareId
= &HardwareIdMouse
;
2985 DeviceIndex
= DeviceIndexMouse
++;
2987 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierParallel
, FALSE
) == 0)
2989 pHardwareId
= &HardwareIdParallel
;
2990 DeviceIndex
= DeviceIndexParallel
++;
2992 else if (RelativePath
&& RtlCompareUnicodeString(RelativePath
, &IdentifierFloppy
, FALSE
) == 0)
2994 pHardwareId
= &HardwareIdFloppy
;
2995 DeviceIndex
= DeviceIndexFloppy
++;
2999 /* Unknown key path */
3000 DPRINT("Unknown key path '%wZ'\n", RelativePath
);
3004 /* Prepare hardware id key (hardware id value without final \0) */
3005 HardwareIdKey
= *pHardwareId
;
3006 HardwareIdKey
.Length
-= sizeof(UNICODE_NULL
);
3008 /* Add the detected device to Root key */
3009 InitializeObjectAttributes(&ObjectAttributes
, &HardwareIdKey
, OBJ_KERNEL_HANDLE
, hRootKey
, NULL
);
3010 Status
= ZwCreateKey(
3016 ExpInTextModeSetup
? REG_OPTION_VOLATILE
: 0,
3018 if (!NT_SUCCESS(Status
))
3020 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3023 swprintf(Level2Name
, L
"%04lu", DeviceIndex
);
3024 RtlInitUnicodeString(&Level2NameU
, Level2Name
);
3025 InitializeObjectAttributes(&ObjectAttributes
, &Level2NameU
, OBJ_KERNEL_HANDLE
, hLevel1Key
, NULL
);
3026 Status
= ZwCreateKey(
3028 KEY_SET_VALUE
| KEY_CREATE_SUB_KEY
,
3032 ExpInTextModeSetup
? REG_OPTION_VOLATILE
: 0,
3034 ZwClose(hLevel1Key
);
3035 if (!NT_SUCCESS(Status
))
3037 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3040 DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName
, DeviceIndex
, &HardwareIdKey
);
3041 Status
= ZwSetValueKey(hLevel2Key
, &HardwareIDU
, 0, REG_MULTI_SZ
, pHardwareId
->Buffer
, pHardwareId
->MaximumLength
);
3042 if (!NT_SUCCESS(Status
))
3044 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3045 ZwDeleteKey(hLevel2Key
);
3048 /* Create 'LogConf' subkey */
3049 InitializeObjectAttributes(&ObjectAttributes
, &LogConfU
, OBJ_KERNEL_HANDLE
, hLevel2Key
, NULL
);
3050 Status
= ZwCreateKey(
3056 REG_OPTION_VOLATILE
,
3058 if (!NT_SUCCESS(Status
))
3060 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3061 ZwDeleteKey(hLevel2Key
);
3064 if (BootResourcesLength
>= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))
3066 CmResourceList
= ExAllocatePool(PagedPool
, BootResourcesLength
+ sizeof(ULONG
));
3067 if (!CmResourceList
)
3070 ZwDeleteKey(hLevel2Key
);
3074 /* Add the list count (1st member of CM_RESOURCE_LIST) */
3076 RtlCopyMemory(CmResourceList
,
3080 /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
3081 RtlCopyMemory(CmResourceList
+ sizeof(ULONG
),
3083 BootResourcesLength
);
3085 /* Save boot resources to 'LogConf\BootConfig' */
3086 Status
= ZwSetValueKey(hLogConf
, &BootConfigU
, 0, REG_RESOURCE_LIST
, CmResourceList
, BootResourcesLength
+ sizeof(ULONG
));
3087 if (!NT_SUCCESS(Status
))
3089 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status
);
3091 ZwDeleteKey(hLevel2Key
);
3098 if (BootResources
&& BootResources
!= ParentBootResources
)
3100 ExFreePool(BootResources
);
3101 BootResources
= NULL
;
3105 ZwClose(hLevel2Key
);
3110 ZwClose(hDeviceKey
);
3115 Status
= STATUS_SUCCESS
;
3118 if (hDevicesKey
&& hDevicesKey
!= hBaseKey
)
3119 ZwClose(hDevicesKey
);
3121 ZwClose(hDeviceKey
);
3122 if (pDeviceInformation
)
3123 ExFreePool(pDeviceInformation
);
3124 if (pValueInformation
)
3125 ExFreePool(pValueInformation
);
3129 static BOOLEAN INIT_FUNCTION
3130 IopIsFirmwareMapperDisabled(VOID
)
3132 UNICODE_STRING KeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CURRENTCONTROLSET\\Control\\Pnp");
3133 UNICODE_STRING KeyNameU
= RTL_CONSTANT_STRING(L
"DisableFirmwareMapper");
3134 OBJECT_ATTRIBUTES ObjectAttributes
;
3136 PKEY_VALUE_PARTIAL_INFORMATION KeyInformation
;
3137 ULONG DesiredLength
, Length
;
3141 InitializeObjectAttributes(&ObjectAttributes
, &KeyPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3142 Status
= ZwOpenKey(&hPnpKey
, KEY_QUERY_VALUE
, &ObjectAttributes
);
3143 if (NT_SUCCESS(Status
))
3145 Status
= ZwQueryValueKey(hPnpKey
,
3147 KeyValuePartialInformation
,
3151 if ((Status
== STATUS_BUFFER_TOO_SMALL
) ||
3152 (Status
== STATUS_BUFFER_OVERFLOW
))
3154 Length
= DesiredLength
;
3155 KeyInformation
= ExAllocatePool(PagedPool
, Length
);
3158 Status
= ZwQueryValueKey(hPnpKey
,
3160 KeyValuePartialInformation
,
3164 if (NT_SUCCESS(Status
) && KeyInformation
->DataLength
== sizeof(ULONG
))
3166 KeyValue
= (ULONG
)(*KeyInformation
->Data
);
3170 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed\n", &KeyPathU
, &KeyNameU
);
3173 ExFreePool(KeyInformation
);
3177 DPRINT1("Failed to allocate memory for registry query\n");
3182 DPRINT1("ZwQueryValueKey(%wZ%wZ) failed with status 0x%08lx\n", &KeyPathU
, &KeyNameU
, Status
);
3189 DPRINT1("ZwOpenKey(%wZ) failed with status 0x%08lx\n", &KeyPathU
, Status
);
3192 DPRINT1("Firmware mapper is %s\n", KeyValue
!= 0 ? "disabled" : "enabled");
3194 return (KeyValue
!= 0) ? TRUE
: FALSE
;
3200 IopUpdateRootKey(VOID
)
3202 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
3203 UNICODE_STRING RootPathU
= RTL_CONSTANT_STRING(L
"Root");
3204 UNICODE_STRING MultiKeyPathU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter");
3205 OBJECT_ATTRIBUTES ObjectAttributes
;
3206 HANDLE hEnum
, hRoot
;
3209 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
3210 Status
= ZwCreateKey(&hEnum
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3211 if (!NT_SUCCESS(Status
))
3213 DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status
);
3217 InitializeObjectAttributes(&ObjectAttributes
, &RootPathU
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hEnum
, NULL
);
3218 Status
= ZwCreateKey(&hRoot
, KEY_CREATE_SUB_KEY
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
3220 if (!NT_SUCCESS(Status
))
3222 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3226 if (!IopIsFirmwareMapperDisabled())
3228 Status
= IopOpenRegistryKeyEx(&hEnum
, NULL
, &MultiKeyPathU
, KEY_ENUMERATE_SUB_KEYS
);
3229 if (!NT_SUCCESS(Status
))
3231 /* Nothing to do, don't return with an error status */
3232 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status
);
3234 return STATUS_SUCCESS
;
3236 Status
= IopEnumerateDetectedDevices(
3247 /* Enumeration is disabled */
3248 Status
= STATUS_SUCCESS
;
3258 IopOpenRegistryKeyEx(PHANDLE KeyHandle
,
3260 PUNICODE_STRING Name
,
3261 ACCESS_MASK DesiredAccess
)
3263 OBJECT_ATTRIBUTES ObjectAttributes
;
3270 InitializeObjectAttributes(&ObjectAttributes
,
3272 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3276 Status
= ZwOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
3283 IopCreateRegistryKeyEx(OUT PHANDLE Handle
,
3284 IN HANDLE RootHandle OPTIONAL
,
3285 IN PUNICODE_STRING KeyName
,
3286 IN ACCESS_MASK DesiredAccess
,
3287 IN ULONG CreateOptions
,
3288 OUT PULONG Disposition OPTIONAL
)
3290 OBJECT_ATTRIBUTES ObjectAttributes
;
3291 ULONG KeyDisposition
, RootHandleIndex
= 0, i
= 1, NestedCloseLevel
= 0;
3293 HANDLE HandleArray
[2];
3294 BOOLEAN Recursing
= TRUE
;
3296 UNICODE_STRING KeyString
;
3297 NTSTATUS Status
= STATUS_SUCCESS
;
3300 /* P1 is start, pp is end */
3301 p1
= KeyName
->Buffer
;
3302 pp
= (PVOID
)((ULONG_PTR
)p1
+ KeyName
->Length
);
3304 /* Create the target key */
3305 InitializeObjectAttributes(&ObjectAttributes
,
3307 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3310 Status
= ZwCreateKey(&HandleArray
[i
],
3318 /* Now we check if this failed */
3319 if ((Status
== STATUS_OBJECT_NAME_NOT_FOUND
) && (RootHandle
))
3321 /* Target key failed, so we'll need to create its parent. Setup array */
3322 HandleArray
[0] = NULL
;
3323 HandleArray
[1] = RootHandle
;
3325 /* Keep recursing for each missing parent */
3328 /* And if we're deep enough, close the last handle */
3329 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
3331 /* We're setup to ping-pong between the two handle array entries */
3332 RootHandleIndex
= i
;
3335 /* Clear the one we're attempting to open now */
3336 HandleArray
[i
] = NULL
;
3338 /* Process the parent key name */
3339 for (p
= p1
; ((p
< pp
) && (*p
!= OBJ_NAME_PATH_SEPARATOR
)); p
++);
3340 Length
= (USHORT
)(p
- p1
) * sizeof(WCHAR
);
3342 /* Is there a parent name? */
3345 /* Build the unicode string for it */
3346 KeyString
.Buffer
= p1
;
3347 KeyString
.Length
= KeyString
.MaximumLength
= Length
;
3349 /* Now try opening the parent */
3350 InitializeObjectAttributes(&ObjectAttributes
,
3352 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
3353 HandleArray
[RootHandleIndex
],
3355 Status
= ZwCreateKey(&HandleArray
[i
],
3362 if (NT_SUCCESS(Status
))
3364 /* It worked, we have one more handle */
3369 /* Parent key creation failed, abandon loop */
3376 /* We don't have a parent name, probably corrupted key name */
3377 Status
= STATUS_INVALID_PARAMETER
;
3382 /* Now see if there's more parents to create */
3384 if ((p
== pp
) || (p1
== pp
))
3386 /* We're done, hopefully successfully, so stop */
3391 /* Outer loop check for handle nesting that requires closing the top handle */
3392 if (NestedCloseLevel
> 1) ZwClose(HandleArray
[RootHandleIndex
]);
3395 /* Check if we broke out of the loop due to success */
3396 if (NT_SUCCESS(Status
))
3398 /* Return the target handle (we closed all the parent ones) and disposition */
3399 *Handle
= HandleArray
[i
];
3400 if (Disposition
) *Disposition
= KeyDisposition
;
3403 /* Return the success state */
3409 IopGetRegistryValue(IN HANDLE Handle
,
3411 OUT PKEY_VALUE_FULL_INFORMATION
*Information
)
3413 UNICODE_STRING ValueString
;
3415 PKEY_VALUE_FULL_INFORMATION FullInformation
;
3419 RtlInitUnicodeString(&ValueString
, ValueName
);
3421 Status
= ZwQueryValueKey(Handle
,
3423 KeyValueFullInformation
,
3427 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
3428 (Status
!= STATUS_BUFFER_TOO_SMALL
))
3433 FullInformation
= ExAllocatePool(NonPagedPool
, Size
);
3434 if (!FullInformation
) return STATUS_INSUFFICIENT_RESOURCES
;
3436 Status
= ZwQueryValueKey(Handle
,
3438 KeyValueFullInformation
,
3442 if (!NT_SUCCESS(Status
))
3444 ExFreePool(FullInformation
);
3448 *Information
= FullInformation
;
3449 return STATUS_SUCCESS
;
3452 RTL_GENERIC_COMPARE_RESULTS
3454 PiCompareInstancePath(IN PRTL_AVL_TABLE Table
,
3455 IN PVOID FirstStruct
,
3456 IN PVOID SecondStruct
)
3464 // The allocation function is called by the generic table package whenever
3465 // it needs to allocate memory for the table.
3470 PiAllocateGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3480 PiFreeGenericTableEntry(IN PRTL_AVL_TABLE Table
,
3489 PpInitializeDeviceReferenceTable(VOID
)
3491 /* Setup the guarded mutex and AVL table */
3492 KeInitializeGuardedMutex(&PpDeviceReferenceTableLock
);
3493 RtlInitializeGenericTableAvl(
3494 &PpDeviceReferenceTable
,
3495 (PRTL_AVL_COMPARE_ROUTINE
)PiCompareInstancePath
,
3496 (PRTL_AVL_ALLOCATE_ROUTINE
)PiAllocateGenericTableEntry
,
3497 (PRTL_AVL_FREE_ROUTINE
)PiFreeGenericTableEntry
,
3505 /* Initialize the resource when accessing device registry data */
3506 ExInitializeResourceLite(&PpRegistryDeviceResource
);
3508 /* Setup the device reference AVL table */
3509 PpInitializeDeviceReferenceTable();
3517 /* Check the initialization phase */
3518 switch (ExpInitializationPhase
)
3523 return PiInitPhase0();
3529 //return PiInitPhase1();
3533 /* Don't know any other phase! Bugcheck! */
3534 KeBugCheck(UNEXPECTED_INITIALIZATION_CALL
);
3539 LONG IopNumberDeviceNodes
;
3543 PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject
)
3545 PDEVICE_NODE DeviceNode
;
3549 DeviceNode
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(DEVICE_NODE
), TAG_IO_DEVNODE
);
3550 if (!DeviceNode
) return DeviceNode
;
3553 InterlockedIncrement(&IopNumberDeviceNodes
);
3556 RtlZeroMemory(DeviceNode
, sizeof(DEVICE_NODE
));
3557 DeviceNode
->InterfaceType
= InterfaceTypeUndefined
;
3558 DeviceNode
->BusNumber
= -1;
3559 DeviceNode
->ChildInterfaceType
= InterfaceTypeUndefined
;
3560 DeviceNode
->ChildBusNumber
= -1;
3561 DeviceNode
->ChildBusTypeIndex
= -1;
3562 // KeInitializeEvent(&DeviceNode->EnumerationMutex, SynchronizationEvent, TRUE);
3563 InitializeListHead(&DeviceNode
->DeviceArbiterList
);
3564 InitializeListHead(&DeviceNode
->DeviceTranslatorList
);
3565 InitializeListHead(&DeviceNode
->TargetDeviceNotify
);
3566 InitializeListHead(&DeviceNode
->DockInfo
.ListEntry
);
3567 InitializeListHead(&DeviceNode
->PendedSetInterfaceState
);
3569 /* Check if there is a PDO */
3570 if (PhysicalDeviceObject
)
3572 /* Link it and remove the init flag */
3573 DeviceNode
->PhysicalDeviceObject
= PhysicalDeviceObject
;
3574 ((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
= DeviceNode
;
3575 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3578 /* Return the node */
3582 /* PUBLIC FUNCTIONS **********************************************************/
3586 PnpBusTypeGuidGet(IN USHORT Index
,
3587 IN LPGUID BusTypeGuid
)
3589 NTSTATUS Status
= STATUS_SUCCESS
;
3591 /* Acquire the lock */
3592 ExAcquireFastMutex(&PnpBusTypeGuidList
->Lock
);
3595 if (Index
< PnpBusTypeGuidList
->GuidCount
)
3598 RtlCopyMemory(BusTypeGuid
, &PnpBusTypeGuidList
->Guids
[Index
], sizeof(GUID
));
3603 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
3606 /* Release lock and return status */
3607 ExReleaseFastMutex(&PnpBusTypeGuidList
->Lock
);
3613 PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject
,
3614 IN PHANDLE DeviceInstanceHandle
,
3615 IN ACCESS_MASK DesiredAccess
)
3619 PDEVICE_NODE DeviceNode
;
3620 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
3623 /* Open the enum key */
3624 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
3628 if (!NT_SUCCESS(Status
)) return Status
;
3630 /* Make sure we have an instance path */
3631 DeviceNode
= IopGetDeviceNode(DeviceObject
);
3632 if ((DeviceNode
) && (DeviceNode
->InstancePath
.Length
))
3634 /* Get the instance key */
3635 Status
= IopOpenRegistryKeyEx(DeviceInstanceHandle
,
3637 &DeviceNode
->InstancePath
,
3643 Status
= STATUS_INVALID_DEVICE_REQUEST
;
3646 /* Close the handle and return status */
3653 PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList
)
3655 ULONG FinalSize
, PartialSize
, EntrySize
, i
, j
;
3656 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor
;
3657 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
3659 /* If we don't have one, that's easy */
3660 if (!ResourceList
) return 0;
3662 /* Start with the minimum size possible */
3663 FinalSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
3665 /* Loop each full descriptor */
3666 FullDescriptor
= ResourceList
->List
;
3667 for (i
= 0; i
< ResourceList
->Count
; i
++)
3669 /* Start with the minimum size possible */
3670 PartialSize
= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR
, PartialResourceList
) +
3671 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
);
3673 /* Loop each partial descriptor */
3674 PartialDescriptor
= FullDescriptor
->PartialResourceList
.PartialDescriptors
;
3675 for (j
= 0; j
< FullDescriptor
->PartialResourceList
.Count
; j
++)
3677 /* Start with the minimum size possible */
3678 EntrySize
= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
);
3680 /* Check if there is extra data */
3681 if (PartialDescriptor
->Type
== CmResourceTypeDeviceSpecific
)
3684 EntrySize
+= PartialDescriptor
->u
.DeviceSpecificData
.DataSize
;
3687 /* The size of partial descriptors is bigger */
3688 PartialSize
+= EntrySize
;
3690 /* Go to the next partial descriptor */
3691 PartialDescriptor
= (PVOID
)((ULONG_PTR
)PartialDescriptor
+ EntrySize
);
3694 /* The size of full descriptors is bigger */
3695 FinalSize
+= PartialSize
;
3697 /* Go to the next full descriptor */
3698 FullDescriptor
= (PVOID
)((ULONG_PTR
)FullDescriptor
+ PartialSize
);
3701 /* Return the final size */
3707 PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject
,
3712 IN PULONG BufferLength
)
3715 HANDLE KeyHandle
, SubHandle
;
3716 UNICODE_STRING KeyString
;
3717 PKEY_VALUE_FULL_INFORMATION KeyValueInfo
= NULL
;
3721 /* Find the instance key */
3722 Status
= PnpDeviceObjectToDeviceInstance(DeviceObject
, &KeyHandle
, KEY_READ
);
3723 if (NT_SUCCESS(Status
))
3725 /* Check for name given by caller */
3729 RtlInitUnicodeString(&KeyString
, KeyName
);
3730 Status
= IopOpenRegistryKeyEx(&SubHandle
,
3734 if (NT_SUCCESS(Status
))
3736 /* And use this handle instead */
3738 KeyHandle
= SubHandle
;
3742 /* Check if sub-key handle succeeded (or no-op if no key name given) */
3743 if (NT_SUCCESS(Status
))
3745 /* Now get the size of the property */
3746 Status
= IopGetRegistryValue(KeyHandle
,
3755 /* Fail if any of the registry operations failed */
3756 if (!NT_SUCCESS(Status
)) return Status
;
3758 /* Check how much data we have to copy */
3759 Length
= KeyValueInfo
->DataLength
;
3760 if (*BufferLength
>= Length
)
3762 /* Check for a match in the value type */
3763 if (KeyValueInfo
->Type
== ValueType
)
3766 RtlCopyMemory(Buffer
,
3767 (PVOID
)((ULONG_PTR
)KeyValueInfo
+
3768 KeyValueInfo
->DataOffset
),
3773 /* Invalid registry property type, fail */
3774 Status
= STATUS_INVALID_PARAMETER_2
;
3779 /* Buffer is too small to hold data */
3780 Status
= STATUS_BUFFER_TOO_SMALL
;
3783 /* Return the required buffer length, free the buffer, and return status */
3784 *BufferLength
= Length
;
3785 ExFreePool(KeyValueInfo
);
3789 #define PIP_RETURN_DATA(x, y) {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;}
3790 #define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;}
3791 #define PIP_UNIMPLEMENTED() {UNIMPLEMENTED_DBGBREAK(); break;}
3798 IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject
,
3799 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
3800 IN ULONG BufferLength
,
3801 OUT PVOID PropertyBuffer
,
3802 OUT PULONG ResultLength
)
3804 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
3805 DEVICE_CAPABILITIES DeviceCaps
;
3806 ULONG ReturnLength
= 0, Length
= 0, ValueType
;
3807 PWCHAR ValueName
= NULL
, EnumeratorNameEnd
, DeviceInstanceName
;
3809 NTSTATUS Status
= STATUS_BUFFER_TOO_SMALL
;
3811 POBJECT_NAME_INFORMATION ObjectNameInfo
= NULL
;
3812 BOOLEAN NullTerminate
= FALSE
;
3814 DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject
, DeviceProperty
);
3816 /* Assume failure */
3819 /* Only PDOs can call this */
3820 if (!DeviceNode
) return STATUS_INVALID_DEVICE_REQUEST
;
3822 /* Handle all properties */
3823 switch (DeviceProperty
)
3825 case DevicePropertyBusTypeGuid
:
3827 /* Get the GUID from the internal cache */
3828 Status
= PnpBusTypeGuidGet(DeviceNode
->ChildBusTypeIndex
, &BusTypeGuid
);
3829 if (!NT_SUCCESS(Status
)) return Status
;
3831 /* This is the format of the returned data */
3832 PIP_RETURN_DATA(sizeof(GUID
), &BusTypeGuid
);
3834 case DevicePropertyLegacyBusType
:
3836 /* Validate correct interface type */
3837 if (DeviceNode
->ChildInterfaceType
== InterfaceTypeUndefined
)
3838 return STATUS_OBJECT_NAME_NOT_FOUND
;
3840 /* This is the format of the returned data */
3841 PIP_RETURN_DATA(sizeof(INTERFACE_TYPE
), &DeviceNode
->ChildInterfaceType
);
3843 case DevicePropertyBusNumber
:
3845 /* Validate correct bus number */
3846 if ((DeviceNode
->ChildBusNumber
& 0x80000000) == 0x80000000)
3847 return STATUS_OBJECT_NAME_NOT_FOUND
;
3849 /* This is the format of the returned data */
3850 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceNode
->ChildBusNumber
);
3852 case DevicePropertyEnumeratorName
:
3854 /* Get the instance path */
3855 DeviceInstanceName
= DeviceNode
->InstancePath
.Buffer
;
3858 ASSERT((BufferLength
& 1) == 0);
3859 ASSERT(DeviceInstanceName
!= NULL
);
3861 /* Get the name from the path */
3862 EnumeratorNameEnd
= wcschr(DeviceInstanceName
, OBJ_NAME_PATH_SEPARATOR
);
3863 ASSERT(EnumeratorNameEnd
);
3865 /* This string needs to be NULL-terminated */
3866 NullTerminate
= TRUE
;
3868 /* This is the format of the returned data */
3869 PIP_RETURN_DATA((ULONG
)(EnumeratorNameEnd
- DeviceInstanceName
) * sizeof(WCHAR
),
3870 DeviceInstanceName
);
3872 case DevicePropertyAddress
:
3874 /* Query the device caps */
3875 Status
= IopQueryDeviceCapabilities(DeviceNode
, &DeviceCaps
);
3876 if (!NT_SUCCESS(Status
) || (DeviceCaps
.Address
== MAXULONG
))
3877 return STATUS_OBJECT_NAME_NOT_FOUND
;
3879 /* This is the format of the returned data */
3880 PIP_RETURN_DATA(sizeof(ULONG
), &DeviceCaps
.Address
);
3882 case DevicePropertyBootConfigurationTranslated
:
3884 /* Validate we have resources */
3885 if (!DeviceNode
->BootResources
)
3886 // if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field
3888 /* No resources will still fake success, but with 0 bytes */
3890 return STATUS_SUCCESS
;
3893 /* This is the format of the returned data */
3894 PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode
->BootResources
), // FIXFIX: Should use BootResourcesTranslated
3895 DeviceNode
->BootResources
); // FIXFIX: Should use BootResourcesTranslated
3897 case DevicePropertyPhysicalDeviceObjectName
:
3899 /* Sanity check for Unicode-sized string */
3900 ASSERT((BufferLength
& 1) == 0);
3902 /* Allocate name buffer */
3903 Length
= BufferLength
+ sizeof(OBJECT_NAME_INFORMATION
);
3904 ObjectNameInfo
= ExAllocatePool(PagedPool
, Length
);
3905 if (!ObjectNameInfo
) return STATUS_INSUFFICIENT_RESOURCES
;
3907 /* Query the PDO name */
3908 Status
= ObQueryNameString(DeviceObject
,
3912 if (Status
== STATUS_INFO_LENGTH_MISMATCH
)
3914 /* It's up to the caller to try again */
3915 Status
= STATUS_BUFFER_TOO_SMALL
;
3918 /* This string needs to be NULL-terminated */
3919 NullTerminate
= TRUE
;
3921 /* Return if successful */
3922 if (NT_SUCCESS(Status
)) PIP_RETURN_DATA(ObjectNameInfo
->Name
.Length
,
3923 ObjectNameInfo
->Name
.Buffer
);
3925 /* Let the caller know how big the name is */
3926 *ResultLength
-= sizeof(OBJECT_NAME_INFORMATION
);
3929 /* Handle the registry-based properties */
3930 case DevicePropertyUINumber
:
3931 PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER
, REG_DWORD
);
3932 case DevicePropertyLocationInformation
:
3933 PIP_REGISTRY_DATA(REGSTR_VAL_LOCATION_INFORMATION
, REG_SZ
);
3934 case DevicePropertyDeviceDescription
:
3935 PIP_REGISTRY_DATA(REGSTR_VAL_DEVDESC
, REG_SZ
);
3936 case DevicePropertyHardwareID
:
3937 PIP_REGISTRY_DATA(REGSTR_VAL_HARDWAREID
, REG_MULTI_SZ
);
3938 case DevicePropertyCompatibleIDs
:
3939 PIP_REGISTRY_DATA(REGSTR_VAL_COMPATIBLEIDS
, REG_MULTI_SZ
);
3940 case DevicePropertyBootConfiguration
:
3941 PIP_REGISTRY_DATA(REGSTR_VAL_BOOTCONFIG
, REG_RESOURCE_LIST
);
3942 case DevicePropertyClassName
:
3943 PIP_REGISTRY_DATA(REGSTR_VAL_CLASS
, REG_SZ
);
3944 case DevicePropertyClassGuid
:
3945 PIP_REGISTRY_DATA(REGSTR_VAL_CLASSGUID
, REG_SZ
);
3946 case DevicePropertyDriverKeyName
:
3947 PIP_REGISTRY_DATA(REGSTR_VAL_DRIVER
, REG_SZ
);
3948 case DevicePropertyManufacturer
:
3949 PIP_REGISTRY_DATA(REGSTR_VAL_MFG
, REG_SZ
);
3950 case DevicePropertyFriendlyName
:
3951 PIP_REGISTRY_DATA(REGSTR_VAL_FRIENDLYNAME
, REG_SZ
);
3952 case DevicePropertyContainerID
:
3953 //PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7
3954 PIP_UNIMPLEMENTED();
3955 case DevicePropertyRemovalPolicy
:
3956 PIP_UNIMPLEMENTED();
3957 case DevicePropertyInstallState
:
3958 PIP_UNIMPLEMENTED();
3959 case DevicePropertyResourceRequirements
:
3960 PIP_UNIMPLEMENTED();
3961 case DevicePropertyAllocatedResources
:
3962 PIP_UNIMPLEMENTED();
3964 return STATUS_INVALID_PARAMETER_2
;
3967 /* Having a registry value name implies registry data */
3970 /* We know up-front how much data to expect */
3971 *ResultLength
= BufferLength
;
3973 /* Go get the data, use the LogConf subkey if necessary */
3974 Status
= PiGetDeviceRegistryProperty(DeviceObject
,
3978 DevicePropertyBootConfiguration
) ?
3983 else if (NT_SUCCESS(Status
))
3985 /* We know up-front how much data to expect, check the caller's buffer */
3986 *ResultLength
= ReturnLength
+ (NullTerminate
? sizeof(UNICODE_NULL
) : 0);
3987 if (*ResultLength
<= BufferLength
)
3989 /* Buffer is all good, copy the data */
3990 RtlCopyMemory(PropertyBuffer
, Data
, ReturnLength
);
3992 /* Check if we need to NULL-terminate the string */
3995 /* Terminate the string */
3996 ((PWCHAR
)PropertyBuffer
)[ReturnLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
3999 /* This is the success path */
4000 Status
= STATUS_SUCCESS
;
4005 Status
= STATUS_BUFFER_TOO_SMALL
;
4009 /* Free any allocation we may have made, and return the status code */
4010 if (ObjectNameInfo
) ExFreePool(ObjectNameInfo
);
4019 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4021 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(PhysicalDeviceObject
);
4022 IO_STACK_LOCATION Stack
;
4025 IO_STATUS_BLOCK IoStatusBlock
;
4027 RtlZeroMemory(&Stack
, sizeof(IO_STACK_LOCATION
));
4028 Stack
.MajorFunction
= IRP_MJ_PNP
;
4029 Stack
.MinorFunction
= IRP_MN_QUERY_PNP_DEVICE_STATE
;
4031 Status
= IopSynchronousCall(PhysicalDeviceObject
, &Stack
, (PVOID
*)&PnPFlags
);
4032 if (!NT_SUCCESS(Status
))
4034 DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE failed with status 0x%x\n", Status
);
4038 if (PnPFlags
& PNP_DEVICE_NOT_DISABLEABLE
)
4039 DeviceNode
->UserFlags
|= DNUF_NOT_DISABLEABLE
;
4041 DeviceNode
->UserFlags
&= ~DNUF_NOT_DISABLEABLE
;
4043 if (PnPFlags
& PNP_DEVICE_DONT_DISPLAY_IN_UI
)
4044 DeviceNode
->UserFlags
|= DNUF_DONT_SHOW_IN_UI
;
4046 DeviceNode
->UserFlags
&= ~DNUF_DONT_SHOW_IN_UI
;
4048 if ((PnPFlags
& PNP_DEVICE_REMOVED
) ||
4049 ((PnPFlags
& PNP_DEVICE_FAILED
) && !(PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
)))
4051 /* Flag it if it's failed */
4052 if (PnPFlags
& PNP_DEVICE_FAILED
) DeviceNode
->Problem
= CM_PROB_FAILED_POST_START
;
4054 /* Send removal IRPs to all of its children */
4055 IopPrepareDeviceForRemoval(PhysicalDeviceObject
, TRUE
);
4057 /* Send surprise removal */
4058 IopSendSurpriseRemoval(PhysicalDeviceObject
);
4060 /* Tell the user-mode PnP manager that a device was removed */
4061 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL
,
4062 &DeviceNode
->InstancePath
);
4064 IopSendRemoveDevice(PhysicalDeviceObject
);
4066 else if ((PnPFlags
& PNP_DEVICE_FAILED
) && (PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
))
4068 /* Stop for resource rebalance */
4069 Status
= IopStopDevice(DeviceNode
);
4070 if (!NT_SUCCESS(Status
))
4072 DPRINT1("Failed to stop device for rebalancing\n");
4074 /* Stop failed so don't rebalance */
4075 PnPFlags
&= ~PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
;
4079 /* Resource rebalance */
4080 if (PnPFlags
& PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
)
4082 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
4084 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
4086 IRP_MN_QUERY_RESOURCES
,
4088 if (NT_SUCCESS(Status
) && IoStatusBlock
.Information
)
4090 DeviceNode
->BootResources
=
4091 (PCM_RESOURCE_LIST
)IoStatusBlock
.Information
;
4092 IopDeviceNodeSetFlag(DeviceNode
, DNF_HAS_BOOT_CONFIG
);
4096 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status
);
4097 DeviceNode
->BootResources
= NULL
;
4100 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
4102 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
4104 IRP_MN_QUERY_RESOURCE_REQUIREMENTS
,
4106 if (NT_SUCCESS(Status
))
4108 DeviceNode
->ResourceRequirements
=
4109 (PIO_RESOURCE_REQUIREMENTS_LIST
)IoStatusBlock
.Information
;
4113 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status
);
4114 DeviceNode
->ResourceRequirements
= NULL
;
4117 /* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by IopStartDevice */
4118 if (IopStartDevice(DeviceNode
) != STATUS_SUCCESS
)
4120 DPRINT1("Restart after resource rebalance failed\n");
4122 DeviceNode
->Flags
&= ~(DNF_STARTED
| DNF_START_REQUEST_PENDING
);
4123 DeviceNode
->Flags
|= DNF_START_FAILED
;
4125 IopRemoveDevice(DeviceNode
);
4131 * @name IoOpenDeviceRegistryKey
4133 * Open a registry key unique for a specified driver or device instance.
4135 * @param DeviceObject Device to get the registry key for.
4136 * @param DevInstKeyType Type of the key to return.
4137 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
4138 * @param DevInstRegKey Handle to the opened registry key on
4139 * successful return.
4147 IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject
,
4148 IN ULONG DevInstKeyType
,
4149 IN ACCESS_MASK DesiredAccess
,
4150 OUT PHANDLE DevInstRegKey
)
4152 static WCHAR RootKeyName
[] =
4153 L
"\\Registry\\Machine\\System\\CurrentControlSet\\";
4154 static WCHAR ProfileKeyName
[] =
4155 L
"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
4156 static WCHAR ClassKeyName
[] = L
"Control\\Class\\";
4157 static WCHAR EnumKeyName
[] = L
"Enum\\";
4158 static WCHAR DeviceParametersKeyName
[] = L
"Device Parameters";
4159 ULONG KeyNameLength
;
4160 LPWSTR KeyNameBuffer
;
4161 UNICODE_STRING KeyName
;
4162 ULONG DriverKeyLength
;
4163 OBJECT_ATTRIBUTES ObjectAttributes
;
4164 PDEVICE_NODE DeviceNode
= NULL
;
4167 DPRINT("IoOpenDeviceRegistryKey() called\n");
4169 if ((DevInstKeyType
& (PLUGPLAY_REGKEY_DEVICE
| PLUGPLAY_REGKEY_DRIVER
)) == 0)
4171 DPRINT1("IoOpenDeviceRegistryKey(): got wrong params, exiting... \n");
4172 return STATUS_INVALID_PARAMETER
;
4175 if (!IopIsValidPhysicalDeviceObject(DeviceObject
))
4176 return STATUS_INVALID_DEVICE_REQUEST
;
4177 DeviceNode
= IopGetDeviceNode(DeviceObject
);
4180 * Calculate the length of the base key name. This is the full
4181 * name for driver key or the name excluding "Device Parameters"
4182 * subkey for device key.
4185 KeyNameLength
= sizeof(RootKeyName
);
4186 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
4187 KeyNameLength
+= sizeof(ProfileKeyName
) - sizeof(UNICODE_NULL
);
4188 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4190 KeyNameLength
+= sizeof(ClassKeyName
) - sizeof(UNICODE_NULL
);
4191 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
4192 0, NULL
, &DriverKeyLength
);
4193 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
4195 KeyNameLength
+= DriverKeyLength
;
4199 KeyNameLength
+= sizeof(EnumKeyName
) - sizeof(UNICODE_NULL
) +
4200 DeviceNode
->InstancePath
.Length
;
4204 * Now allocate the buffer for the key name...
4207 KeyNameBuffer
= ExAllocatePool(PagedPool
, KeyNameLength
);
4208 if (KeyNameBuffer
== NULL
)
4209 return STATUS_INSUFFICIENT_RESOURCES
;
4212 KeyName
.MaximumLength
= (USHORT
)KeyNameLength
;
4213 KeyName
.Buffer
= KeyNameBuffer
;
4216 * ...and build the key name.
4219 KeyName
.Length
+= sizeof(RootKeyName
) - sizeof(UNICODE_NULL
);
4220 RtlCopyMemory(KeyNameBuffer
, RootKeyName
, KeyName
.Length
);
4222 if (DevInstKeyType
& PLUGPLAY_REGKEY_CURRENT_HWPROFILE
)
4223 RtlAppendUnicodeToString(&KeyName
, ProfileKeyName
);
4225 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4227 RtlAppendUnicodeToString(&KeyName
, ClassKeyName
);
4228 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyDriverKeyName
,
4229 DriverKeyLength
, KeyNameBuffer
+
4230 (KeyName
.Length
/ sizeof(WCHAR
)),
4232 if (!NT_SUCCESS(Status
))
4234 DPRINT1("Call to IoGetDeviceProperty() failed with Status 0x%08lx\n", Status
);
4235 ExFreePool(KeyNameBuffer
);
4238 KeyName
.Length
+= (USHORT
)DriverKeyLength
- sizeof(UNICODE_NULL
);
4242 RtlAppendUnicodeToString(&KeyName
, EnumKeyName
);
4243 Status
= RtlAppendUnicodeStringToString(&KeyName
, &DeviceNode
->InstancePath
);
4244 if (DeviceNode
->InstancePath
.Length
== 0)
4246 ExFreePool(KeyNameBuffer
);
4252 * Open the base key.
4254 Status
= IopOpenRegistryKeyEx(DevInstRegKey
, NULL
, &KeyName
, DesiredAccess
);
4255 if (!NT_SUCCESS(Status
))
4257 DPRINT1("IoOpenDeviceRegistryKey(%wZ): Base key doesn't exist, exiting... (Status 0x%08lx)\n", &KeyName
, Status
);
4258 ExFreePool(KeyNameBuffer
);
4261 ExFreePool(KeyNameBuffer
);
4264 * For driver key we're done now.
4267 if (DevInstKeyType
& PLUGPLAY_REGKEY_DRIVER
)
4271 * Let's go further. For device key we must open "Device Parameters"
4272 * subkey and create it if it doesn't exist yet.
4275 RtlInitUnicodeString(&KeyName
, DeviceParametersKeyName
);
4276 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
,
4277 OBJ_CASE_INSENSITIVE
, *DevInstRegKey
, NULL
);
4278 Status
= ZwCreateKey(DevInstRegKey
, DesiredAccess
, &ObjectAttributes
,
4279 0, NULL
, ExpInTextModeSetup
? REG_OPTION_VOLATILE
: 0, NULL
);
4280 ZwClose(ObjectAttributes
.RootDirectory
);
4287 IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
, BOOLEAN Force
)
4289 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
, FailedRemoveDevice
;
4293 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4294 ChildDeviceNode
= ParentDeviceNode
->Child
;
4295 while (ChildDeviceNode
!= NULL
)
4297 NextDeviceNode
= ChildDeviceNode
->Sibling
;
4298 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4300 Status
= IopPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
, Force
);
4301 if (!NT_SUCCESS(Status
))
4303 FailedRemoveDevice
= ChildDeviceNode
;
4307 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4308 ChildDeviceNode
= NextDeviceNode
;
4310 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4312 return STATUS_SUCCESS
;
4315 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4316 ChildDeviceNode
= ParentDeviceNode
->Child
;
4317 while (ChildDeviceNode
!= NULL
)
4319 NextDeviceNode
= ChildDeviceNode
->Sibling
;
4320 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4322 IopCancelPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
);
4324 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
4325 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
4326 if (ChildDeviceNode
== FailedRemoveDevice
)
4329 ChildDeviceNode
= NextDeviceNode
;
4331 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4333 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4340 IopSendRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
)
4342 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
;
4345 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4346 ChildDeviceNode
= ParentDeviceNode
->Child
;
4347 while (ChildDeviceNode
!= NULL
)
4349 NextDeviceNode
= ChildDeviceNode
->Sibling
;
4350 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4352 IopSendRemoveDevice(ChildDeviceNode
->PhysicalDeviceObject
);
4354 ChildDeviceNode
= NextDeviceNode
;
4356 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4358 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4363 IopCancelRemoveChildDevices(PDEVICE_NODE ParentDeviceNode
)
4365 PDEVICE_NODE ChildDeviceNode
, NextDeviceNode
;
4368 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4369 ChildDeviceNode
= ParentDeviceNode
->Child
;
4370 while (ChildDeviceNode
!= NULL
)
4372 NextDeviceNode
= ChildDeviceNode
->Sibling
;
4373 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4375 IopCancelPrepareDeviceForRemoval(ChildDeviceNode
->PhysicalDeviceObject
);
4377 ChildDeviceNode
= NextDeviceNode
;
4379 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
4381 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
4386 IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
, BOOLEAN Force
)
4388 /* This function DOES NOT dereference the device objects on SUCCESS
4389 * but it DOES dereference device objects on FAILURE */
4394 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4396 Status
= IopPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
], Force
);
4397 if (!NT_SUCCESS(Status
))
4404 return STATUS_SUCCESS
;
4407 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
4408 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
4409 for (i
= 0; i
<= j
; i
++)
4411 IopCancelPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
]);
4412 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4413 DeviceRelations
->Objects
[i
] = NULL
;
4415 for (; i
< DeviceRelations
->Count
; i
++)
4417 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4418 DeviceRelations
->Objects
[i
] = NULL
;
4420 ExFreePool(DeviceRelations
);
4427 IopSendRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
)
4429 /* This function DOES dereference the device objects in all cases */
4433 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4435 IopSendRemoveDevice(DeviceRelations
->Objects
[i
]);
4436 DeviceRelations
->Objects
[i
] = NULL
;
4439 ExFreePool(DeviceRelations
);
4444 IopCancelRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations
)
4446 /* This function DOES dereference the device objects in all cases */
4450 for (i
= 0; i
< DeviceRelations
->Count
; i
++)
4452 IopCancelPrepareDeviceForRemoval(DeviceRelations
->Objects
[i
]);
4453 ObDereferenceObject(DeviceRelations
->Objects
[i
]);
4454 DeviceRelations
->Objects
[i
] = NULL
;
4457 ExFreePool(DeviceRelations
);
4461 IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject
)
4463 IO_STACK_LOCATION Stack
;
4464 IO_STATUS_BLOCK IoStatusBlock
;
4465 PDEVICE_RELATIONS DeviceRelations
;
4468 IopCancelRemoveDevice(DeviceObject
);
4470 Stack
.Parameters
.QueryDeviceRelations
.Type
= RemovalRelations
;
4472 Status
= IopInitiatePnpIrp(DeviceObject
,
4474 IRP_MN_QUERY_DEVICE_RELATIONS
,
4476 if (!NT_SUCCESS(Status
))
4478 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4479 DeviceRelations
= NULL
;
4483 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4486 if (DeviceRelations
)
4487 IopCancelRemoveDeviceRelations(DeviceRelations
);
4491 IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject
, BOOLEAN Force
)
4493 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(DeviceObject
);
4494 IO_STACK_LOCATION Stack
;
4495 IO_STATUS_BLOCK IoStatusBlock
;
4496 PDEVICE_RELATIONS DeviceRelations
;
4499 if ((DeviceNode
->UserFlags
& DNUF_NOT_DISABLEABLE
) && !Force
)
4501 DPRINT1("Removal not allowed for %wZ\n", &DeviceNode
->InstancePath
);
4502 return STATUS_UNSUCCESSFUL
;
4505 if (!Force
&& IopQueryRemoveDevice(DeviceObject
) != STATUS_SUCCESS
)
4507 DPRINT1("Removal vetoed by failing the query remove request\n");
4509 IopCancelRemoveDevice(DeviceObject
);
4511 return STATUS_UNSUCCESSFUL
;
4514 Stack
.Parameters
.QueryDeviceRelations
.Type
= RemovalRelations
;
4516 Status
= IopInitiatePnpIrp(DeviceObject
,
4518 IRP_MN_QUERY_DEVICE_RELATIONS
,
4520 if (!NT_SUCCESS(Status
))
4522 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4523 DeviceRelations
= NULL
;
4527 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4530 if (DeviceRelations
)
4532 Status
= IopQueryRemoveDeviceRelations(DeviceRelations
, Force
);
4533 if (!NT_SUCCESS(Status
))
4537 Status
= IopQueryRemoveChildDevices(DeviceNode
, Force
);
4538 if (!NT_SUCCESS(Status
))
4540 if (DeviceRelations
)
4541 IopCancelRemoveDeviceRelations(DeviceRelations
);
4545 if (DeviceRelations
)
4546 IopSendRemoveDeviceRelations(DeviceRelations
);
4547 IopSendRemoveChildDevices(DeviceNode
);
4549 return STATUS_SUCCESS
;
4553 IopRemoveDevice(PDEVICE_NODE DeviceNode
)
4557 DPRINT("Removing device: %wZ\n", &DeviceNode
->InstancePath
);
4559 Status
= IopPrepareDeviceForRemoval(DeviceNode
->PhysicalDeviceObject
, FALSE
);
4560 if (NT_SUCCESS(Status
))
4562 IopSendRemoveDevice(DeviceNode
->PhysicalDeviceObject
);
4563 IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL
,
4564 &DeviceNode
->InstancePath
);
4565 return STATUS_SUCCESS
;
4576 IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject
)
4578 PDEVICE_NODE DeviceNode
= IopGetDeviceNode(PhysicalDeviceObject
);
4579 PDEVICE_RELATIONS DeviceRelations
;
4580 IO_STATUS_BLOCK IoStatusBlock
;
4581 IO_STACK_LOCATION Stack
;
4582 DEVICE_CAPABILITIES Capabilities
;
4585 IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT
,
4586 &DeviceNode
->InstancePath
);
4588 if (IopQueryDeviceCapabilities(DeviceNode
, &Capabilities
) != STATUS_SUCCESS
)
4593 Stack
.Parameters
.QueryDeviceRelations
.Type
= EjectionRelations
;
4595 Status
= IopInitiatePnpIrp(PhysicalDeviceObject
,
4597 IRP_MN_QUERY_DEVICE_RELATIONS
,
4599 if (!NT_SUCCESS(Status
))
4601 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status
);
4602 DeviceRelations
= NULL
;
4606 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
4609 if (DeviceRelations
)
4611 Status
= IopQueryRemoveDeviceRelations(DeviceRelations
, FALSE
);
4612 if (!NT_SUCCESS(Status
))
4616 Status
= IopQueryRemoveChildDevices(DeviceNode
, FALSE
);
4617 if (!NT_SUCCESS(Status
))
4619 if (DeviceRelations
)
4620 IopCancelRemoveDeviceRelations(DeviceRelations
);
4624 if (IopPrepareDeviceForRemoval(PhysicalDeviceObject
, FALSE
) != STATUS_SUCCESS
)
4626 if (DeviceRelations
)
4627 IopCancelRemoveDeviceRelations(DeviceRelations
);
4628 IopCancelRemoveChildDevices(DeviceNode
);
4632 if (DeviceRelations
)
4633 IopSendRemoveDeviceRelations(DeviceRelations
);
4634 IopSendRemoveChildDevices(DeviceNode
);
4636 DeviceNode
->Problem
= CM_PROB_HELD_FOR_EJECT
;
4637 if (Capabilities
.EjectSupported
)
4639 if (IopSendEject(PhysicalDeviceObject
) != STATUS_SUCCESS
)
4646 DeviceNode
->Flags
|= DNF_DISABLED
;
4649 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT
,
4650 &DeviceNode
->InstancePath
);
4655 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED
,
4656 &DeviceNode
->InstancePath
);
4664 IoInvalidateDeviceRelations(
4665 IN PDEVICE_OBJECT DeviceObject
,
4666 IN DEVICE_RELATION_TYPE Type
)
4668 PIO_WORKITEM WorkItem
;
4669 PINVALIDATE_DEVICE_RELATION_DATA Data
;
4671 Data
= ExAllocatePool(NonPagedPool
, sizeof(INVALIDATE_DEVICE_RELATION_DATA
));
4674 WorkItem
= IoAllocateWorkItem(DeviceObject
);
4681 ObReferenceObject(DeviceObject
);
4682 Data
->DeviceObject
= DeviceObject
;
4684 Data
->WorkItem
= WorkItem
;
4688 IopAsynchronousInvalidateDeviceRelations
,
4698 IoSynchronousInvalidateDeviceRelations(
4699 IN PDEVICE_OBJECT DeviceObject
,
4700 IN DEVICE_RELATION_TYPE Type
)
4707 /* Enumerate the device */
4708 return IopEnumerateDevice(DeviceObject
);
4709 case PowerRelations
:
4710 /* Not handled yet */
4711 return STATUS_NOT_IMPLEMENTED
;
4712 case TargetDeviceRelation
:
4714 return STATUS_SUCCESS
;
4716 /* Ejection relations are not supported */
4717 return STATUS_NOT_SUPPORTED
;
4726 IoTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
4728 IN PHYSICAL_ADDRESS BusAddress
,
4729 IN OUT PULONG AddressSpace
,
4730 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
4732 /* FIXME: Notify the resource arbiter */
4734 return HalTranslateBusAddress(InterfaceType
,