2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/pnproot.c
5 * PURPOSE: PnP manager root device
7 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
10 /* INCLUDES ******************************************************************/
14 #include <internal/debug.h>
16 /* GLOBALS *******************************************************************/
18 #define ENUM_NAME_ROOT L"Root"
20 /* DATA **********************************************************************/
22 typedef struct _PNPROOT_DEVICE
24 // Entry on device list
26 // Physical Device Object of device
29 UNICODE_STRING ServiceName
;
31 UNICODE_STRING DeviceID
;
33 UNICODE_STRING InstanceID
;
35 UNICODE_STRING DeviceDescription
;
36 // Resource requirement list
37 PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList
;
38 } PNPROOT_DEVICE
, *PPNPROOT_DEVICE
;
47 } PNPROOT_DEVICE_STATE
;
52 typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION
54 // Pointer to device object, this device extension is associated with
55 PDEVICE_OBJECT DeviceObject
;
56 // Wether this device extension is for an FDO or PDO
58 // Wether the device is removed
60 // Current device power state for the device
61 DEVICE_POWER_STATE DevicePowerState
;
62 } PNPROOT_COMMON_DEVICE_EXTENSION
, *PPNPROOT_COMMON_DEVICE_EXTENSION
;
65 /* Physical Device Object device extension for a child device */
66 typedef struct _PNPROOT_PDO_DEVICE_EXTENSION
69 PNPROOT_COMMON_DEVICE_EXTENSION Common
;
71 UNICODE_STRING DeviceID
;
73 UNICODE_STRING InstanceID
;
74 // Resource requirement list
75 PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList
;
76 } PNPROOT_PDO_DEVICE_EXTENSION
, *PPNPROOT_PDO_DEVICE_EXTENSION
;
79 /* Functional Device Object device extension for the PCI driver device object */
80 typedef struct _PNPROOT_FDO_DEVICE_EXTENSION
83 PNPROOT_COMMON_DEVICE_EXTENSION Common
;
84 // Physical Device Object
86 // Lower device object
88 // Current state of the driver
89 PNPROOT_DEVICE_STATE State
;
90 // Namespace device list
91 LIST_ENTRY DeviceListHead
;
92 // Number of (not removed) devices in device list
93 ULONG DeviceListCount
;
94 // Lock for namespace device list
95 // FIXME: Use fast mutex instead?
96 KSPIN_LOCK DeviceListLock
;
97 } PNPROOT_FDO_DEVICE_EXTENSION
, *PPNPROOT_FDO_DEVICE_EXTENSION
;
103 PDEVICE_OBJECT PnpRootDeviceObject
;
106 /* FUNCTIONS *****************************************************************/
108 /* Physical Device Object routines */
112 PDEVICE_OBJECT
*PhysicalDeviceObject
)
114 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
115 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
116 PPNPROOT_DEVICE Device
;
119 /* This function should be obsoleted soon */
123 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)PnpRootDeviceObject
->DeviceExtension
;
125 Device
= (PPNPROOT_DEVICE
)ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
127 return STATUS_INSUFFICIENT_RESOURCES
;
129 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
131 Status
= IoCreateDevice(
132 PnpRootDeviceObject
->DriverObject
,
133 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
135 FILE_DEVICE_CONTROLLER
,
136 FILE_AUTOGENERATED_DEVICE_NAME
,
139 if (!NT_SUCCESS(Status
)) {
140 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status
);
145 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
147 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
149 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
151 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
153 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
155 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
157 PdoDeviceExtension
->Common
.DeviceObject
= Device
->Pdo
;
159 PdoDeviceExtension
->Common
.DevicePowerState
= PowerDeviceD0
;
161 if (!RtlCreateUnicodeString(
162 &PdoDeviceExtension
->DeviceID
,
164 L
"\\LEGACY_UNKNOWN"))
167 DPRINT("RtlCreateUnicodeString() failed\n");
170 if (!RtlCreateUnicodeString(
171 &PdoDeviceExtension
->InstanceID
,
175 DPRINT("RtlCreateUnicodeString() failed\n");
178 ExInterlockedInsertTailList(
179 &DeviceExtension
->DeviceListHead
,
181 &DeviceExtension
->DeviceListLock
);
183 DeviceExtension
->DeviceListCount
++;
185 *PhysicalDeviceObject
= Device
->Pdo
;
187 return STATUS_SUCCESS
;
193 IN PDEVICE_OBJECT DeviceObject
,
195 PIO_STACK_LOCATION IrpSp
)
197 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
198 UNICODE_STRING String
;
203 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
205 // Irp->IoStatus.Information = 0;
207 Status
= STATUS_SUCCESS
;
209 RtlInitUnicodeString(&String
, NULL
);
211 switch (IrpSp
->Parameters
.QueryId
.IdType
) {
212 case BusQueryDeviceID
:
213 Status
= RtlDuplicateUnicodeString(TRUE
,
214 &DeviceExtension
->DeviceID
,
217 DPRINT("DeviceID: %wZ\n", &String
);
219 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
222 case BusQueryHardwareIDs
:
223 case BusQueryCompatibleIDs
:
224 Status
= STATUS_NOT_IMPLEMENTED
;
227 case BusQueryInstanceID
:
228 Status
= RtlDuplicateUnicodeString(TRUE
,
229 &DeviceExtension
->InstanceID
,
232 DPRINT("InstanceID: %S\n", String
.Buffer
);
234 Irp
->IoStatus
.Information
= (ULONG_PTR
)String
.Buffer
;
237 case BusQueryDeviceSerialNumber
:
239 Status
= STATUS_NOT_IMPLEMENTED
;
248 IN PDEVICE_OBJECT DeviceObject
,
250 PIO_STACK_LOCATION IrpSp
)
252 PCM_RESOURCE_LIST ResourceList
;
253 ULONG ResourceListSize
= FIELD_OFFSET(CM_RESOURCE_LIST
, List
);
255 ResourceList
= ExAllocatePool(PagedPool
, ResourceListSize
);
256 if (ResourceList
== NULL
)
257 return STATUS_INSUFFICIENT_RESOURCES
;
259 ResourceList
->Count
= 0;
261 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
263 return STATUS_SUCCESS
;
268 PdoQueryResourceRequirements(
269 IN PDEVICE_OBJECT DeviceObject
,
271 PIO_STACK_LOCATION IrpSp
)
273 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension
;
274 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList
;
275 ULONG ResourceListSize
= FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST
, List
);
279 DeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
281 if (DeviceExtension
->ResourceRequirementsList
== NULL
)
283 /* Create an empty resource list */
284 ResourceList
= ExAllocatePool(PagedPool
, ResourceListSize
);
285 if (ResourceList
== NULL
)
286 return STATUS_INSUFFICIENT_RESOURCES
;
288 RtlZeroMemory(ResourceList
, ResourceListSize
);
289 ResourceList
->ListSize
= ResourceListSize
;
291 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
295 /* Copy existing resource requirement list */
296 ResourceList
= ExAllocatePool(PagedPool
, DeviceExtension
->ResourceRequirementsList
->ListSize
);
297 if (ResourceList
== NULL
)
298 return STATUS_INSUFFICIENT_RESOURCES
;
302 DeviceExtension
->ResourceRequirementsList
,
303 DeviceExtension
->ResourceRequirementsList
->ListSize
);
304 Irp
->IoStatus
.Information
= (ULONG_PTR
)ResourceList
;
307 return STATUS_SUCCESS
;
312 PnpRootPdoQueryCapabilities(
313 IN PDEVICE_OBJECT DeviceObject
,
315 PIO_STACK_LOCATION IrpSp
)
317 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
318 PDEVICE_CAPABILITIES DeviceCapabilities
;
322 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
323 DeviceCapabilities
= IrpSp
->Parameters
.DeviceCapabilities
.Capabilities
;
325 if (DeviceCapabilities
->Version
!= 1)
326 return STATUS_UNSUCCESSFUL
;
328 DeviceCapabilities
->UniqueID
= TRUE
;
329 /* FIXME: Fill other fields */
331 return STATUS_SUCCESS
;
336 * FUNCTION: Handle Plug and Play IRPs for the child device
338 * DeviceObject = Pointer to physical device object of the child device
339 * Irp = Pointer to IRP that should be handled
344 PnpRootPdoPnpControl(
345 PDEVICE_OBJECT DeviceObject
,
348 PIO_STACK_LOCATION IrpSp
;
353 Status
= Irp
->IoStatus
.Status
;
355 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
357 switch (IrpSp
->MinorFunction
) {
359 case IRP_MN_QUERY_BUS_INFORMATION
:
362 case IRP_MN_QUERY_DEVICE_RELATIONS
:
363 /* FIXME: Handle for TargetDeviceRelation */
367 case IRP_MN_QUERY_ID
:
368 Status
= PdoQueryId(DeviceObject
, Irp
, IrpSp
);
371 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
372 Status
= PdoQueryResourceRequirements(DeviceObject
, Irp
, IrpSp
);
375 case IRP_MN_QUERY_RESOURCES
:
376 Status
= PdoQueryResources(DeviceObject
, Irp
, IrpSp
);
379 case IRP_MN_QUERY_CAPABILITIES
:
380 Status
= PnpRootPdoQueryCapabilities(DeviceObject
, Irp
, IrpSp
);
383 case IRP_MN_START_DEVICE
:
384 case IRP_MN_QUERY_STOP_DEVICE
:
385 case IRP_MN_CANCEL_STOP_DEVICE
:
386 case IRP_MN_STOP_DEVICE
:
387 case IRP_MN_QUERY_REMOVE_DEVICE
:
388 case IRP_MN_CANCEL_REMOVE_DEVICE
:
389 case IRP_MN_REMOVE_DEVICE
:
390 case IRP_MN_SURPRISE_REMOVAL
:
391 Status
= STATUS_SUCCESS
;
395 DPRINT("Unknown IOCTL 0x%X\n", IrpSp
->MinorFunction
);
399 Irp
->IoStatus
.Status
= Status
;
400 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
402 DPRINT("Leaving. Status 0x%X\n", Status
);
409 * FUNCTION: Handle power management IRPs for the child device
411 * DeviceObject = Pointer to physical device object of the child device
412 * Irp = Pointer to IRP that should be handled
417 PnpRootPdoPowerControl(
418 PDEVICE_OBJECT DeviceObject
,
421 PIO_STACK_LOCATION IrpSp
;
426 Status
= Irp
->IoStatus
.Status
;
428 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
430 switch (IrpSp
->MinorFunction
) {
432 DPRINT("Unknown IOCTL 0x%X\n", IrpSp
->MinorFunction
);
433 Status
= STATUS_NOT_IMPLEMENTED
;
437 Irp
->IoStatus
.Status
= Status
;
438 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
440 DPRINT("Leaving. Status 0x%X\n", Status
);
446 /* Functional Device Object routines */
449 PnpRootReadRegistryBinary(
451 IN PWSTR ValueKeyName
,
454 OBJECT_ATTRIBUTES ObjectAttributes
;
455 UNICODE_STRING KeyNameU
;
456 UNICODE_STRING ValueKeyNameU
;
457 KEY_VALUE_PARTIAL_INFORMATION Size
;
458 PKEY_VALUE_PARTIAL_INFORMATION Data
= NULL
;
459 ULONG DataSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
);
465 RtlInitUnicodeString(&KeyNameU
, KeyName
);
466 RtlInitUnicodeString(&ValueKeyNameU
, ValueKeyName
);
468 InitializeObjectAttributes(
471 OBJ_CASE_INSENSITIVE
,
473 NULL
); /* Security descriptor */
474 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
475 if (!NT_SUCCESS(Status
))
477 DPRINT("ZwOpenKey() failed (Status 0x%08lx)\n", Status
);
481 Status
= ZwQueryValueKey(
484 KeyValuePartialInformation
,
487 if (Status
!= STATUS_BUFFER_OVERFLOW
)
489 DPRINT("ZwQueryValueKey() failed (Status 0x%08lx)\n", Status
);
494 while (Status
== STATUS_BUFFER_OVERFLOW
)
497 ExFreePoolWithTag(Data
, TAG_PNP_ROOT
);
498 Data
= (PKEY_VALUE_PARTIAL_INFORMATION
)ExAllocatePoolWithTag(PagedPool
, DataSize
, TAG_PNP_ROOT
);
501 DPRINT("ExAllocatePoolWithTag() failed\n", Status
);
506 Status
= ZwQueryValueKey(
509 KeyValuePartialInformation
,
512 if (NT_SUCCESS(Status
))
514 *Buffer
= ExAllocatePoolWithTag(PagedPool
, Data
->DataLength
, TAG_PNP_ROOT
);
517 DPRINT("ExAllocatePoolWithTag() failed\n", Status
);
518 ExFreePoolWithTag(Data
, TAG_PNP_ROOT
);
532 ExFreePoolWithTag(Data
, TAG_PNP_ROOT
);
539 PnpRootFdoReadDeviceInfo(
540 PPNPROOT_DEVICE Device
)
542 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
543 PUNICODE_STRING DeviceDesc
;
544 WCHAR KeyName
[MAX_PATH
];
549 /* Retrieve configuration from Enum key */
551 DeviceDesc
= &Device
->DeviceDescription
;
553 wcscpy(KeyName
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
554 wcscat(KeyName
, ENUM_NAME_ROOT
);
555 wcscat(KeyName
, L
"\\");
556 wcscat(KeyName
, Device
->ServiceName
.Buffer
);
557 wcscat(KeyName
, L
"\\");
558 wcscat(KeyName
, Device
->InstanceID
.Buffer
);
560 DPRINT("KeyName %S\n", KeyName
);
562 /* 1. Read informations in instance key */
563 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
565 RtlInitUnicodeString(DeviceDesc
, NULL
);
567 QueryTable
[0].Name
= L
"DeviceDesc";
568 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
569 QueryTable
[0].EntryContext
= DeviceDesc
;
571 Status
= RtlQueryRegistryValues(
572 RTL_REGISTRY_ABSOLUTE
| RTL_REGISTRY_OPTIONAL
,
578 DPRINT("RtlQueryRegistryValues() returned status 0x%08lx\n", Status
);
580 if (!NT_SUCCESS(Status
))
585 DPRINT("Got device description: %S\n", DeviceDesc
->Buffer
);
587 /* 2. Read informations in instance key, LogConf subkey */
588 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
589 wcscat(KeyName
, L
"\\LogConf");
591 Status
= PnpRootReadRegistryBinary(
593 L
"BasicConfigVector",
594 (PVOID
*)&Device
->ResourceRequirementsList
);
596 DPRINT("PnpRootReadRegistryBinary() returned status 0x%08lx\n", Status
);
598 if (!NT_SUCCESS(Status
))
603 return STATUS_SUCCESS
;
608 PnpRootFdoEnumerateDevices(
609 PDEVICE_OBJECT DeviceObject
)
611 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
612 OBJECT_ATTRIBUTES ObjectAttributes
, SubKeyAttributes
;
613 PKEY_BASIC_INFORMATION KeyInfo
, SubKeyInfo
;
614 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\" ENUM_NAME_ROOT
);
615 UNICODE_STRING SubKeyName
;
616 PPNPROOT_DEVICE Device
;
617 WCHAR Buffer
[MAX_PATH
];
618 HANDLE KeyHandle
, SubKeyHandle
;
622 ULONG Index1
, Index2
;
626 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
628 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + (MAX_PATH
+1) * sizeof(WCHAR
);
629 KeyInfo
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_PNP_ROOT
);
632 return STATUS_INSUFFICIENT_RESOURCES
;
634 SubKeyInfo
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_PNP_ROOT
);
637 ExFreePoolWithTag(KeyInfo
, TAG_PNP_ROOT
);
638 return STATUS_INSUFFICIENT_RESOURCES
;
641 InitializeObjectAttributes(
644 OBJ_CASE_INSENSITIVE
,
648 Status
= ZwOpenKey(&KeyHandle
, KEY_ENUMERATE_SUB_KEYS
, &ObjectAttributes
);
649 if (!NT_SUCCESS(Status
))
651 DPRINT("ZwOpenKey() failed (Status 0x%08lx)\n", Status
);
652 ExFreePoolWithTag(KeyInfo
, TAG_PNP_ROOT
);
653 ExFreePoolWithTag(SubKeyInfo
, TAG_PNP_ROOT
);
657 /* FIXME: Disabled due to still using the old method of auto loading drivers e.g.
658 there are more entries in the list than found in the registry as some
659 drivers are passed on the command line */
660 // DeviceExtension->DeviceListCount = 0;
662 /* Devices are sub-sub-keys of 'KeyName'. KeyName is already opened as
663 * KeyHandle. We'll first do a first enumeration to have first level keys,
664 * and an inner one to have the real devices list.
670 Status
= ZwEnumerateKey(
677 if (!NT_SUCCESS(Status
))
679 DPRINT("ZwEnumerateKey() (Status 0x%08lx)\n", Status
);
683 /* Terminate the string */
684 KeyInfo
->Name
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
687 RtlInitUnicodeString(&SubKeyName
, KeyInfo
->Name
);
688 InitializeObjectAttributes(
693 NULL
); /* Security descriptor */
694 Status
= ZwOpenKey(&SubKeyHandle
, KEY_ENUMERATE_SUB_KEYS
, &SubKeyAttributes
);
695 if (!NT_SUCCESS(Status
))
697 DPRINT("ZwOpenKey() failed (Status 0x%08lx)\n", Status
);
701 /* Enumerate the sub-keys */
705 Status
= ZwEnumerateKey(
712 if (!NT_SUCCESS(Status
))
714 DPRINT("ZwEnumerateKey() (Status 0x%08lx)\n", Status
);
718 /* Terminate the string */
719 SubKeyInfo
->Name
[SubKeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
721 Device
= (PPNPROOT_DEVICE
)ExAllocatePoolWithTag(PagedPool
, sizeof(PNPROOT_DEVICE
), TAG_PNP_ROOT
);
725 DPRINT("ExAllocatePoolWithTag() failed\n");
729 RtlZeroMemory(Device
, sizeof(PNPROOT_DEVICE
));
731 if (!RtlCreateUnicodeString(&Device
->ServiceName
, KeyInfo
->Name
))
734 DPRINT("RtlCreateUnicodeString() failed\n");
737 wcscpy(Buffer
, ENUM_NAME_ROOT
);
738 wcscat(Buffer
, L
"\\");
739 wcscat(Buffer
, KeyInfo
->Name
);
741 if (!RtlCreateUnicodeString(&Device
->DeviceID
, Buffer
))
744 DPRINT("RtlCreateUnicodeString() failed\n");
747 DPRINT("Got entry: %S\n", Device
->DeviceID
.Buffer
);
749 if (!RtlCreateUnicodeString(
754 DPRINT("RtlCreateUnicodeString() failed\n");
757 Status
= PnpRootFdoReadDeviceInfo(Device
);
758 if (!NT_SUCCESS(Status
))
761 DPRINT("PnpRootFdoReadDeviceInfo() failed with status 0x%08lx\n", Status
);
764 ExInterlockedInsertTailList(
765 &DeviceExtension
->DeviceListHead
,
767 &DeviceExtension
->DeviceListLock
);
769 DeviceExtension
->DeviceListCount
++;
774 ZwClose(SubKeyHandle
);
780 ExFreePoolWithTag(KeyInfo
, TAG_PNP_ROOT
);
781 ExFreePoolWithTag(SubKeyInfo
, TAG_PNP_ROOT
);
783 return STATUS_SUCCESS
;
788 PnpRootQueryBusRelations(
789 IN PDEVICE_OBJECT DeviceObject
,
791 IN PIO_STACK_LOCATION IrpSp
)
793 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension
;
794 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
795 PDEVICE_RELATIONS Relations
;
796 PPNPROOT_DEVICE Device
;
803 Status
= PnpRootFdoEnumerateDevices(DeviceObject
);
804 if (!NT_SUCCESS(Status
))
807 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
809 if (Irp
->IoStatus
.Information
)
811 /* FIXME: Another bus driver has already created a DEVICE_RELATIONS
812 structure so we must merge this structure with our own */
815 Size
= sizeof(DEVICE_RELATIONS
) + sizeof(Relations
->Objects
) *
816 (DeviceExtension
->DeviceListCount
- 1);
818 Relations
= (PDEVICE_RELATIONS
)ExAllocatePool(PagedPool
, Size
);
820 return STATUS_INSUFFICIENT_RESOURCES
;
822 Relations
->Count
= DeviceExtension
->DeviceListCount
;
825 LIST_FOR_EACH(Device
,&DeviceExtension
->DeviceListHead
,PNPROOT_DEVICE
, ListEntry
)
829 /* Create a physical device object for the
830 device as it does not already have one */
831 Status
= IoCreateDevice(
832 DeviceObject
->DriverObject
,
833 sizeof(PNPROOT_PDO_DEVICE_EXTENSION
),
835 FILE_DEVICE_CONTROLLER
,
836 FILE_AUTOGENERATED_DEVICE_NAME
,
839 if (!NT_SUCCESS(Status
))
841 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status
);
842 ExFreePool(Relations
);
846 DPRINT("Created PDO 0x%p\n", Device
->Pdo
);
848 Device
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
850 Device
->Pdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
852 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
854 PdoDeviceExtension
= (PPNPROOT_PDO_DEVICE_EXTENSION
)Device
->Pdo
->DeviceExtension
;
856 RtlZeroMemory(PdoDeviceExtension
, sizeof(PNPROOT_PDO_DEVICE_EXTENSION
));
858 PdoDeviceExtension
->Common
.IsFDO
= FALSE
;
860 PdoDeviceExtension
->Common
.DeviceObject
= Device
->Pdo
;
862 PdoDeviceExtension
->Common
.DevicePowerState
= PowerDeviceD0
;
864 if (!RtlCreateUnicodeString(
865 &PdoDeviceExtension
->DeviceID
,
866 Device
->DeviceID
.Buffer
))
868 DPRINT("Insufficient resources\n");
872 DPRINT("DeviceID: %wZ PDO %p\n",
873 &PdoDeviceExtension
->DeviceID
,
876 if (!RtlCreateUnicodeString(
877 &PdoDeviceExtension
->InstanceID
,
878 Device
->InstanceID
.Buffer
))
880 DPRINT("Insufficient resources\n");
884 DPRINT("InstanceID: %wZ PDO %p\n",
885 &PdoDeviceExtension
->InstanceID
,
888 if (Device
->ResourceRequirementsList
!= NULL
)
890 PdoDeviceExtension
->ResourceRequirementsList
= ExAllocatePoolWithTag(
892 Device
->ResourceRequirementsList
->ListSize
,
894 if (PdoDeviceExtension
->ResourceRequirementsList
)
897 PdoDeviceExtension
->ResourceRequirementsList
,
898 Device
->ResourceRequirementsList
,
899 Device
->ResourceRequirementsList
->ListSize
);
904 DPRINT("ExAllocatePoolWithTag() failed\n");
908 DPRINT("ResourceRequirementsList: %p PDO %p\n",
909 PdoDeviceExtension
->ResourceRequirementsList
,
913 /* Reference the physical device object. The PnP manager
914 will dereference it again when it is no longer needed */
915 ObReferenceObject(Device
->Pdo
);
917 Relations
->Objects
[i
] = Device
->Pdo
;
922 if (NT_SUCCESS(Status
))
924 Irp
->IoStatus
.Information
= (ULONG_PTR
)Relations
;
928 Irp
->IoStatus
.Information
= 0;
936 PnpRootQueryDeviceRelations(
937 IN PDEVICE_OBJECT DeviceObject
,
939 IN PIO_STACK_LOCATION IrpSp
)
945 switch (IrpSp
->Parameters
.QueryDeviceRelations
.Type
) {
947 Status
= PnpRootQueryBusRelations(DeviceObject
, Irp
, IrpSp
);
951 Status
= STATUS_NOT_IMPLEMENTED
;
959 * FUNCTION: Handle Plug and Play IRPs for the root bus device object
961 * DeviceObject = Pointer to functional device object of the root bus driver
962 * Irp = Pointer to IRP that should be handled
968 PnpRootFdoPnpControl(
969 IN PDEVICE_OBJECT DeviceObject
,
972 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
973 PIO_STACK_LOCATION IrpSp
;
978 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
980 Status
= Irp
->IoStatus
.Status
;
982 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
984 switch (IrpSp
->MinorFunction
) {
985 case IRP_MN_QUERY_DEVICE_RELATIONS
:
986 Status
= PnpRootQueryDeviceRelations(DeviceObject
, Irp
, IrpSp
);
989 case IRP_MN_START_DEVICE
:
990 DeviceExtension
->State
= dsStarted
;
991 Status
= STATUS_SUCCESS
;
994 case IRP_MN_STOP_DEVICE
:
995 /* Root device cannot be stopped */
996 Status
= STATUS_UNSUCCESSFUL
;
1000 DPRINT("Unknown IOCTL 0x%X\n", IrpSp
->MinorFunction
);
1001 Status
= STATUS_NOT_IMPLEMENTED
;
1005 if (Status
!= STATUS_PENDING
) {
1006 Irp
->IoStatus
.Status
= Status
;
1007 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1010 DPRINT("Leaving. Status 0x%X\n", Status
);
1017 * FUNCTION: Handle power management IRPs for the root bus device object
1019 * DeviceObject = Pointer to functional device object of the root bus driver
1020 * Irp = Pointer to IRP that should be handled
1026 PnpRootFdoPowerControl(
1027 IN PDEVICE_OBJECT DeviceObject
,
1030 PIO_STACK_LOCATION IrpSp
;
1035 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1037 switch (IrpSp
->MinorFunction
) {
1039 DPRINT("Unknown IOCTL 0x%X\n", IrpSp
->MinorFunction
);
1040 Status
= STATUS_NOT_IMPLEMENTED
;
1044 if (Status
!= STATUS_PENDING
) {
1045 Irp
->IoStatus
.Status
= Status
;
1046 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1049 DPRINT("Leaving. Status 0x%X\n", Status
);
1056 * FUNCTION: Handle Plug and Play IRPs
1058 * DeviceObject = Pointer to PDO or FDO
1059 * Irp = Pointer to IRP that should be handled
1066 IN PDEVICE_OBJECT DeviceObject
,
1069 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension
;
1072 DeviceExtension
= (PPNPROOT_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1074 DPRINT("DeviceObject 0x%p DeviceExtension 0x%p IsFDO %d\n",
1077 DeviceExtension
->IsFDO
);
1079 if (DeviceExtension
->IsFDO
) {
1080 Status
= PnpRootFdoPnpControl(DeviceObject
, Irp
);
1082 Status
= PnpRootPdoPnpControl(DeviceObject
, Irp
);
1090 * FUNCTION: Handle power management IRPs
1092 * DeviceObject = Pointer to PDO or FDO
1093 * Irp = Pointer to IRP that should be handled
1099 PnpRootPowerControl(
1100 IN PDEVICE_OBJECT DeviceObject
,
1103 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension
;
1106 DeviceExtension
= (PPNPROOT_COMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1108 if (DeviceExtension
->IsFDO
) {
1109 Status
= PnpRootFdoPowerControl(DeviceObject
, Irp
);
1111 Status
= PnpRootPdoPowerControl(DeviceObject
, Irp
);
1121 IN PDRIVER_OBJECT DriverObject
,
1122 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1124 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension
;
1129 Status
= IoCreateDevice(
1131 sizeof(PNPROOT_FDO_DEVICE_EXTENSION
),
1133 FILE_DEVICE_BUS_EXTENDER
,
1134 FILE_DEVICE_SECURE_OPEN
,
1136 &PnpRootDeviceObject
);
1137 if (!NT_SUCCESS(Status
)) {
1138 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1141 DeviceExtension
= (PPNPROOT_FDO_DEVICE_EXTENSION
)PnpRootDeviceObject
->DeviceExtension
;
1143 RtlZeroMemory(DeviceExtension
, sizeof(PNPROOT_FDO_DEVICE_EXTENSION
));
1145 DeviceExtension
->Common
.IsFDO
= TRUE
;
1147 DeviceExtension
->State
= dsStopped
;
1149 DeviceExtension
->Ldo
= IoAttachDeviceToDeviceStack(
1150 PnpRootDeviceObject
,
1151 PhysicalDeviceObject
);
1153 if (!PnpRootDeviceObject
) {
1154 CPRINT("PnpRootDeviceObject 0x%p\n", PnpRootDeviceObject
);
1155 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1158 if (!PhysicalDeviceObject
) {
1159 CPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject
);
1160 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
1163 InitializeListHead(&DeviceExtension
->DeviceListHead
);
1165 DeviceExtension
->DeviceListCount
= 0;
1167 KeInitializeSpinLock(&DeviceExtension
->DeviceListLock
);
1169 PnpRootDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1171 //PnpRootDeviceObject->Flags |= DO_POWER_PAGABLE;
1173 DPRINT("Done AddDevice()\n");
1175 return STATUS_SUCCESS
;
1182 IN PDRIVER_OBJECT DriverObject
,
1183 IN PUNICODE_STRING RegistryPath
)
1187 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = (PDRIVER_DISPATCH
) PnpRootPnpControl
;
1188 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = (PDRIVER_DISPATCH
) PnpRootPowerControl
;
1189 DriverObject
->DriverExtension
->AddDevice
= PnpRootAddDevice
;
1191 return STATUS_SUCCESS
;