2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/io/pnpmgr/pnpinit.c
5 * PURPOSE: PnP Initialization Code
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 typedef struct _IOPNP_DEVICE_EXTENSION
19 PWCHAR CompatibleIdList
;
20 ULONG CompatibleIdListSize
;
21 } IOPNP_DEVICE_EXTENSION
, *PIOPNP_DEVICE_EXTENSION
;
23 PUNICODE_STRING PiInitGroupOrderTable
;
24 USHORT PiInitGroupOrderTableCount
;
25 INTERFACE_TYPE PnpDefaultInterfaceType
;
27 /* FUNCTIONS ******************************************************************/
31 IopDetermineDefaultInterfaceType(VOID
)
33 /* FIXME: ReactOS doesn't support MicroChannel yet */
39 IopInitializeArbiters(VOID
)
42 return STATUS_SUCCESS
;
48 PiInitCacheGroupInformation(VOID
)
52 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
;
53 PUNICODE_STRING GroupTable
;
55 UNICODE_STRING GroupString
=
56 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet"
57 L
"\\Control\\ServiceGroupOrder");
59 /* ReactOS HACK for SETUPLDR */
60 if (KeLoaderBlock
->SetupLdrBlock
)
62 DPRINT1("WARNING!! In PiInitCacheGroupInformation, using ReactOS HACK for SETUPLDR!!\n");
65 PiInitGroupOrderTableCount
= 0;
66 PiInitGroupOrderTable
= (PVOID
)0xBABEB00B;
67 return STATUS_SUCCESS
;
70 /* Open the registry key */
71 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
75 if (NT_SUCCESS(Status
))
78 Status
= IopGetRegistryValue(KeyHandle
, L
"List", &KeyValueInformation
);
81 /* Make sure we got it */
82 if (NT_SUCCESS(Status
))
84 /* Make sure it's valid */
85 if ((KeyValueInformation
->Type
== REG_MULTI_SZ
) &&
86 (KeyValueInformation
->DataLength
))
88 /* Convert it to unicode strings */
89 Status
= PnpRegMultiSzToUnicodeStrings(KeyValueInformation
,
93 /* Cache it for later */
94 PiInitGroupOrderTable
= GroupTable
;
95 PiInitGroupOrderTableCount
= (USHORT
)Count
;
100 Status
= STATUS_UNSUCCESSFUL
;
103 /* Free the information */
104 ExFreePool(KeyValueInformation
);
114 PpInitGetGroupOrderIndex(IN HANDLE ServiceHandle
)
117 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
;
120 UNICODE_STRING Group
;
123 /* Make sure we have a cache */
124 if (!PiInitGroupOrderTable
) return -1;
126 /* If we don't have a handle, the rest is easy -- return the count */
127 if (!ServiceHandle
) return PiInitGroupOrderTableCount
+ 1;
129 /* Otherwise, get the group value */
130 Status
= IopGetRegistryValue(ServiceHandle
, L
"Group", &KeyValueInformation
);
131 if (!NT_SUCCESS(Status
)) return PiInitGroupOrderTableCount
;
133 /* Make sure we have a valid string */
134 ASSERT(KeyValueInformation
->Type
== REG_SZ
);
135 ASSERT(KeyValueInformation
->DataLength
);
137 /* Convert to unicode string */
138 Buffer
= (PVOID
)((ULONG_PTR
)KeyValueInformation
+ KeyValueInformation
->DataOffset
);
139 PnpRegSzToString(Buffer
, KeyValueInformation
->DataLength
, &Group
.Length
);
140 Group
.MaximumLength
= (USHORT
)KeyValueInformation
->DataLength
;
141 Group
.Buffer
= Buffer
;
143 /* Loop the groups */
144 for (i
= 0; i
< PiInitGroupOrderTableCount
; i
++)
146 /* Try to find a match */
147 if (RtlEqualUnicodeString(&Group
, &PiInitGroupOrderTable
[i
], TRUE
)) break;
151 ExFreePool(KeyValueInformation
);
157 PipGetDriverTagPriority(IN HANDLE ServiceHandle
)
160 HANDLE KeyHandle
= NULL
;
161 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
= NULL
;
162 PKEY_VALUE_FULL_INFORMATION KeyValueInformationTag
;
163 PKEY_VALUE_FULL_INFORMATION KeyValueInformationGroupOrderList
;
165 UNICODE_STRING Group
;
167 ULONG Count
, Tag
= 0;
169 UNICODE_STRING GroupString
=
170 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet"
171 L
"\\Control\\ServiceGroupOrder");
174 Status
= IopOpenRegistryKeyEx(&KeyHandle
, NULL
, &GroupString
, KEY_READ
);
175 if (!NT_SUCCESS(Status
)) goto Quickie
;
178 Status
= IopGetRegistryValue(ServiceHandle
, L
"Group", &KeyValueInformation
);
179 if (!NT_SUCCESS(Status
)) goto Quickie
;
181 /* Make sure we have a group */
182 if ((KeyValueInformation
->Type
== REG_SZ
) &&
183 (KeyValueInformation
->DataLength
))
185 /* Convert to unicode string */
186 Buffer
= (PVOID
)((ULONG_PTR
)KeyValueInformation
+ KeyValueInformation
->DataOffset
);
187 PnpRegSzToString(Buffer
, KeyValueInformation
->DataLength
, &Group
.Length
);
188 Group
.MaximumLength
= (USHORT
)KeyValueInformation
->DataLength
;
189 Group
.Buffer
= Buffer
;
192 /* Now read the tag */
193 Status
= IopGetRegistryValue(ServiceHandle
, L
"Tag", &KeyValueInformationTag
);
194 if (!NT_SUCCESS(Status
)) goto Quickie
;
196 /* Make sure we have a tag */
197 if ((KeyValueInformationTag
->Type
== REG_DWORD
) &&
198 (KeyValueInformationTag
->DataLength
))
201 Tag
= *(PULONG
)((ULONG_PTR
)KeyValueInformationTag
+
202 KeyValueInformationTag
->DataOffset
);
205 /* We can get rid of this now */
206 ExFreePool(KeyValueInformationTag
);
208 /* Now let's read the group's tag order */
209 Status
= IopGetRegistryValue(KeyHandle
,
211 &KeyValueInformationGroupOrderList
);
213 /* We can get rid of this now */
215 if (KeyValueInformation
) ExFreePool(KeyValueInformation
);
216 if (KeyHandle
) NtClose(KeyHandle
);
217 if (!NT_SUCCESS(Status
)) return -1;
219 /* We're on the success path -- validate the tag order*/
220 if ((KeyValueInformationGroupOrderList
->Type
== REG_BINARY
) &&
221 (KeyValueInformationGroupOrderList
->DataLength
))
223 /* Get the order array */
224 GroupOrder
= (PULONG
)((ULONG_PTR
)KeyValueInformationGroupOrderList
+
225 KeyValueInformationGroupOrderList
->DataOffset
);
229 ASSERT(((Count
+ 1) * sizeof(ULONG
)) <=
230 KeyValueInformationGroupOrderList
->DataLength
);
232 /* Now loop each tag */
234 for (i
= 1; i
<= Count
; i
++)
236 /* If we found it, we're out */
237 if (Tag
== *GroupOrder
) break;
239 /* Try the next one */
244 /* Last buffer to free */
245 ExFreePool(KeyValueInformationGroupOrderList
);
251 PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode
,
252 IN BOOLEAN LoadDriver
,
253 IN PDRIVER_OBJECT DriverObject
)
256 HANDLE EnumRootKey
, SubKey
, ControlKey
, ClassKey
, PropertiesKey
;
257 UNICODE_STRING ClassGuid
, Properties
;
258 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
259 UNICODE_STRING ControlClass
=
260 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class");
261 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
= NULL
;
264 /* Open enumeration root key */
265 Status
= IopOpenRegistryKeyEx(&EnumRootKey
,
269 if (!NT_SUCCESS(Status
))
271 DPRINT1("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n",
276 /* Open instance subkey */
277 Status
= IopOpenRegistryKeyEx(&SubKey
,
279 &DeviceNode
->InstancePath
,
281 ZwClose(EnumRootKey
);
282 if (!NT_SUCCESS(Status
))
284 DPRINT1("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n",
285 &DeviceNode
->InstancePath
, Status
);
290 Status
= IopGetRegistryValue(SubKey
,
291 REGSTR_VAL_CLASSGUID
,
292 &KeyValueInformation
);
293 if (NT_SUCCESS(Status
))
295 /* Convert to unicode string */
296 Buffer
= (PVOID
)((ULONG_PTR
)KeyValueInformation
+ KeyValueInformation
->DataOffset
);
297 PnpRegSzToString(Buffer
, KeyValueInformation
->DataLength
, &ClassGuid
.Length
);
298 ClassGuid
.MaximumLength
= (USHORT
)KeyValueInformation
->DataLength
;
299 ClassGuid
.Buffer
= Buffer
;
302 Status
= IopOpenRegistryKeyEx(&ControlKey
,
306 if (!NT_SUCCESS(Status
))
309 DPRINT1("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n",
310 &ControlClass
, Status
);
315 /* Open the class key */
316 Status
= IopOpenRegistryKeyEx(&ClassKey
,
321 if (!NT_SUCCESS(Status
))
324 DPRINT1("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n",
330 /* Check if we made it till here */
333 /* Get the device properties */
334 RtlInitUnicodeString(&Properties
, REGSTR_KEY_DEVICE_PROPERTIES
);
335 Status
= IopOpenRegistryKeyEx(&PropertiesKey
,
340 if (!NT_SUCCESS(Status
))
343 DPRINT("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n",
344 &Properties
, Status
);
345 PropertiesKey
= NULL
;
349 ZwClose(PropertiesKey
);
353 /* Free the registry data */
354 ExFreePool(KeyValueInformation
);
357 /* Do ReactOS-style setup */
358 Status
= IopAttachFilterDrivers(DeviceNode
, SubKey
, TRUE
);
359 if (!NT_SUCCESS(Status
))
361 IopRemoveDevice(DeviceNode
);
364 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
365 if (NT_SUCCESS(Status
))
367 Status
= IopAttachFilterDrivers(DeviceNode
, SubKey
, FALSE
);
368 if (!NT_SUCCESS(Status
))
370 IopRemoveDevice(DeviceNode
);
374 Status
= IopStartDevice(DeviceNode
);
378 /* Close key and return status */
386 IopInitializePlugPlayServices(VOID
)
390 HANDLE KeyHandle
, EnumHandle
, ParentHandle
, TreeHandle
, ControlHandle
;
391 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
392 UNICODE_STRING PnpManagerDriverName
= RTL_CONSTANT_STRING(DRIVER_ROOT_NAME L
"PnpManager");
395 /* Initialize locks and such */
396 KeInitializeSpinLock(&IopDeviceTreeLock
);
397 KeInitializeSpinLock(&IopDeviceRelationsSpinLock
);
398 InitializeListHead(&IopDeviceRelationsRequestList
);
400 /* Get the default interface */
401 PnpDefaultInterfaceType
= IopDetermineDefaultInterfaceType();
403 /* Initialize arbiters */
404 Status
= IopInitializeArbiters();
405 if (!NT_SUCCESS(Status
)) return Status
;
407 /* Setup the group cache */
408 Status
= PiInitCacheGroupInformation();
409 if (!NT_SUCCESS(Status
)) return Status
;
411 /* Open the current control set */
412 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
416 if (!NT_SUCCESS(Status
)) return Status
;
418 /* Create the control key */
419 RtlInitUnicodeString(&KeyName
, L
"Control");
420 Status
= IopCreateRegistryKeyEx(&ControlHandle
,
424 REG_OPTION_NON_VOLATILE
,
426 if (!NT_SUCCESS(Status
)) return Status
;
428 /* Check if it's a new key */
429 if (Disposition
== REG_CREATED_NEW_KEY
)
431 HANDLE DeviceClassesHandle
;
433 /* Create the device classes key */
434 RtlInitUnicodeString(&KeyName
, L
"DeviceClasses");
435 Status
= IopCreateRegistryKeyEx(&DeviceClassesHandle
,
439 REG_OPTION_NON_VOLATILE
,
441 if (!NT_SUCCESS(Status
)) return Status
;
443 ZwClose(DeviceClassesHandle
);
446 ZwClose(ControlHandle
);
448 /* Create the enum key */
449 RtlInitUnicodeString(&KeyName
, REGSTR_KEY_ENUM
);
450 Status
= IopCreateRegistryKeyEx(&EnumHandle
,
454 REG_OPTION_NON_VOLATILE
,
456 if (!NT_SUCCESS(Status
)) return Status
;
458 /* Check if it's a new key */
459 if (Disposition
== REG_CREATED_NEW_KEY
)
464 /* Create the root key */
465 ParentHandle
= EnumHandle
;
466 RtlInitUnicodeString(&KeyName
, REGSTR_KEY_ROOTENUM
);
467 Status
= IopCreateRegistryKeyEx(&EnumHandle
,
471 REG_OPTION_NON_VOLATILE
,
473 NtClose(ParentHandle
);
474 if (!NT_SUCCESS(Status
)) return Status
;
477 /* Open the root key now */
478 RtlInitUnicodeString(&KeyName
, L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
479 Status
= IopOpenRegistryKeyEx(&EnumHandle
,
483 if (NT_SUCCESS(Status
))
485 /* Create the root dev node */
486 RtlInitUnicodeString(&KeyName
, REGSTR_VAL_ROOT_DEVNODE
);
487 Status
= IopCreateRegistryKeyEx(&TreeHandle
,
491 REG_OPTION_NON_VOLATILE
,
494 if (NT_SUCCESS(Status
)) NtClose(TreeHandle
);
497 /* Create the root driver */
498 Status
= IoCreateDriver(&PnpManagerDriverName
, PnpRootDriverEntry
);
499 if (!NT_SUCCESS(Status
))
501 DPRINT1("IoCreateDriverObject() failed\n");
502 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
505 /* Create the root PDO */
506 Status
= IoCreateDevice(IopRootDriverObject
,
507 sizeof(IOPNP_DEVICE_EXTENSION
),
509 FILE_DEVICE_CONTROLLER
,
513 if (!NT_SUCCESS(Status
))
515 DPRINT1("IoCreateDevice() failed\n");
516 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
519 /* This is a bus enumerated device */
520 Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
522 /* Create the root device node */
523 IopRootDeviceNode
= PipAllocateDeviceNode(Pdo
);
526 IopRootDeviceNode
->Flags
|= DNF_STARTED
+ DNF_PROCESSED
+ DNF_ENUMERATED
+
527 DNF_MADEUP
+ DNF_NO_RESOURCE_REQUIRED
+
530 /* Create instance path */
531 RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
532 REGSTR_VAL_ROOT_DEVNODE
);
534 /* Call the add device routine */
535 IopRootDriverObject
->DriverExtension
->AddDevice(IopRootDriverObject
,
536 IopRootDeviceNode
->PhysicalDeviceObject
);
538 /* Initialize PnP-Event notification support */
539 Status
= IopInitPlugPlayEvents();
540 if (!NT_SUCCESS(Status
)) return Status
;
542 /* Report the device to the user-mode pnp manager */
543 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
544 &IopRootDeviceNode
->InstancePath
);
546 /* Initialize the Bus Type GUID List */
547 PnpBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
548 RtlZeroMemory(PnpBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
549 ExInitializeFastMutex(&PnpBusTypeGuidList
->Lock
);
551 /* Launch the firmware mapper */
552 Status
= IopUpdateRootKey();
553 if (!NT_SUCCESS(Status
)) return Status
;
555 /* Close the handle to the control set */
559 return STATUS_SUCCESS
;