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
)
63 PiInitGroupOrderTableCount
= 0;
64 PiInitGroupOrderTable
= (PVOID
)0xBABEB00B;
65 return STATUS_SUCCESS
;
68 /* Open the registry key */
69 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
73 if (NT_SUCCESS(Status
))
76 Status
= IopGetRegistryValue(KeyHandle
, L
"List", &KeyValueInformation
);
79 /* Make sure we got it */
80 if (NT_SUCCESS(Status
))
82 /* Make sure it's valid */
83 if ((KeyValueInformation
->Type
== REG_MULTI_SZ
) &&
84 (KeyValueInformation
->DataLength
))
86 /* Convert it to unicode strings */
87 Status
= PnpRegMultiSzToUnicodeStrings(KeyValueInformation
,
91 /* Cache it for later */
92 PiInitGroupOrderTable
= GroupTable
;
93 PiInitGroupOrderTableCount
= (USHORT
)Count
;
98 Status
= STATUS_UNSUCCESSFUL
;
101 /* Free the information */
102 ExFreePool(KeyValueInformation
);
112 PpInitGetGroupOrderIndex(IN HANDLE ServiceHandle
)
115 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
;
118 UNICODE_STRING Group
;
121 /* Make sure we have a cache */
122 if (!PiInitGroupOrderTable
) return -1;
124 /* If we don't have a handle, the rest is easy -- return the count */
125 if (!ServiceHandle
) return PiInitGroupOrderTableCount
+ 1;
127 /* Otherwise, get the group value */
128 Status
= IopGetRegistryValue(ServiceHandle
, L
"Group", &KeyValueInformation
);
129 if (!NT_SUCCESS(Status
)) return PiInitGroupOrderTableCount
;
131 /* Make sure we have a valid string */
132 ASSERT(KeyValueInformation
->Type
== REG_SZ
);
133 ASSERT(KeyValueInformation
->DataLength
);
135 /* Convert to unicode string */
136 Buffer
= (PVOID
)((ULONG_PTR
)KeyValueInformation
+ KeyValueInformation
->DataOffset
);
137 PnpRegSzToString(Buffer
, KeyValueInformation
->DataLength
, &Group
.Length
);
138 Group
.MaximumLength
= (USHORT
)KeyValueInformation
->DataLength
;
139 Group
.Buffer
= Buffer
;
141 /* Loop the groups */
142 for (i
= 0; i
< PiInitGroupOrderTableCount
; i
++)
144 /* Try to find a match */
145 if (RtlEqualUnicodeString(&Group
, &PiInitGroupOrderTable
[i
], TRUE
)) break;
149 ExFreePool(KeyValueInformation
);
155 PipGetDriverTagPriority(IN HANDLE ServiceHandle
)
158 HANDLE KeyHandle
= NULL
;
159 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
= NULL
;
160 PKEY_VALUE_FULL_INFORMATION KeyValueInformationTag
;
161 PKEY_VALUE_FULL_INFORMATION KeyValueInformationGroupOrderList
;
163 UNICODE_STRING Group
;
165 ULONG Count
, Tag
= 0;
167 UNICODE_STRING GroupString
=
168 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet"
169 L
"\\Control\\ServiceGroupOrder");
172 Status
= IopOpenRegistryKeyEx(&KeyHandle
, NULL
, &GroupString
, KEY_READ
);
173 if (!NT_SUCCESS(Status
)) goto Quickie
;
176 Status
= IopGetRegistryValue(ServiceHandle
, L
"Group", &KeyValueInformation
);
177 if (!NT_SUCCESS(Status
)) goto Quickie
;
179 /* Make sure we have a group */
180 if ((KeyValueInformation
->Type
== REG_SZ
) &&
181 (KeyValueInformation
->DataLength
))
183 /* Convert to unicode string */
184 Buffer
= (PVOID
)((ULONG_PTR
)KeyValueInformation
+ KeyValueInformation
->DataOffset
);
185 PnpRegSzToString(Buffer
, KeyValueInformation
->DataLength
, &Group
.Length
);
186 Group
.MaximumLength
= (USHORT
)KeyValueInformation
->DataLength
;
187 Group
.Buffer
= Buffer
;
190 /* Now read the tag */
191 Status
= IopGetRegistryValue(ServiceHandle
, L
"Tag", &KeyValueInformationTag
);
192 if (!NT_SUCCESS(Status
)) goto Quickie
;
194 /* Make sure we have a tag */
195 if ((KeyValueInformationTag
->Type
== REG_DWORD
) &&
196 (KeyValueInformationTag
->DataLength
))
199 Tag
= *(PULONG
)((ULONG_PTR
)KeyValueInformationTag
+
200 KeyValueInformationTag
->DataOffset
);
203 /* We can get rid of this now */
204 ExFreePool(KeyValueInformationTag
);
206 /* Now let's read the group's tag order */
207 Status
= IopGetRegistryValue(KeyHandle
,
209 &KeyValueInformationGroupOrderList
);
211 /* We can get rid of this now */
213 if (KeyValueInformation
) ExFreePool(KeyValueInformation
);
214 if (KeyHandle
) NtClose(KeyHandle
);
215 if (!NT_SUCCESS(Status
)) return -1;
217 /* We're on the success path -- validate the tag order*/
218 if ((KeyValueInformationGroupOrderList
->Type
== REG_BINARY
) &&
219 (KeyValueInformationGroupOrderList
->DataLength
))
221 /* Get the order array */
222 GroupOrder
= (PULONG
)((ULONG_PTR
)KeyValueInformationGroupOrderList
+
223 KeyValueInformationGroupOrderList
->DataOffset
);
227 ASSERT(((Count
+ 1) * sizeof(ULONG
)) <=
228 KeyValueInformationGroupOrderList
->DataLength
);
230 /* Now loop each tag */
232 for (i
= 1; i
<= Count
; i
++)
234 /* If we found it, we're out */
235 if (Tag
== *GroupOrder
) break;
237 /* Try the next one */
242 /* Last buffer to free */
243 ExFreePool(KeyValueInformationGroupOrderList
);
249 PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode
,
250 IN BOOLEAN LoadDriver
,
251 IN PDRIVER_OBJECT DriverObject
)
254 HANDLE EnumRootKey
, SubKey
, ControlKey
, ClassKey
, PropertiesKey
;
255 UNICODE_STRING ClassGuid
, Properties
;
256 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
257 UNICODE_STRING ControlClass
=
258 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class");
259 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
= NULL
;
262 /* Open enumeration root key */
263 Status
= IopOpenRegistryKeyEx(&EnumRootKey
,
267 if (!NT_SUCCESS(Status
))
269 DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status
);
273 /* Open instance subkey */
274 Status
= IopOpenRegistryKeyEx(&SubKey
,
276 &DeviceNode
->InstancePath
,
278 ZwClose(EnumRootKey
);
279 if (!NT_SUCCESS(Status
))
281 DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status
);
286 Status
= IopGetRegistryValue(SubKey
,
287 REGSTR_VAL_CLASSGUID
,
288 &KeyValueInformation
);
289 if (NT_SUCCESS(Status
))
291 /* Convert to unicode string */
292 Buffer
= (PVOID
)((ULONG_PTR
)KeyValueInformation
+ KeyValueInformation
->DataOffset
);
293 PnpRegSzToString(Buffer
, KeyValueInformation
->DataLength
, &ClassGuid
.Length
);
294 ClassGuid
.MaximumLength
= (USHORT
)KeyValueInformation
->DataLength
;
295 ClassGuid
.Buffer
= Buffer
;
298 Status
= IopOpenRegistryKeyEx(&ControlKey
,
302 if (!NT_SUCCESS(Status
))
305 DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status
);
310 /* Open the class key */
311 Status
= IopOpenRegistryKeyEx(&ClassKey
,
316 if (!NT_SUCCESS(Status
))
319 DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status
);
324 /* Check if we made it till here */
327 /* Get the device properties */
328 RtlInitUnicodeString(&Properties
, REGSTR_KEY_DEVICE_PROPERTIES
);
329 Status
= IopOpenRegistryKeyEx(&PropertiesKey
,
334 if (!NT_SUCCESS(Status
))
337 DPRINT("IopOpenRegistryKeyEx() failed with Status %08X\n", Status
);
338 PropertiesKey
= NULL
;
342 ZwClose(PropertiesKey
);
346 /* Free the registry data */
347 ExFreePool(KeyValueInformation
);
350 /* Do ReactOS-style setup */
351 Status
= IopAttachFilterDrivers(DeviceNode
, TRUE
);
352 if (!NT_SUCCESS(Status
))
354 IopRemoveDevice(DeviceNode
);
357 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
358 if (NT_SUCCESS(Status
))
360 Status
= IopAttachFilterDrivers(DeviceNode
, FALSE
);
361 if (!NT_SUCCESS(Status
))
363 IopRemoveDevice(DeviceNode
);
367 Status
= IopStartDevice(DeviceNode
);
377 IopInitializePlugPlayServices(VOID
)
381 HANDLE KeyHandle
, EnumHandle
, ParentHandle
, TreeHandle
, ControlHandle
;
382 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
383 UNICODE_STRING PnpManagerDriverName
= RTL_CONSTANT_STRING(DRIVER_ROOT_NAME L
"PnpManager");
386 /* Initialize locks and such */
387 KeInitializeSpinLock(&IopDeviceTreeLock
);
388 KeInitializeSpinLock(&IopDeviceRelationsSpinLock
);
389 InitializeListHead(&IopDeviceRelationsRequestList
);
391 /* Get the default interface */
392 PnpDefaultInterfaceType
= IopDetermineDefaultInterfaceType();
394 /* Initialize arbiters */
395 Status
= IopInitializeArbiters();
396 if (!NT_SUCCESS(Status
)) return Status
;
398 /* Setup the group cache */
399 Status
= PiInitCacheGroupInformation();
400 if (!NT_SUCCESS(Status
)) return Status
;
402 /* Open the current control set */
403 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
407 if (!NT_SUCCESS(Status
)) return Status
;
409 /* Create the control key */
410 RtlInitUnicodeString(&KeyName
, L
"Control");
411 Status
= IopCreateRegistryKeyEx(&ControlHandle
,
415 REG_OPTION_NON_VOLATILE
,
417 if (!NT_SUCCESS(Status
)) return Status
;
419 /* Check if it's a new key */
420 if (Disposition
== REG_CREATED_NEW_KEY
)
422 HANDLE DeviceClassesHandle
;
424 /* Create the device classes key */
425 RtlInitUnicodeString(&KeyName
, L
"DeviceClasses");
426 Status
= IopCreateRegistryKeyEx(&DeviceClassesHandle
,
430 REG_OPTION_NON_VOLATILE
,
432 if (!NT_SUCCESS(Status
)) return Status
;
434 ZwClose(DeviceClassesHandle
);
437 ZwClose(ControlHandle
);
439 /* Create the enum key */
440 RtlInitUnicodeString(&KeyName
, REGSTR_KEY_ENUM
);
441 Status
= IopCreateRegistryKeyEx(&EnumHandle
,
445 REG_OPTION_NON_VOLATILE
,
447 if (!NT_SUCCESS(Status
)) return Status
;
449 /* Check if it's a new key */
450 if (Disposition
== REG_CREATED_NEW_KEY
)
453 DPRINT1("Need to build DACL\n");
456 /* Create the root key */
457 ParentHandle
= EnumHandle
;
458 RtlInitUnicodeString(&KeyName
, REGSTR_KEY_ROOTENUM
);
459 Status
= IopCreateRegistryKeyEx(&EnumHandle
,
463 REG_OPTION_NON_VOLATILE
,
465 NtClose(ParentHandle
);
466 if (!NT_SUCCESS(Status
)) return Status
;
469 /* Open the root key now */
470 RtlInitUnicodeString(&KeyName
, L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
471 Status
= IopOpenRegistryKeyEx(&EnumHandle
,
475 if (NT_SUCCESS(Status
))
477 /* Create the root dev node */
478 RtlInitUnicodeString(&KeyName
, REGSTR_VAL_ROOT_DEVNODE
);
479 Status
= IopCreateRegistryKeyEx(&TreeHandle
,
483 REG_OPTION_NON_VOLATILE
,
486 if (NT_SUCCESS(Status
)) NtClose(TreeHandle
);
489 /* Create the root driver */
490 Status
= IoCreateDriver(&PnpManagerDriverName
, PnpRootDriverEntry
);
491 if (!NT_SUCCESS(Status
))
493 DPRINT1("IoCreateDriverObject() failed\n");
494 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
497 /* Create the root PDO */
498 Status
= IoCreateDevice(IopRootDriverObject
,
499 sizeof(IOPNP_DEVICE_EXTENSION
),
501 FILE_DEVICE_CONTROLLER
,
505 if (!NT_SUCCESS(Status
))
507 DPRINT1("IoCreateDevice() failed\n");
508 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
511 /* This is a bus enumerated device */
512 Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
514 /* Create the root device node */
515 IopRootDeviceNode
= PipAllocateDeviceNode(Pdo
);
518 IopRootDeviceNode
->Flags
|= DNF_STARTED
+ DNF_PROCESSED
+ DNF_ENUMERATED
+
519 DNF_MADEUP
+ DNF_NO_RESOURCE_REQUIRED
+
522 /* Create instance path */
523 RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
524 REGSTR_VAL_ROOT_DEVNODE
);
526 /* Call the add device routine */
527 IopRootDriverObject
->DriverExtension
->AddDevice(IopRootDriverObject
,
528 IopRootDeviceNode
->PhysicalDeviceObject
);
530 /* Initialize PnP-Event notification support */
531 Status
= IopInitPlugPlayEvents();
532 if (!NT_SUCCESS(Status
)) return Status
;
534 /* Report the device to the user-mode pnp manager */
535 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
536 &IopRootDeviceNode
->InstancePath
);
538 /* Initialize the Bus Type GUID List */
539 PnpBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
540 RtlZeroMemory(PnpBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
541 ExInitializeFastMutex(&PnpBusTypeGuidList
->Lock
);
543 /* Launch the firmware mapper */
544 Status
= IopUpdateRootKey();
545 if (!NT_SUCCESS(Status
)) return Status
;
547 /* Close the handle to the control set */
551 return STATUS_SUCCESS
;