Implemented many console & registry functions to get registry explorer running.
[reactos.git] / reactos / ntoskrnl / io / pnpmgr.c
1 /* $Id: pnpmgr.c,v 1.3 2001/09/01 15:36:44 chorns Exp $
2 *
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)
8 * UPDATE HISTORY:
9 * 16/04/2001 CSH Created
10 */
11
12 /* INCLUDES ******************************************************************/
13
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>
19
20 #define NDEBUG
21 #include <internal/debug.h>
22
23 /* GLOBALS *******************************************************************/
24
25 PDEVICE_NODE IopRootDeviceNode;
26 KSPIN_LOCK IopDeviceTreeLock;
27
28 /* DATA **********************************************************************/
29
30 PDRIVER_OBJECT IopRootDriverObject;
31
32 /* FUNCTIONS *****************************************************************/
33
34 VOID
35 STDCALL
36 IoInitializeRemoveLockEx(
37 IN PIO_REMOVE_LOCK Lock,
38 IN ULONG AllocateTag,
39 IN ULONG MaxLockedMinutes,
40 IN ULONG HighWatermark,
41 IN ULONG RemlockSize)
42 {
43 }
44
45 NTSTATUS
46 STDCALL
47 IoAcquireRemoveLockEx(
48 IN PIO_REMOVE_LOCK RemoveLock,
49 IN OPTIONAL PVOID Tag,
50 IN LPCSTR File,
51 IN ULONG Line,
52 IN ULONG RemlockSize)
53 {
54 return STATUS_NOT_IMPLEMENTED;
55 }
56
57 VOID
58 STDCALL
59 IoReleaseRemoveLockEx(
60 IN PIO_REMOVE_LOCK RemoveLock,
61 IN PVOID Tag,
62 IN ULONG RemlockSize)
63 {
64 }
65
66 VOID
67 STDCALL
68 IoReleaseRemoveLockAndWaitEx(
69 IN PIO_REMOVE_LOCK RemoveLock,
70 IN PVOID Tag,
71 IN ULONG RemlockSize)
72 {
73 }
74
75 VOID
76 STDCALL
77 IoAdjustPagingPathCount(
78 IN PLONG Count,
79 IN BOOLEAN Increment)
80 {
81 }
82
83 NTSTATUS
84 STDCALL
85 IoGetDeviceInterfaceAlias(
86 IN PUNICODE_STRING SymbolicLinkName,
87 IN CONST GUID *AliasInterfaceClassGuid,
88 OUT PUNICODE_STRING AliasSymbolicLinkName)
89 {
90 return STATUS_NOT_IMPLEMENTED;
91 }
92
93 NTSTATUS
94 STDCALL
95 IoGetDeviceInterfaces(
96 IN CONST GUID *InterfaceClassGuid,
97 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
98 IN ULONG Flags,
99 OUT PWSTR *SymbolicLinkList)
100 {
101 return STATUS_NOT_IMPLEMENTED;
102 }
103
104 NTSTATUS
105 STDCALL
106 IoGetDeviceProperty(
107 IN PDEVICE_OBJECT DeviceObject,
108 IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
109 IN ULONG BufferLength,
110 OUT PVOID PropertyBuffer,
111 OUT PULONG ResultLength)
112 {
113 return STATUS_NOT_IMPLEMENTED;
114 }
115
116 VOID
117 STDCALL
118 IoInvalidateDeviceRelations(
119 IN PDEVICE_OBJECT DeviceObject,
120 IN DEVICE_RELATION_TYPE Type)
121 {
122 }
123
124 VOID
125 STDCALL
126 IoInvalidateDeviceState(
127 IN PDEVICE_OBJECT PhysicalDeviceObject)
128 {
129 }
130
131 NTSTATUS
132 STDCALL
133 IoOpenDeviceInterfaceRegistryKey(
134 IN PUNICODE_STRING SymbolicLinkName,
135 IN ACCESS_MASK DesiredAccess,
136 OUT PHANDLE DeviceInterfaceKey)
137 {
138 return STATUS_NOT_IMPLEMENTED;
139 }
140
141 NTSTATUS
142 STDCALL
143 IoOpenDeviceRegistryKey(
144 IN PDEVICE_OBJECT DeviceObject,
145 IN ULONG DevInstKeyType,
146 IN ACCESS_MASK DesiredAccess,
147 OUT PHANDLE DevInstRegKey)
148 {
149 return STATUS_NOT_IMPLEMENTED;
150 }
151
152 NTSTATUS
153 STDCALL
154 IoRegisterDeviceInterface(
155 IN PDEVICE_OBJECT PhysicalDeviceObject,
156 IN CONST GUID *InterfaceClassGuid,
157 IN PUNICODE_STRING ReferenceString OPTIONAL,
158 OUT PUNICODE_STRING SymbolicLinkName)
159 {
160 return STATUS_NOT_IMPLEMENTED;
161 }
162
163 NTSTATUS
164 STDCALL
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,
171 IN PVOID Context,
172 OUT PVOID *NotificationEntry)
173 {
174 return STATUS_NOT_IMPLEMENTED;
175 }
176
177 NTSTATUS
178 STDCALL
179 IoReportDetectedDevice(
180 IN PDRIVER_OBJECT DriverObject,
181 IN INTERFACE_TYPE LegacyBusType,
182 IN ULONG BusNumber,
183 IN ULONG SlotNumber,
184 IN PCM_RESOURCE_LIST ResourceList,
185 IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL,
186 IN BOOLEAN ResourceAssigned,
187 IN OUT PDEVICE_OBJECT *DeviceObject)
188 {
189 return STATUS_NOT_IMPLEMENTED;
190 }
191
192 NTSTATUS
193 STDCALL
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)
202 {
203 return STATUS_NOT_IMPLEMENTED;
204 }
205
206 NTSTATUS
207 STDCALL
208 IoReportTargetDeviceChange(
209 IN PDEVICE_OBJECT PhysicalDeviceObject,
210 IN PVOID NotificationStructure)
211 {
212 return STATUS_NOT_IMPLEMENTED;
213 }
214
215 NTSTATUS
216 STDCALL
217 IoReportTargetDeviceChangeAsynchronous(
218 IN PDEVICE_OBJECT PhysicalDeviceObject,
219 IN PVOID NotificationStructure,
220 IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL,
221 IN PVOID Context OPTIONAL)
222 {
223 return STATUS_NOT_IMPLEMENTED;
224 }
225
226 VOID
227 STDCALL
228 IoRequestDeviceEject(
229 IN PDEVICE_OBJECT PhysicalDeviceObject)
230 {
231 }
232
233 NTSTATUS
234 STDCALL
235 IoSetDeviceInterfaceState(
236 IN PUNICODE_STRING SymbolicLinkName,
237 IN BOOLEAN Enable)
238 {
239 return STATUS_NOT_IMPLEMENTED;
240 }
241
242 NTSTATUS
243 STDCALL
244 IoUnregisterPlugPlayNotification(
245 IN PVOID NotificationEntry)
246 {
247 return STATUS_NOT_IMPLEMENTED;
248 }
249
250
251 NTSTATUS
252 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject)
253 {
254 KIRQL OldIrql;
255
256 assert(PopSystemPowerDeviceNode);
257
258 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
259 *DeviceObject = PopSystemPowerDeviceNode->Pdo;
260 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
261
262 return STATUS_SUCCESS;
263 }
264
265 /**********************************************************************
266 * DESCRIPTION
267 * Creates a device node
268 *
269 * ARGUMENTS
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
275 *
276 * RETURN VALUE
277 * Status
278 */
279 NTSTATUS
280 IopCreateDeviceNode(PDEVICE_NODE ParentNode,
281 PDEVICE_OBJECT PhysicalDeviceObject,
282 PDEVICE_NODE *DeviceNode)
283 {
284 PDEVICE_NODE Node;
285 NTSTATUS Status;
286 KIRQL OldIrql;
287
288 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
289 ParentNode, PhysicalDeviceObject);
290
291 Node = (PDEVICE_NODE)ExAllocatePool(PagedPool, sizeof(DEVICE_NODE));
292 if (!Node)
293 {
294 return STATUS_INSUFFICIENT_RESOURCES;
295 }
296
297 RtlZeroMemory(Node, sizeof(DEVICE_NODE));
298
299 if (!PhysicalDeviceObject)
300 {
301 Status = PnpRootCreateDevice(&PhysicalDeviceObject);
302 if (!NT_SUCCESS(Status))
303 {
304 ExFreePool(Node);
305 return Status;
306 }
307 }
308
309 Node->Pdo = PhysicalDeviceObject;
310
311 if (ParentNode)
312 {
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);
319 }
320
321 *DeviceNode = Node;
322
323 return STATUS_SUCCESS;
324 }
325
326 NTSTATUS
327 IopFreeDeviceNode(PDEVICE_NODE DeviceNode)
328 {
329 KIRQL OldIrql;
330
331 /* All children must be deleted before a parent is deleted */
332 assert(!DeviceNode->Child);
333
334 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
335
336 assert(DeviceNode->Pdo);
337
338 ObDereferenceObject(DeviceNode->Pdo);
339
340 /* Unlink from parent if it exists */
341
342 if ((DeviceNode->Parent) && (DeviceNode->Parent->Child == DeviceNode))
343 {
344 DeviceNode->Parent->Child = DeviceNode->NextSibling;
345 }
346
347 /* Unlink from sibling list */
348
349 if (DeviceNode->PrevSibling)
350 {
351 DeviceNode->PrevSibling->NextSibling = DeviceNode->NextSibling;
352 }
353
354 if (DeviceNode->NextSibling)
355 {
356 DeviceNode->NextSibling->PrevSibling = DeviceNode->PrevSibling;
357 }
358
359 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
360
361 RtlFreeUnicodeString(&DeviceNode->InstancePath);
362
363 RtlFreeUnicodeString(&DeviceNode->ServiceName);
364
365 /* FIXME: Other fields may need to be released */
366
367 ExFreePool(DeviceNode);
368
369 return STATUS_SUCCESS;
370 }
371
372 NTSTATUS
373 IopInitiatePnpIrp(
374 PDEVICE_OBJECT DeviceObject,
375 PIO_STATUS_BLOCK IoStatusBlock,
376 ULONG MinorFunction,
377 PIO_STACK_LOCATION Stack)
378 {
379 PDEVICE_OBJECT TopDeviceObject;
380 PIO_STACK_LOCATION IrpSp;
381 NTSTATUS Status;
382 KEVENT Event;
383 PIRP Irp;
384
385 /* Always call the top of the device stack */
386 TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
387
388 KeInitializeEvent(
389 &Event,
390 NotificationEvent,
391 FALSE);
392
393 /* PNP IRPs are always initialized with a status code of
394 STATUS_NOT_IMPLEMENTED */
395 IoStatusBlock->Status = STATUS_NOT_IMPLEMENTED;
396
397 Irp = IoBuildSynchronousFsdRequest(
398 IRP_MJ_PNP,
399 TopDeviceObject,
400 NULL,
401 0,
402 NULL,
403 &Event,
404 IoStatusBlock);
405
406 IrpSp = IoGetNextIrpStackLocation(Irp);
407 IrpSp->MinorFunction = MinorFunction;
408 RtlMoveMemory(
409 &IrpSp->Parameters,
410 &Stack->Parameters,
411 sizeof(Stack->Parameters));
412
413 Status = IoCallDriver(TopDeviceObject, Irp);
414 if (Status == STATUS_PENDING)
415 {
416 KeWaitForSingleObject(
417 &Event,
418 Executive,
419 KernelMode,
420 FALSE,
421 NULL);
422 Status = IoStatusBlock->Status;
423 }
424
425 return Status;
426 }
427
428 NTSTATUS
429 IopInterrogateBusExtender(
430 PDEVICE_NODE DeviceNode,
431 PDEVICE_OBJECT FunctionDeviceObject,
432 BOOLEAN BootDriversOnly)
433 {
434 PDEVICE_RELATIONS DeviceRelations;
435 IO_STATUS_BLOCK IoStatusBlock;
436 UNICODE_STRING DriverName;
437 IO_STACK_LOCATION Stack;
438 NTSTATUS Status;
439
440 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to bus driver\n");
441
442 Stack.Parameters.QueryDeviceRelations.Type = BusRelations;
443
444 Status = IopInitiatePnpIrp(
445 FunctionDeviceObject,
446 &IoStatusBlock,
447 IRP_MN_QUERY_DEVICE_RELATIONS,
448 &Stack);
449 if (!NT_SUCCESS(Status))
450 {
451 DPRINT("IopInitiatePnpIrp() failed\n");
452 }
453
454 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
455
456 DPRINT("Got %d PDOs\n", DeviceRelations->Count);
457
458 if (DeviceRelations->Count <= 0)
459 {
460 DPRINT("No PDOs\n");
461 ExFreePool(DeviceRelations);
462 return STATUS_SUCCESS;
463 }
464
465 Status = IopCreateDeviceNode(DeviceNode, NULL, &DeviceNode);
466 if (!NT_SUCCESS(Status))
467 {
468 DPRINT("No resources\n");
469 ExFreePool(DeviceRelations);
470 return STATUS_INSUFFICIENT_RESOURCES;
471 }
472
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))
477 {
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);
482 return Status;
483 }
484
485 ExFreePool(DeviceRelations);
486
487 return Status;
488 }
489
490 VOID IopLoadBootStartDrivers(VOID)
491 {
492 OBJECT_ATTRIBUTES ObjectAttributes;
493 PKEY_BASIC_INFORMATION KeyInfo;
494 PDEVICE_NODE DeviceNode;
495 UNICODE_STRING KeyName;
496 HANDLE KeyHandle;
497 ULONG BufferSize;
498 ULONG ResultSize;
499 NTSTATUS Status;
500 ULONG Index;
501
502 DPRINT("Loading boot start drivers\n");
503
504 BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH+1) * sizeof(WCHAR);
505 KeyInfo = ExAllocatePool(PagedPool, BufferSize);
506 if (!KeyInfo)
507 {
508 return;
509 }
510
511 RtlInitUnicodeString(
512 &KeyName,
513 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
514
515 InitializeObjectAttributes(
516 &ObjectAttributes,
517 &KeyName,
518 OBJ_CASE_INSENSITIVE,
519 NULL,
520 NULL);
521
522 Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
523 if (!NT_SUCCESS(Status))
524 {
525 DPRINT("NtOpenKey() failed (Status %x)\n", Status);
526 ExFreePool(KeyInfo);
527 return;
528 }
529
530 Index = 0;
531 do {
532 Status = ZwEnumerateKey(
533 KeyHandle,
534 Index,
535 KeyBasicInformation,
536 KeyInfo,
537 BufferSize,
538 &ResultSize);
539 if (!NT_SUCCESS(Status))
540 {
541 DPRINT("ZwEnumerateKey() (Status %x)\n", Status);
542 break;
543 }
544
545 /* Terminate the string */
546 KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0;
547
548 /* Use IopRootDeviceNode for now */
549 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
550 if (!NT_SUCCESS(Status))
551 {
552 CPRINT("IopCreateDeviceNode() failed with status 0x%X\n", Status);
553 break;
554 }
555
556 if (!RtlCreateUnicodeString(&DeviceNode->ServiceName, KeyInfo->Name))
557 {
558 CPRINT("RtlCreateUnicodeString() failed\n");
559 IopFreeDeviceNode(DeviceNode);
560 break;
561 }
562
563 Status = IopInitializeDeviceNodeService(DeviceNode);
564 if (!NT_SUCCESS(Status))
565 {
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);
569
570 IopFreeDeviceNode(DeviceNode);
571 }
572
573 Index++;
574 } while (TRUE);
575
576 DPRINT("Services found: %d\n", Index);
577
578 NtClose(KeyHandle);
579
580 ExFreePool(KeyInfo);
581 }
582
583 VOID PnpInit(VOID)
584 {
585 NTSTATUS Status;
586
587 DPRINT("Called\n");
588
589 KeInitializeSpinLock(&IopDeviceTreeLock);
590
591 Status = IopCreateDriverObject(&IopRootDriverObject);
592 if (!NT_SUCCESS(Status))
593 {
594 CPRINT("IoCreateDriverObject() failed\n");
595 KeBugCheck(0);
596 }
597
598 PnpRootDriverEntry(IopRootDriverObject, NULL);
599
600 Status = IoCreateDevice(IopRootDriverObject, 0, NULL,
601 FILE_DEVICE_CONTROLLER, 0, FALSE, &IopRootDeviceNode->Pdo);
602 if (!NT_SUCCESS(Status))
603 {
604 CPRINT("IoCreateDevice() failed\n");
605 KeBugCheck(0);
606 }
607
608 IopRootDeviceNode->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
609
610 IopRootDriverObject->DriverExtension->AddDevice(
611 IopRootDriverObject, IopRootDeviceNode->Pdo);
612 }
613
614 /* EOF */