1 /* $Id: pnpmgr.c,v 1.3 2001/09/01 15:36:44 chorns Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/pnpmgr.c
6 * PURPOSE: Initializes the PnP manager
7 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * 16/04/2001 CSH Created
12 /* INCLUDES ******************************************************************/
14 #include <ddk/ntddk.h>
15 #include <internal/io.h>
16 #include <internal/po.h>
17 #include <internal/ldr.h>
18 #include <internal/module.h>
21 #include <internal/debug.h>
23 /* GLOBALS *******************************************************************/
25 PDEVICE_NODE IopRootDeviceNode
;
26 KSPIN_LOCK IopDeviceTreeLock
;
28 /* DATA **********************************************************************/
30 PDRIVER_OBJECT IopRootDriverObject
;
32 /* FUNCTIONS *****************************************************************/
36 IoInitializeRemoveLockEx(
37 IN PIO_REMOVE_LOCK Lock
,
39 IN ULONG MaxLockedMinutes
,
40 IN ULONG HighWatermark
,
47 IoAcquireRemoveLockEx(
48 IN PIO_REMOVE_LOCK RemoveLock
,
49 IN OPTIONAL PVOID Tag
,
54 return STATUS_NOT_IMPLEMENTED
;
59 IoReleaseRemoveLockEx(
60 IN PIO_REMOVE_LOCK RemoveLock
,
68 IoReleaseRemoveLockAndWaitEx(
69 IN PIO_REMOVE_LOCK RemoveLock
,
77 IoAdjustPagingPathCount(
85 IoGetDeviceInterfaceAlias(
86 IN PUNICODE_STRING SymbolicLinkName
,
87 IN CONST GUID
*AliasInterfaceClassGuid
,
88 OUT PUNICODE_STRING AliasSymbolicLinkName
)
90 return STATUS_NOT_IMPLEMENTED
;
95 IoGetDeviceInterfaces(
96 IN CONST GUID
*InterfaceClassGuid
,
97 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL
,
99 OUT PWSTR
*SymbolicLinkList
)
101 return STATUS_NOT_IMPLEMENTED
;
107 IN PDEVICE_OBJECT DeviceObject
,
108 IN DEVICE_REGISTRY_PROPERTY DeviceProperty
,
109 IN ULONG BufferLength
,
110 OUT PVOID PropertyBuffer
,
111 OUT PULONG ResultLength
)
113 return STATUS_NOT_IMPLEMENTED
;
118 IoInvalidateDeviceRelations(
119 IN PDEVICE_OBJECT DeviceObject
,
120 IN DEVICE_RELATION_TYPE Type
)
126 IoInvalidateDeviceState(
127 IN PDEVICE_OBJECT PhysicalDeviceObject
)
133 IoOpenDeviceInterfaceRegistryKey(
134 IN PUNICODE_STRING SymbolicLinkName
,
135 IN ACCESS_MASK DesiredAccess
,
136 OUT PHANDLE DeviceInterfaceKey
)
138 return STATUS_NOT_IMPLEMENTED
;
143 IoOpenDeviceRegistryKey(
144 IN PDEVICE_OBJECT DeviceObject
,
145 IN ULONG DevInstKeyType
,
146 IN ACCESS_MASK DesiredAccess
,
147 OUT PHANDLE DevInstRegKey
)
149 return STATUS_NOT_IMPLEMENTED
;
154 IoRegisterDeviceInterface(
155 IN PDEVICE_OBJECT PhysicalDeviceObject
,
156 IN CONST GUID
*InterfaceClassGuid
,
157 IN PUNICODE_STRING ReferenceString OPTIONAL
,
158 OUT PUNICODE_STRING SymbolicLinkName
)
160 return STATUS_NOT_IMPLEMENTED
;
165 IoRegisterPlugPlayNotification(
166 IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory
,
167 IN ULONG EventCategoryFlags
,
168 IN PVOID EventCategoryData OPTIONAL
,
169 IN PDRIVER_OBJECT DriverObject
,
170 IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine
,
172 OUT PVOID
*NotificationEntry
)
174 return STATUS_NOT_IMPLEMENTED
;
179 IoReportDetectedDevice(
180 IN PDRIVER_OBJECT DriverObject
,
181 IN INTERFACE_TYPE LegacyBusType
,
184 IN PCM_RESOURCE_LIST ResourceList
,
185 IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL
,
186 IN BOOLEAN ResourceAssigned
,
187 IN OUT PDEVICE_OBJECT
*DeviceObject
)
189 return STATUS_NOT_IMPLEMENTED
;
194 IoReportResourceForDetection(
195 IN PDRIVER_OBJECT DriverObject
,
196 IN PCM_RESOURCE_LIST DriverList OPTIONAL
,
197 IN ULONG DriverListSize OPTIONAL
,
198 IN PDEVICE_OBJECT DeviceObject OPTIONAL
,
199 IN PCM_RESOURCE_LIST DeviceList OPTIONAL
,
200 IN ULONG DeviceListSize OPTIONAL
,
201 OUT PBOOLEAN ConflictDetected
)
203 return STATUS_NOT_IMPLEMENTED
;
208 IoReportTargetDeviceChange(
209 IN PDEVICE_OBJECT PhysicalDeviceObject
,
210 IN PVOID NotificationStructure
)
212 return STATUS_NOT_IMPLEMENTED
;
217 IoReportTargetDeviceChangeAsynchronous(
218 IN PDEVICE_OBJECT PhysicalDeviceObject
,
219 IN PVOID NotificationStructure
,
220 IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL
,
221 IN PVOID Context OPTIONAL
)
223 return STATUS_NOT_IMPLEMENTED
;
228 IoRequestDeviceEject(
229 IN PDEVICE_OBJECT PhysicalDeviceObject
)
235 IoSetDeviceInterfaceState(
236 IN PUNICODE_STRING SymbolicLinkName
,
239 return STATUS_NOT_IMPLEMENTED
;
244 IoUnregisterPlugPlayNotification(
245 IN PVOID NotificationEntry
)
247 return STATUS_NOT_IMPLEMENTED
;
252 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT
*DeviceObject
)
256 assert(PopSystemPowerDeviceNode
);
258 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
259 *DeviceObject
= PopSystemPowerDeviceNode
->Pdo
;
260 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
262 return STATUS_SUCCESS
;
265 /**********************************************************************
267 * Creates a device node
270 * ParentNode = Pointer to parent device node
271 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
272 * to have the root device node create one
273 * (eg. for legacy drivers)
274 * DeviceNode = Pointer to storage for created device node
280 IopCreateDeviceNode(PDEVICE_NODE ParentNode
,
281 PDEVICE_OBJECT PhysicalDeviceObject
,
282 PDEVICE_NODE
*DeviceNode
)
288 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
289 ParentNode
, PhysicalDeviceObject
);
291 Node
= (PDEVICE_NODE
)ExAllocatePool(PagedPool
, sizeof(DEVICE_NODE
));
294 return STATUS_INSUFFICIENT_RESOURCES
;
297 RtlZeroMemory(Node
, sizeof(DEVICE_NODE
));
299 if (!PhysicalDeviceObject
)
301 Status
= PnpRootCreateDevice(&PhysicalDeviceObject
);
302 if (!NT_SUCCESS(Status
))
309 Node
->Pdo
= PhysicalDeviceObject
;
313 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
314 Node
->Parent
= ParentNode
;
315 Node
->NextSibling
= ParentNode
->Child
;
316 ParentNode
->Child
->PrevSibling
= Node
;
317 ParentNode
->Child
= Node
;
318 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
323 return STATUS_SUCCESS
;
327 IopFreeDeviceNode(PDEVICE_NODE DeviceNode
)
331 /* All children must be deleted before a parent is deleted */
332 assert(!DeviceNode
->Child
);
334 KeAcquireSpinLock(&IopDeviceTreeLock
, &OldIrql
);
336 assert(DeviceNode
->Pdo
);
338 ObDereferenceObject(DeviceNode
->Pdo
);
340 /* Unlink from parent if it exists */
342 if ((DeviceNode
->Parent
) && (DeviceNode
->Parent
->Child
== DeviceNode
))
344 DeviceNode
->Parent
->Child
= DeviceNode
->NextSibling
;
347 /* Unlink from sibling list */
349 if (DeviceNode
->PrevSibling
)
351 DeviceNode
->PrevSibling
->NextSibling
= DeviceNode
->NextSibling
;
354 if (DeviceNode
->NextSibling
)
356 DeviceNode
->NextSibling
->PrevSibling
= DeviceNode
->PrevSibling
;
359 KeReleaseSpinLock(&IopDeviceTreeLock
, OldIrql
);
361 RtlFreeUnicodeString(&DeviceNode
->InstancePath
);
363 RtlFreeUnicodeString(&DeviceNode
->ServiceName
);
365 /* FIXME: Other fields may need to be released */
367 ExFreePool(DeviceNode
);
369 return STATUS_SUCCESS
;
374 PDEVICE_OBJECT DeviceObject
,
375 PIO_STATUS_BLOCK IoStatusBlock
,
377 PIO_STACK_LOCATION Stack
)
379 PDEVICE_OBJECT TopDeviceObject
;
380 PIO_STACK_LOCATION IrpSp
;
385 /* Always call the top of the device stack */
386 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
393 /* PNP IRPs are always initialized with a status code of
394 STATUS_NOT_IMPLEMENTED */
395 IoStatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
397 Irp
= IoBuildSynchronousFsdRequest(
406 IrpSp
= IoGetNextIrpStackLocation(Irp
);
407 IrpSp
->MinorFunction
= MinorFunction
;
411 sizeof(Stack
->Parameters
));
413 Status
= IoCallDriver(TopDeviceObject
, Irp
);
414 if (Status
== STATUS_PENDING
)
416 KeWaitForSingleObject(
422 Status
= IoStatusBlock
->Status
;
429 IopInterrogateBusExtender(
430 PDEVICE_NODE DeviceNode
,
431 PDEVICE_OBJECT FunctionDeviceObject
,
432 BOOLEAN BootDriversOnly
)
434 PDEVICE_RELATIONS DeviceRelations
;
435 IO_STATUS_BLOCK IoStatusBlock
;
436 UNICODE_STRING DriverName
;
437 IO_STACK_LOCATION Stack
;
440 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to bus driver\n");
442 Stack
.Parameters
.QueryDeviceRelations
.Type
= BusRelations
;
444 Status
= IopInitiatePnpIrp(
445 FunctionDeviceObject
,
447 IRP_MN_QUERY_DEVICE_RELATIONS
,
449 if (!NT_SUCCESS(Status
))
451 DPRINT("IopInitiatePnpIrp() failed\n");
454 DeviceRelations
= (PDEVICE_RELATIONS
)IoStatusBlock
.Information
;
456 DPRINT("Got %d PDOs\n", DeviceRelations
->Count
);
458 if (DeviceRelations
->Count
<= 0)
461 ExFreePool(DeviceRelations
);
462 return STATUS_SUCCESS
;
465 Status
= IopCreateDeviceNode(DeviceNode
, NULL
, &DeviceNode
);
466 if (!NT_SUCCESS(Status
))
468 DPRINT("No resources\n");
469 ExFreePool(DeviceRelations
);
470 return STATUS_INSUFFICIENT_RESOURCES
;
473 /* FIXME: Use registry to find name of driver and only load driver if not
474 already loaded. If loaded, just call AddDevice() */
475 Status
= LdrLoadDriver(&DriverName
, DeviceNode
, FALSE
);
476 if (!NT_SUCCESS(Status
))
478 /* Don't free the device node, just log the error and return */
479 /* FIXME: Log the error */
480 CPRINT("Driver load failed, status (%x)\n", Status
);
481 ExFreePool(DeviceRelations
);
485 ExFreePool(DeviceRelations
);
490 VOID
IopLoadBootStartDrivers(VOID
)
492 OBJECT_ATTRIBUTES ObjectAttributes
;
493 PKEY_BASIC_INFORMATION KeyInfo
;
494 PDEVICE_NODE DeviceNode
;
495 UNICODE_STRING KeyName
;
502 DPRINT("Loading boot start drivers\n");
504 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + (MAX_PATH
+1) * sizeof(WCHAR
);
505 KeyInfo
= ExAllocatePool(PagedPool
, BufferSize
);
511 RtlInitUnicodeString(
513 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
515 InitializeObjectAttributes(
518 OBJ_CASE_INSENSITIVE
,
522 Status
= NtOpenKey(&KeyHandle
, KEY_ALL_ACCESS
, &ObjectAttributes
);
523 if (!NT_SUCCESS(Status
))
525 DPRINT("NtOpenKey() failed (Status %x)\n", Status
);
532 Status
= ZwEnumerateKey(
539 if (!NT_SUCCESS(Status
))
541 DPRINT("ZwEnumerateKey() (Status %x)\n", Status
);
545 /* Terminate the string */
546 KeyInfo
->Name
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = 0;
548 /* Use IopRootDeviceNode for now */
549 Status
= IopCreateDeviceNode(IopRootDeviceNode
, NULL
, &DeviceNode
);
550 if (!NT_SUCCESS(Status
))
552 CPRINT("IopCreateDeviceNode() failed with status 0x%X\n", Status
);
556 if (!RtlCreateUnicodeString(&DeviceNode
->ServiceName
, KeyInfo
->Name
))
558 CPRINT("RtlCreateUnicodeString() failed\n");
559 IopFreeDeviceNode(DeviceNode
);
563 Status
= IopInitializeDeviceNodeService(DeviceNode
);
564 if (!NT_SUCCESS(Status
))
566 /* FIXME: Write an entry in the system error log */
567 CPRINT("Could not load boot start driver: %wZ, status 0x%X\n",
568 &DeviceNode
->ServiceName
, Status
);
570 IopFreeDeviceNode(DeviceNode
);
576 DPRINT("Services found: %d\n", Index
);
589 KeInitializeSpinLock(&IopDeviceTreeLock
);
591 Status
= IopCreateDriverObject(&IopRootDriverObject
);
592 if (!NT_SUCCESS(Status
))
594 CPRINT("IoCreateDriverObject() failed\n");
598 PnpRootDriverEntry(IopRootDriverObject
, NULL
);
600 Status
= IoCreateDevice(IopRootDriverObject
, 0, NULL
,
601 FILE_DEVICE_CONTROLLER
, 0, FALSE
, &IopRootDeviceNode
->Pdo
);
602 if (!NT_SUCCESS(Status
))
604 CPRINT("IoCreateDevice() failed\n");
608 IopRootDeviceNode
->Pdo
->Flags
|= DO_BUS_ENUMERATED_DEVICE
;
610 IopRootDriverObject
->DriverExtension
->AddDevice(
611 IopRootDriverObject
, IopRootDeviceNode
->Pdo
);