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 ULONG 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
;
47 PiInitCacheGroupInformation(VOID
)
51 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
;
52 PUNICODE_STRING GroupTable
;
54 UNICODE_STRING GroupString
=
55 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet"
56 L
"\\Control\\ServiceGroupOrder");
58 /* ReactOS HACK for SETUPLDR */
59 if (KeLoaderBlock
->SetupLdrBlock
)
62 PiInitGroupOrderTableCount
= 0;
63 PiInitGroupOrderTable
= (PVOID
)0xBABEB00B;
64 return STATUS_SUCCESS
;
67 /* Open the registry key */
68 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
72 if (NT_SUCCESS(Status
))
75 Status
= IopGetRegistryValue(KeyHandle
, L
"List", &KeyValueInformation
);
78 /* Make sure we got it */
79 if (NT_SUCCESS(Status
))
81 /* Make sure it's valid */
82 if ((KeyValueInformation
->Type
== REG_MULTI_SZ
) &&
83 (KeyValueInformation
->DataLength
))
85 /* Convert it to unicode strings */
86 Status
= PnpRegMultiSzToUnicodeStrings(KeyValueInformation
,
90 /* Cache it for later */
91 PiInitGroupOrderTable
= GroupTable
;
92 PiInitGroupOrderTableCount
= Count
;
97 Status
= STATUS_UNSUCCESSFUL
;
100 /* Free the information */
101 ExFreePool(KeyValueInformation
);
111 PpInitGetGroupOrderIndex(IN HANDLE ServiceHandle
)
114 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
;
117 UNICODE_STRING Group
;
120 /* Make sure we have a cache */
121 if (!PiInitGroupOrderTable
) return -1;
123 /* If we don't have a handle, the rest is easy -- return the count */
124 if (!ServiceHandle
) return PiInitGroupOrderTableCount
+ 1;
126 /* Otherwise, get the group value */
127 Status
= IopGetRegistryValue(ServiceHandle
, L
"Group", &KeyValueInformation
);
128 if (!NT_SUCCESS(Status
)) return PiInitGroupOrderTableCount
;
130 /* Make sure we have a valid string */
131 ASSERT(KeyValueInformation
->Type
== REG_SZ
);
132 ASSERT(KeyValueInformation
->DataLength
);
134 /* Convert to unicode string */
135 Buffer
= (PVOID
)((ULONG_PTR
)KeyValueInformation
+ KeyValueInformation
->DataOffset
);
136 PnpRegSzToString(Buffer
, KeyValueInformation
->DataLength
, &Group
.Length
);
137 Group
.MaximumLength
= KeyValueInformation
->DataLength
;
138 Group
.Buffer
= Buffer
;
140 /* Loop the groups */
141 for (i
= 0; i
< PiInitGroupOrderTableCount
; i
++)
143 /* Try to find a match */
144 if (RtlEqualUnicodeString(&Group
, &PiInitGroupOrderTable
[i
], TRUE
)) break;
148 ExFreePool(KeyValueInformation
);
154 PipGetDriverTagPriority(IN HANDLE ServiceHandle
)
157 HANDLE KeyHandle
= NULL
;
158 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
= NULL
;
159 PKEY_VALUE_FULL_INFORMATION KeyValueInformationTag
;
160 PKEY_VALUE_FULL_INFORMATION KeyValueInformationGroupOrderList
;
162 UNICODE_STRING Group
;
164 ULONG i
= -1, Count
, Tag
= 0;
165 UNICODE_STRING GroupString
=
166 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet"
167 L
"\\Control\\ServiceGroupOrder");
170 Status
= IopOpenRegistryKeyEx(&KeyHandle
, NULL
, &GroupString
, KEY_READ
);
171 if (!NT_SUCCESS(Status
)) goto Quickie
;
174 Status
= IopGetRegistryValue(ServiceHandle
, L
"Group", &KeyValueInformation
);
175 if (!NT_SUCCESS(Status
)) goto Quickie
;
177 /* Make sure we have a group */
178 if ((KeyValueInformation
->Type
== REG_SZ
) &&
179 (KeyValueInformation
->DataLength
))
181 /* Convert to unicode string */
182 Buffer
= (PVOID
)((ULONG_PTR
)KeyValueInformation
+ KeyValueInformation
->DataOffset
);
183 PnpRegSzToString(Buffer
, KeyValueInformation
->DataLength
, &Group
.Length
);
184 Group
.MaximumLength
= KeyValueInformation
->DataLength
;
185 Group
.Buffer
= Buffer
;
188 /* Now read the tag */
189 Status
= IopGetRegistryValue(ServiceHandle
, L
"Tag", &KeyValueInformationTag
);
190 if (!NT_SUCCESS(Status
)) goto Quickie
;
192 /* Make sure we have a tag */
193 if ((KeyValueInformationTag
->Type
== REG_DWORD
) &&
194 (KeyValueInformationTag
->DataLength
))
197 Tag
= *(PULONG
)((ULONG_PTR
)KeyValueInformationTag
+
198 KeyValueInformationTag
->DataOffset
);
201 /* We can get rid of this now */
202 ExFreePool(KeyValueInformationTag
);
204 /* Now let's read the group's tag order */
205 Status
= IopGetRegistryValue(KeyHandle
,
207 &KeyValueInformationGroupOrderList
);
209 /* We can get rid of this now */
211 if (KeyValueInformation
) ExFreePool(KeyValueInformation
);
212 if (KeyHandle
) NtClose(KeyHandle
);
213 if (!NT_SUCCESS(Status
)) return -1;
215 /* We're on the success path -- validate the tag order*/
216 if ((KeyValueInformationGroupOrderList
->Type
== REG_BINARY
) &&
217 (KeyValueInformationGroupOrderList
->DataLength
))
219 /* Get the order array */
220 GroupOrder
= (PULONG
)((ULONG_PTR
)KeyValueInformationGroupOrderList
+
221 KeyValueInformationGroupOrderList
->DataOffset
);
225 ASSERT(((Count
+ 1) * sizeof(ULONG
)) <=
226 KeyValueInformationGroupOrderList
->DataLength
);
228 /* Now loop each tag */
230 for (i
= 1; i
<= Count
; i
++)
232 /* If we found it, we're out */
233 if (Tag
== *GroupOrder
) break;
235 /* Try the next one */
240 /* Last buffer to free */
241 ExFreePool(KeyValueInformationGroupOrderList
);
247 PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode
,
248 IN BOOLEAN LoadDriver
,
249 IN PDRIVER_OBJECT DriverObject
)
252 HANDLE EnumRootKey
, SubKey
, ControlKey
, ClassKey
, PropertiesKey
;
253 UNICODE_STRING ClassGuid
, Properties
;
254 UNICODE_STRING EnumRoot
= RTL_CONSTANT_STRING(ENUM_ROOT
);
255 UNICODE_STRING ControlClass
=
256 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class");
257 PKEY_VALUE_FULL_INFORMATION KeyValueInformation
= NULL
;
260 /* Open enumeration root key */
261 Status
= IopOpenRegistryKeyEx(&EnumRootKey
,
265 if (!NT_SUCCESS(Status
))
267 DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status
);
271 /* Open instance subkey */
272 Status
= IopOpenRegistryKeyEx(&SubKey
,
274 &DeviceNode
->InstancePath
,
276 if (!NT_SUCCESS(Status
))
278 DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status
);
279 ZwClose(EnumRootKey
);
284 Status
= IopGetRegistryValue(SubKey
,
285 REGSTR_VAL_CLASSGUID
,
286 &KeyValueInformation
);
287 if (NT_SUCCESS(Status
))
289 /* Convert to unicode string */
290 Buffer
= (PVOID
)((ULONG_PTR
)KeyValueInformation
+ KeyValueInformation
->DataOffset
);
291 PnpRegSzToString(Buffer
, KeyValueInformation
->DataLength
, &ClassGuid
.Length
);
292 ClassGuid
.MaximumLength
= KeyValueInformation
->DataLength
;
293 ClassGuid
.Buffer
= Buffer
;
296 Status
= IopOpenRegistryKeyEx(&ControlKey
,
300 if (!NT_SUCCESS(Status
))
303 DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status
);
308 /* Open the class key */
309 Status
= IopOpenRegistryKeyEx(&ClassKey
,
314 if (!NT_SUCCESS(Status
))
317 DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status
);
322 /* Check if we made it till here */
325 /* Get the device properties */
326 RtlInitUnicodeString(&Properties
, REGSTR_KEY_DEVICE_PROPERTIES
);
327 Status
= IopOpenRegistryKeyEx(&PropertiesKey
,
331 if (!NT_SUCCESS(Status
))
334 DPRINT("IopOpenRegistryKeyEx() failed with Status %08X\n", Status
);
335 PropertiesKey
= NULL
;
339 /* Free the registry data */
340 ExFreePool(KeyValueInformation
);
343 /* Do ReactOS-style setup */
344 IopAttachFilterDrivers(DeviceNode
, TRUE
);
345 Status
= IopInitializeDevice(DeviceNode
, DriverObject
);
346 if (NT_SUCCESS(Status
))
348 IopAttachFilterDrivers(DeviceNode
, FALSE
);
349 Status
= IopStartDevice(DeviceNode
);
358 IopInitializePlugPlayServices(VOID
)
362 HANDLE KeyHandle
, EnumHandle
, ParentHandle
, TreeHandle
;
363 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
366 /* Initialize locks and such */
367 KeInitializeSpinLock(&IopDeviceTreeLock
);
369 /* Get the default interface */
370 PnpDefaultInterfaceType
= IopDetermineDefaultInterfaceType();
372 /* Initialize arbiters */
373 Status
= IopInitializeArbiters();
374 if (!NT_SUCCESS(Status
)) return Status
;
376 /* Setup the group cache */
377 Status
= PiInitCacheGroupInformation();
378 if (!NT_SUCCESS(Status
)) return Status
;
380 /* Open the current control set */
381 Status
= IopOpenRegistryKeyEx(&KeyHandle
,
385 if (!NT_SUCCESS(Status
)) return Status
;
387 /* Create the enum key */
388 RtlInitUnicodeString(&KeyName
, REGSTR_KEY_ENUM
);
389 Status
= IopCreateRegistryKeyEx(&EnumHandle
,
393 REG_OPTION_NON_VOLATILE
,
395 if (!NT_SUCCESS(Status
)) return Status
;
397 /* Check if it's a new key */
398 if (Disposition
== REG_CREATED_NEW_KEY
)
401 DPRINT1("Need to build DACL\n");
404 /* Create the root key */
405 ParentHandle
= EnumHandle
;
406 RtlInitUnicodeString(&KeyName
, REGSTR_KEY_ROOTENUM
);
407 Status
= IopCreateRegistryKeyEx(&EnumHandle
,
411 REG_OPTION_NON_VOLATILE
,
413 NtClose(ParentHandle
);
414 if (!NT_SUCCESS(Status
)) return Status
;
417 /* Open the root key now */
418 RtlInitUnicodeString(&KeyName
, L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
419 Status
= IopOpenRegistryKeyEx(&EnumHandle
,
423 if (NT_SUCCESS(Status
))
425 /* Create the root dev node */
426 RtlInitUnicodeString(&KeyName
, REGSTR_VAL_ROOT_DEVNODE
);
427 Status
= IopCreateRegistryKeyEx(&TreeHandle
,
431 REG_OPTION_NON_VOLATILE
,
434 if (NT_SUCCESS(Status
)) NtClose(TreeHandle
);
437 /* Create the root driver */
438 Status
= IoCreateDriver(NULL
, PnpRootDriverEntry
);
439 if (!NT_SUCCESS(Status
))
441 DPRINT1("IoCreateDriverObject() failed\n");
442 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
445 /* Create the root PDO */
446 Status
= IoCreateDevice(IopRootDriverObject
,
447 sizeof(IOPNP_DEVICE_EXTENSION
),
449 FILE_DEVICE_CONTROLLER
,
453 if (!NT_SUCCESS(Status
))
455 DPRINT1("IoCreateDevice() failed\n");
456 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
459 /* This is a bus enumerated device */
460 Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
462 /* Create the root device node */
463 IopRootDeviceNode
= PipAllocateDeviceNode(Pdo
);
466 IopRootDeviceNode
->Flags
|= DNF_STARTED
+ DNF_PROCESSED
+ DNF_ENUMERATED
+
467 DNF_MADEUP
+ DNF_NO_RESOURCE_REQUIRED
+
470 /* Create instance path */
471 RtlCreateUnicodeString(&IopRootDeviceNode
->InstancePath
,
472 REGSTR_VAL_ROOT_DEVNODE
);
474 /* Call the add device routine */
475 IopRootDriverObject
->DriverExtension
->AddDevice(IopRootDriverObject
,
476 IopRootDeviceNode
->PhysicalDeviceObject
);
478 /* Initialize PnP-Event notification support */
479 Status
= IopInitPlugPlayEvents();
480 if (!NT_SUCCESS(Status
)) return Status
;
482 /* Report the device to the user-mode pnp manager */
483 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL
,
484 &IopRootDeviceNode
->InstancePath
);
486 /* Initialize the Bus Type GUID List */
487 PnpBusTypeGuidList
= ExAllocatePool(PagedPool
, sizeof(IO_BUS_TYPE_GUID_LIST
));
488 RtlZeroMemory(PnpBusTypeGuidList
, sizeof(IO_BUS_TYPE_GUID_LIST
));
489 ExInitializeFastMutex(&PnpBusTypeGuidList
->Lock
);
491 /* Launch the firmware mapper */
492 Status
= IopUpdateRootKey();
493 if (!NT_SUCCESS(Status
)) return Status
;
495 /* Close the handle to the control set */
499 return STATUS_SUCCESS
;