Update DEVICE_NODE structure but some ReactOS specific components still remain.
[reactos.git] / reactos / ntoskrnl / io / pnpmgr.c
1 /* $Id: pnpmgr.c,v 1.45 2004/10/23 14:48:16 ekohl Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/pnpmgr/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 <ntoskrnl.h>
15 #include <ole32/guiddef.h>
16 #ifdef DEFINE_GUID
17 DEFINE_GUID(GUID_CLASS_COMPORT, 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73);
18 DEFINE_GUID(GUID_SERENUM_BUS_ENUMERATOR, 0x4D36E978L, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18);
19 #endif // DEFINE_GUID
20
21 //#define NDEBUG
22 #include <internal/debug.h>
23
24
25 /* GLOBALS *******************************************************************/
26
27 PDEVICE_NODE IopRootDeviceNode;
28 KSPIN_LOCK IopDeviceTreeLock;
29
30 /* DATA **********************************************************************/
31
32 PDRIVER_OBJECT IopRootDriverObject;
33
34 /* FUNCTIONS *****************************************************************/
35
36 /*
37 * @unimplemented
38 */
39 VOID
40 STDCALL
41 IoInvalidateDeviceRelations(
42 IN PDEVICE_OBJECT DeviceObject,
43 IN DEVICE_RELATION_TYPE Type)
44 {
45 }
46
47 PDEVICE_NODE FASTCALL
48 IopGetDeviceNode(
49 PDEVICE_OBJECT DeviceObject)
50 {
51 return DeviceObject->DeviceObjectExtension->DeviceNode;
52 }
53
54 /*
55 * @unimplemented
56 */
57 NTSTATUS
58 STDCALL
59 IoGetDeviceProperty(
60 IN PDEVICE_OBJECT DeviceObject,
61 IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
62 IN ULONG BufferLength,
63 OUT PVOID PropertyBuffer,
64 OUT PULONG ResultLength)
65 {
66 PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
67 ULONG Length;
68 PVOID Data;
69 PWSTR Ptr;
70
71 DPRINT("IoGetDeviceProperty(%x %d)\n", DeviceObject, DeviceProperty);
72
73 if (DeviceNode == NULL)
74 return STATUS_INVALID_DEVICE_REQUEST;
75
76 switch (DeviceProperty)
77 {
78 case DevicePropertyBusNumber:
79 Length = sizeof(ULONG);
80 Data = &DeviceNode->BusNumber;
81 break;
82
83 /* Complete, untested */
84 case DevicePropertyBusTypeGuid:
85 *ResultLength = 39 * sizeof(WCHAR);
86 if (BufferLength < (39 * sizeof(WCHAR)))
87 return STATUS_BUFFER_TOO_SMALL;
88 swprintf((PWSTR)PropertyBuffer,
89 L"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
90 DeviceNode->BusTypeGuid.Data1,
91 DeviceNode->BusTypeGuid.Data2,
92 DeviceNode->BusTypeGuid.Data3,
93 DeviceNode->BusTypeGuid.Data4[0],
94 DeviceNode->BusTypeGuid.Data4[1],
95 DeviceNode->BusTypeGuid.Data4[2],
96 DeviceNode->BusTypeGuid.Data4[3],
97 DeviceNode->BusTypeGuid.Data4[4],
98 DeviceNode->BusTypeGuid.Data4[5],
99 DeviceNode->BusTypeGuid.Data4[6],
100 DeviceNode->BusTypeGuid.Data4[7]);
101 return STATUS_SUCCESS;
102
103 case DevicePropertyLegacyBusType:
104 Length = sizeof(INTERFACE_TYPE);
105 Data = &DeviceNode->InterfaceType;
106 break;
107
108 case DevicePropertyAddress:
109 Length = sizeof(ULONG);
110 Data = &DeviceNode->Address;
111 break;
112
113 // case DevicePropertyUINumber:
114 // if (DeviceNode->CapabilityFlags == NULL)
115 // return STATUS_INVALID_DEVICE_REQUEST;
116 // Length = sizeof(ULONG);
117 // Data = &DeviceNode->CapabilityFlags->UINumber;
118 // break;
119
120 case DevicePropertyClassName:
121 case DevicePropertyClassGuid:
122 case DevicePropertyDriverKeyName:
123 case DevicePropertyManufacturer:
124 case DevicePropertyFriendlyName:
125 case DevicePropertyHardwareID:
126 case DevicePropertyCompatibleIDs:
127 case DevicePropertyDeviceDescription:
128 case DevicePropertyLocationInformation:
129 case DevicePropertyUINumber:
130 {
131 LPWSTR RegistryPropertyName, KeyNameBuffer;
132 UNICODE_STRING KeyName, ValueName;
133 OBJECT_ATTRIBUTES ObjectAttributes;
134 KEY_VALUE_PARTIAL_INFORMATION *ValueInformation;
135 ULONG ValueInformationLength;
136 HANDLE KeyHandle;
137 NTSTATUS Status;
138
139 switch (DeviceProperty)
140 {
141 case DevicePropertyClassName:
142 RegistryPropertyName = L"Class"; break;
143 case DevicePropertyClassGuid:
144 RegistryPropertyName = L"ClassGuid"; break;
145 case DevicePropertyDriverKeyName:
146 RegistryPropertyName = L"Driver"; break;
147 case DevicePropertyManufacturer:
148 RegistryPropertyName = L"Mfg"; break;
149 case DevicePropertyFriendlyName:
150 RegistryPropertyName = L"FriendlyName"; break;
151 case DevicePropertyHardwareID:
152 RegistryPropertyName = L"HardwareID"; break;
153 case DevicePropertyCompatibleIDs:
154 RegistryPropertyName = L"CompatibleIDs"; break;
155 case DevicePropertyDeviceDescription:
156 RegistryPropertyName = L"DeviceDesc"; break;
157 case DevicePropertyLocationInformation:
158 RegistryPropertyName = L"LocationInformation"; break;
159 case DevicePropertyUINumber:
160 RegistryPropertyName = L"UINumber"; break;
161 default:
162 RegistryPropertyName = NULL; break;
163 }
164
165 KeyNameBuffer = ExAllocatePool(PagedPool,
166 (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
167
168 DPRINT1("KeyNameBuffer: %x, value %S\n",
169 KeyNameBuffer, RegistryPropertyName);
170
171 if (KeyNameBuffer == NULL)
172 return STATUS_INSUFFICIENT_RESOURCES;
173
174 wcscpy(KeyNameBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
175 wcscat(KeyNameBuffer, DeviceNode->InstancePath.Buffer);
176 RtlInitUnicodeString(&KeyName, KeyNameBuffer);
177 InitializeObjectAttributes(&ObjectAttributes, &KeyName,
178 OBJ_CASE_INSENSITIVE, NULL, NULL);
179
180 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
181 ExFreePool(KeyNameBuffer);
182 if (!NT_SUCCESS(Status))
183 return Status;
184
185 RtlInitUnicodeString(&ValueName, RegistryPropertyName);
186 ValueInformationLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,
187 Data[0]) + BufferLength;
188 ValueInformation = ExAllocatePool(PagedPool, ValueInformationLength);
189 if (ValueInformation == NULL)
190 {
191 ZwClose(KeyHandle);
192 return STATUS_INSUFFICIENT_RESOURCES;
193 }
194
195 Status = ZwQueryValueKey(KeyHandle, &ValueName,
196 KeyValuePartialInformation, ValueInformation,
197 ValueInformationLength,
198 &ValueInformationLength);
199 *ResultLength = ValueInformation->DataLength;
200 ZwClose(KeyHandle);
201
202 if (ValueInformation->DataLength > BufferLength)
203 Status = STATUS_BUFFER_TOO_SMALL;
204
205 if (!NT_SUCCESS(Status))
206 {
207 ExFreePool(ValueInformation);
208 return Status;
209 }
210
211 /* FIXME: Verify the value (NULL-terminated, correct format). */
212
213 RtlCopyMemory(PropertyBuffer, ValueInformation->Data,
214 ValueInformation->DataLength);
215 ExFreePool(ValueInformation);
216
217 return STATUS_SUCCESS;
218 }
219
220 case DevicePropertyBootConfiguration:
221 Length = 0;
222 if (DeviceNode->BootResources->Count != 0)
223 {
224 Length = sizeof(CM_RESOURCE_LIST) +
225 ((DeviceNode->BootResources->Count - 1) * sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
226 }
227 Data = &DeviceNode->BootResources;
228 break;
229
230 /* FIXME: use a translated boot configuration instead */
231 case DevicePropertyBootConfigurationTranslated:
232 Length = 0;
233 if (DeviceNode->BootResources->Count != 0)
234 {
235 Length = sizeof(CM_RESOURCE_LIST) +
236 ((DeviceNode->BootResources->Count - 1) * sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
237 }
238 Data = &DeviceNode->BootResources;
239 break;
240
241 case DevicePropertyEnumeratorName:
242 Ptr = wcschr(DeviceNode->InstancePath.Buffer, L'\\');
243 if (Ptr != NULL)
244 {
245 Length = (ULONG)((ULONG_PTR)Ptr - (ULONG_PTR)DeviceNode->InstancePath.Buffer) + sizeof(WCHAR);
246 }
247 else
248 {
249 Length = 0;
250 Data = NULL;
251 }
252
253 case DevicePropertyPhysicalDeviceObjectName:
254 return STATUS_NOT_IMPLEMENTED;
255
256 default:
257 return STATUS_INVALID_PARAMETER_2;
258 }
259
260 *ResultLength = Length;
261 if (BufferLength < Length)
262 return STATUS_BUFFER_TOO_SMALL;
263 RtlCopyMemory(PropertyBuffer, Data, Length);
264
265 /* Terminate the string */
266 if (DeviceProperty == DevicePropertyEnumeratorName)
267 {
268 Ptr = (PWSTR)PropertyBuffer;
269 Ptr[(Length / sizeof(WCHAR)) - 1] = 0;
270 }
271
272 return STATUS_SUCCESS;
273 }
274
275 /*
276 * @unimplemented
277 */
278 VOID
279 STDCALL
280 IoInvalidateDeviceState(
281 IN PDEVICE_OBJECT PhysicalDeviceObject)
282 {
283 }
284
285 /*
286 * @unimplemented
287 */
288 NTSTATUS
289 STDCALL
290 IoOpenDeviceRegistryKey(
291 IN PDEVICE_OBJECT DeviceObject,
292 IN ULONG DevInstKeyType,
293 IN ACCESS_MASK DesiredAccess,
294 OUT PHANDLE DevInstRegKey)
295 {
296 static const WCHAR ClassKeyName[] = {
297 '\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
298 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t',
299 'r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\',
300 'C','l','a','s','s','\\'};
301 LPWSTR KeyNameBuffer;
302 UNICODE_STRING KeyName;
303 ULONG DriverKeyLength;
304 OBJECT_ATTRIBUTES ObjectAttributes;
305 NTSTATUS Status;
306
307 if (DevInstKeyType == PLUGPLAY_REGKEY_DRIVER)
308 {
309 Status = IoGetDeviceProperty(DeviceObject, DevicePropertyDriverKeyName,
310 0, NULL, &DriverKeyLength);
311 if (Status != STATUS_BUFFER_TOO_SMALL)
312 return Status;
313
314 KeyNameBuffer = ExAllocatePool(PagedPool, DriverKeyLength + sizeof(ClassKeyName));
315 if (KeyNameBuffer == NULL)
316 return STATUS_INSUFFICIENT_RESOURCES;
317
318 RtlCopyMemory(KeyNameBuffer, ClassKeyName, sizeof(ClassKeyName));
319 Status = IoGetDeviceProperty(DeviceObject, DevicePropertyDriverKeyName,
320 DriverKeyLength, KeyNameBuffer +
321 (sizeof(ClassKeyName) / sizeof(WCHAR)),
322 &DriverKeyLength);
323 if (!NT_SUCCESS(Status))
324 {
325 ExFreePool(KeyNameBuffer);
326 return Status;
327 }
328
329 RtlInitUnicodeString(&KeyName, KeyNameBuffer);
330 InitializeObjectAttributes(&ObjectAttributes, &KeyName,
331 OBJ_CASE_INSENSITIVE, NULL, NULL);
332 Status = ZwOpenKey(DevInstRegKey, DesiredAccess, &ObjectAttributes);
333 ExFreePool(KeyNameBuffer);
334 return Status;
335 }
336
337 return STATUS_NOT_IMPLEMENTED;
338 }
339
340 /*
341 * @unimplemented
342 */
343 VOID
344 STDCALL
345 IoRequestDeviceEject(
346 IN PDEVICE_OBJECT PhysicalDeviceObject
347 )
348 {
349 UNIMPLEMENTED;
350 }
351
352
353 BOOLEAN
354 IopCreateUnicodeString(
355 PUNICODE_STRING Destination,
356 PWSTR Source,
357 POOL_TYPE PoolType)
358 {
359 ULONG Length;
360
361 if (!Source)
362 {
363 RtlInitUnicodeString(Destination, NULL);
364 return TRUE;
365 }
366
367 Length = (wcslen(Source) + 1) * sizeof(WCHAR);
368
369 Destination->Buffer = ExAllocatePool(PoolType, Length);
370
371 if (Destination->Buffer == NULL)
372 {
373 return FALSE;
374 }
375
376 RtlCopyMemory(Destination->Buffer, Source, Length);
377
378 Destination->MaximumLength = Length;
379
380 Destination->Length = Length - sizeof(WCHAR);
381
382 return TRUE;
383 }
384
385 NTSTATUS
386 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject)
387 {
388 KIRQL OldIrql;
389
390 if (PopSystemPowerDeviceNode)
391 {
392 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
393 *DeviceObject = PopSystemPowerDeviceNode->PhysicalDeviceObject;
394 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
395
396 return STATUS_SUCCESS;
397 }
398
399 return STATUS_UNSUCCESSFUL;
400 }
401
402 /**********************************************************************
403 * DESCRIPTION
404 * Creates a device node
405 *
406 * ARGUMENTS
407 * ParentNode = Pointer to parent device node
408 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
409 * to have the root device node create one
410 * (eg. for legacy drivers)
411 * DeviceNode = Pointer to storage for created device node
412 *
413 * RETURN VALUE
414 * Status
415 */
416 NTSTATUS
417 IopCreateDeviceNode(PDEVICE_NODE ParentNode,
418 PDEVICE_OBJECT PhysicalDeviceObject,
419 PDEVICE_NODE *DeviceNode)
420 {
421 PDEVICE_NODE Node;
422 NTSTATUS Status;
423 KIRQL OldIrql;
424
425 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
426 ParentNode, PhysicalDeviceObject);
427
428 Node = (PDEVICE_NODE)ExAllocatePool(PagedPool, sizeof(DEVICE_NODE));
429 if (!Node)
430 {
431 return STATUS_INSUFFICIENT_RESOURCES;
432 }
433
434 RtlZeroMemory(Node, sizeof(DEVICE_NODE));
435
436 if (!PhysicalDeviceObject)
437 {
438 Status = PnpRootCreateDevice(&PhysicalDeviceObject);
439 if (!NT_SUCCESS(Status))
440 {
441 ExFreePool(Node);
442 return Status;
443 }
444
445 /* This is for drivers passed on the command line to ntoskrnl.exe */
446 IopDeviceNodeSetFlag(Node, DNF_STARTED);
447 IopDeviceNodeSetFlag(Node, DNF_LEGACY_DRIVER);
448 }
449
450 Node->PhysicalDeviceObject = PhysicalDeviceObject;
451
452 PhysicalDeviceObject->DeviceObjectExtension->DeviceNode = Node;
453
454 if (ParentNode)
455 {
456 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
457 Node->Parent = ParentNode;
458 Node->NextSibling = ParentNode->Child;
459 if (ParentNode->Child != NULL)
460 {
461 ParentNode->Child->PrevSibling = Node;
462 }
463 ParentNode->Child = Node;
464 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
465 }
466
467 *DeviceNode = Node;
468
469 return STATUS_SUCCESS;
470 }
471
472 NTSTATUS
473 IopFreeDeviceNode(PDEVICE_NODE DeviceNode)
474 {
475 KIRQL OldIrql;
476
477 /* All children must be deleted before a parent is deleted */
478 ASSERT(!DeviceNode->Child);
479
480 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
481
482 ASSERT(DeviceNode->PhysicalDeviceObject);
483
484 ObDereferenceObject(DeviceNode->PhysicalDeviceObject);
485
486 /* Unlink from parent if it exists */
487
488 if ((DeviceNode->Parent) && (DeviceNode->Parent->Child == DeviceNode))
489 {
490 DeviceNode->Parent->Child = DeviceNode->NextSibling;
491 }
492
493 /* Unlink from sibling list */
494
495 if (DeviceNode->PrevSibling)
496 {
497 DeviceNode->PrevSibling->NextSibling = DeviceNode->NextSibling;
498 }
499
500 if (DeviceNode->NextSibling)
501 {
502 DeviceNode->NextSibling->PrevSibling = DeviceNode->PrevSibling;
503 }
504
505 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
506
507 RtlFreeUnicodeString(&DeviceNode->InstancePath);
508
509 RtlFreeUnicodeString(&DeviceNode->ServiceName);
510
511 if (DeviceNode->ResourceList)
512 {
513 ExFreePool(DeviceNode->ResourceList);
514 }
515
516 if (DeviceNode->ResourceListTranslated)
517 {
518 ExFreePool(DeviceNode->ResourceListTranslated);
519 }
520
521 if (DeviceNode->ResourceRequirements)
522 {
523 ExFreePool(DeviceNode->ResourceRequirements);
524 }
525
526 if (DeviceNode->BootResources)
527 {
528 ExFreePool(DeviceNode->BootResources);
529 }
530
531 ExFreePool(DeviceNode);
532
533 return STATUS_SUCCESS;
534 }
535
536 NTSTATUS
537 IopInitiatePnpIrp(
538 PDEVICE_OBJECT DeviceObject,
539 PIO_STATUS_BLOCK IoStatusBlock,
540 ULONG MinorFunction,
541 PIO_STACK_LOCATION Stack OPTIONAL)
542 {
543 PDEVICE_OBJECT TopDeviceObject;
544 PIO_STACK_LOCATION IrpSp;
545 NTSTATUS Status;
546 KEVENT Event;
547 PIRP Irp;
548
549 /* Always call the top of the device stack */
550 TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
551
552 KeInitializeEvent(
553 &Event,
554 NotificationEvent,
555 FALSE);
556
557 Irp = IoBuildSynchronousFsdRequest(
558 IRP_MJ_PNP,
559 TopDeviceObject,
560 NULL,
561 0,
562 NULL,
563 &Event,
564 IoStatusBlock);
565
566 /* PNP IRPs are always initialized with a status code of
567 STATUS_NOT_IMPLEMENTED */
568 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
569 Irp->IoStatus.Information = 0;
570
571 IrpSp = IoGetNextIrpStackLocation(Irp);
572 IrpSp->MinorFunction = MinorFunction;
573
574 if (Stack)
575 {
576 RtlMoveMemory(
577 &IrpSp->Parameters,
578 &Stack->Parameters,
579 sizeof(Stack->Parameters));
580 }
581
582 Status = IoCallDriver(TopDeviceObject, Irp);
583 if (Status == STATUS_PENDING)
584 {
585 KeWaitForSingleObject(
586 &Event,
587 Executive,
588 KernelMode,
589 FALSE,
590 NULL);
591 Status = IoStatusBlock->Status;
592 }
593
594 ObDereferenceObject(TopDeviceObject);
595
596 return Status;
597 }
598
599
600 NTSTATUS
601 IopTraverseDeviceTreeNode(
602 PDEVICETREE_TRAVERSE_CONTEXT Context)
603 {
604 PDEVICE_NODE ParentDeviceNode;
605 PDEVICE_NODE ChildDeviceNode;
606 NTSTATUS Status;
607
608 /* Copy context data so we don't overwrite it in subsequent calls to this function */
609 ParentDeviceNode = Context->DeviceNode;
610
611 /* Call the action routine */
612 Status = (Context->Action)(ParentDeviceNode, Context->Context);
613 if (!NT_SUCCESS(Status))
614 {
615 return Status;
616 }
617
618 /* Traversal of all children nodes */
619 for (ChildDeviceNode = ParentDeviceNode->Child;
620 ChildDeviceNode != NULL;
621 ChildDeviceNode = ChildDeviceNode->NextSibling)
622 {
623 /* Pass the current device node to the action routine */
624 Context->DeviceNode = ChildDeviceNode;
625
626 Status = IopTraverseDeviceTreeNode(Context);
627 if (!NT_SUCCESS(Status))
628 {
629 return Status;
630 }
631 }
632
633 return Status;
634 }
635
636
637 NTSTATUS
638 IopTraverseDeviceTree(
639 PDEVICETREE_TRAVERSE_CONTEXT Context)
640 {
641 NTSTATUS Status;
642
643 DPRINT("Context %x\n", Context);
644
645 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
646 Context->DeviceNode, Context->FirstDeviceNode, Context->Action, Context->Context);
647
648 /* Start from the specified device node */
649 Context->DeviceNode = Context->FirstDeviceNode;
650
651 /* Recursively traverse the device tree */
652 Status = IopTraverseDeviceTreeNode(Context);
653 if (Status == STATUS_UNSUCCESSFUL)
654 {
655 /* The action routine just wanted to terminate the traversal with status
656 code STATUS_SUCCESS */
657 Status = STATUS_SUCCESS;
658 }
659
660 return Status;
661 }
662
663
664 static NTSTATUS
665 IopCreateDeviceKeyPath(PWSTR Path,
666 PHANDLE Handle)
667 {
668 OBJECT_ATTRIBUTES ObjectAttributes;
669 WCHAR KeyBuffer[MAX_PATH];
670 UNICODE_STRING KeyName;
671 HANDLE KeyHandle;
672 NTSTATUS Status;
673 PWCHAR Current;
674 PWCHAR Next;
675
676 *Handle = NULL;
677
678 if (_wcsnicmp(Path, L"\\Registry\\", 10) != 0)
679 {
680 return STATUS_INVALID_PARAMETER;
681 }
682
683 wcsncpy (KeyBuffer, Path, MAX_PATH-1);
684 RtlInitUnicodeString (&KeyName, KeyBuffer);
685
686 /* Skip \\Registry\\ */
687 Current = KeyName.Buffer;
688 Current = wcschr (Current, '\\') + 1;
689 Current = wcschr (Current, '\\') + 1;
690
691 while (TRUE)
692 {
693 Next = wcschr (Current, '\\');
694 if (Next == NULL)
695 {
696 /* The end */
697 }
698 else
699 {
700 *Next = 0;
701 }
702
703 InitializeObjectAttributes (&ObjectAttributes,
704 &KeyName,
705 OBJ_CASE_INSENSITIVE,
706 NULL,
707 NULL);
708
709 DPRINT("Create '%S'\n", KeyName.Buffer);
710
711 Status = NtCreateKey (&KeyHandle,
712 KEY_ALL_ACCESS,
713 &ObjectAttributes,
714 0,
715 NULL,
716 0,
717 NULL);
718 if (!NT_SUCCESS (Status))
719 {
720 DPRINT ("NtCreateKey() failed with status %x\n", Status);
721 return Status;
722 }
723
724 if (Next == NULL)
725 {
726 *Handle = KeyHandle;
727 return STATUS_SUCCESS;
728 }
729 else
730 {
731 NtClose (KeyHandle);
732 *Next = L'\\';
733 }
734
735 Current = Next + 1;
736 }
737
738 return STATUS_UNSUCCESSFUL;
739 }
740
741
742 static NTSTATUS
743 IopSetDeviceInstanceData(HANDLE InstanceKey,
744 PDEVICE_NODE DeviceNode)
745 {
746 OBJECT_ATTRIBUTES ObjectAttributes;
747 UNICODE_STRING KeyName;
748 HANDLE LogConfKey;
749 ULONG ResCount;
750 ULONG ListSize;
751 NTSTATUS Status;
752
753 DPRINT("IopSetDeviceInstanceData() called\n");
754
755 /* Create the 'LogConf' key */
756 RtlInitUnicodeString(&KeyName,
757 L"LogConf");
758 InitializeObjectAttributes(&ObjectAttributes,
759 &KeyName,
760 OBJ_CASE_INSENSITIVE,
761 InstanceKey,
762 NULL);
763 Status = NtCreateKey(&LogConfKey,
764 KEY_ALL_ACCESS,
765 &ObjectAttributes,
766 0,
767 NULL,
768 0,
769 NULL);
770 if (NT_SUCCESS(Status))
771 {
772 /* Set 'BootConfig' value */
773 if (DeviceNode->BootResources != NULL)
774 {
775 ResCount = DeviceNode->BootResources->Count;
776 if (ResCount != 0)
777 {
778 ListSize = sizeof(CM_RESOURCE_LIST) +
779 ((ResCount - 1) * sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
780
781 RtlInitUnicodeString(&KeyName,
782 L"BootConfig");
783 Status = NtSetValueKey(LogConfKey,
784 &KeyName,
785 0,
786 REG_RESOURCE_LIST,
787 &DeviceNode->BootResources,
788 ListSize);
789 }
790 }
791
792 /* Set 'BasicConfigVector' value */
793 if (DeviceNode->ResourceRequirements != NULL &&
794 DeviceNode->ResourceRequirements->ListSize != 0)
795 {
796 RtlInitUnicodeString(&KeyName,
797 L"BasicConfigVector");
798 Status = NtSetValueKey(LogConfKey,
799 &KeyName,
800 0,
801 REG_RESOURCE_REQUIREMENTS_LIST,
802 &DeviceNode->ResourceRequirements,
803 DeviceNode->ResourceRequirements->ListSize);
804 }
805
806 NtClose(LogConfKey);
807 }
808
809 DPRINT("IopSetDeviceInstanceData() done\n");
810
811 return STATUS_SUCCESS;
812 }
813
814
815 /*
816 * IopActionInterrogateDeviceStack
817 *
818 * Retrieve information for all (direct) child nodes of a parent node.
819 *
820 * Parameters
821 * DeviceNode
822 * Pointer to device node.
823 * Context
824 * Pointer to parent node to retrieve child node information for.
825 *
826 * Remarks
827 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
828 * when we reach a device node which is not a direct child of the device
829 * node for which we retrieve information of child nodes for. Any errors
830 * that occur is logged instead so that all child services have a chance
831 * of being interrogated.
832 */
833
834 NTSTATUS
835 IopActionInterrogateDeviceStack(
836 PDEVICE_NODE DeviceNode,
837 PVOID Context)
838 {
839 IO_STATUS_BLOCK IoStatusBlock;
840 PDEVICE_NODE ParentDeviceNode;
841 WCHAR InstancePath[MAX_PATH];
842 IO_STACK_LOCATION Stack;
843 NTSTATUS Status;
844 PWSTR KeyBuffer;
845 PWSTR Ptr;
846 USHORT Length;
847 USHORT TotalLength;
848 HANDLE InstanceKey = NULL;
849 UNICODE_STRING ValueName;
850 DEVICE_CAPABILITIES DeviceCapabilities;
851
852 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode, Context);
853 DPRINT("PDO %x\n", DeviceNode->PhysicalDeviceObject);
854
855 ParentDeviceNode = (PDEVICE_NODE)Context;
856
857 /*
858 * We are called for the parent too, but we don't need to do special
859 * handling for this node
860 */
861
862 if (DeviceNode == ParentDeviceNode)
863 {
864 DPRINT("Success\n");
865 return STATUS_SUCCESS;
866 }
867
868 /*
869 * Make sure this device node is a direct child of the parent device node
870 * that is given as an argument
871 */
872
873 if (DeviceNode->Parent != ParentDeviceNode)
874 {
875 /* Stop the traversal immediately and indicate successful operation */
876 DPRINT("Stop\n");
877 return STATUS_UNSUCCESSFUL;
878 }
879
880 /*
881 * FIXME: For critical errors, cleanup and disable device, but always
882 * return STATUS_SUCCESS.
883 */
884
885 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
886
887 Stack.Parameters.QueryId.IdType = BusQueryDeviceID;
888 Status = IopInitiatePnpIrp(
889 DeviceNode->PhysicalDeviceObject,
890 &IoStatusBlock,
891 IRP_MN_QUERY_ID,
892 &Stack);
893 if (NT_SUCCESS(Status))
894 {
895 /* Copy the device id string */
896 wcscpy(InstancePath, (PWSTR)IoStatusBlock.Information);
897
898 /*
899 * FIXME: Check for valid characters, if there is invalid characters
900 * then bugcheck.
901 */
902 }
903 else
904 {
905 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
906 }
907
908 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
909
910 Stack.Parameters.QueryId.IdType = BusQueryInstanceID;
911 Status = IopInitiatePnpIrp(
912 DeviceNode->PhysicalDeviceObject,
913 &IoStatusBlock,
914 IRP_MN_QUERY_ID,
915 &Stack);
916 if (NT_SUCCESS(Status))
917 {
918 /* Append the instance id string */
919 wcscat(InstancePath, L"\\");
920 wcscat(InstancePath, (PWSTR)IoStatusBlock.Information);
921
922 /*
923 * FIXME: Check for valid characters, if there is invalid characters
924 * then bugcheck
925 */
926 }
927 else
928 {
929 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
930 }
931
932 RtlZeroMemory(&DeviceCapabilities, sizeof(DEVICE_CAPABILITIES));
933 DeviceCapabilities.Size = sizeof(DEVICE_CAPABILITIES);
934 DeviceCapabilities.Version = 1;
935 DeviceCapabilities.Address = -1;
936 DeviceCapabilities.UINumber = -1;
937
938 Stack.Parameters.DeviceCapabilities.Capabilities = &DeviceCapabilities;
939 Status = IopInitiatePnpIrp(
940 DeviceNode->PhysicalDeviceObject,
941 &IoStatusBlock,
942 IRP_MN_QUERY_CAPABILITIES,
943 &Stack);
944 if (NT_SUCCESS(Status))
945 {
946 }
947 else
948 {
949 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
950 }
951
952 DeviceNode->CapabilityFlags = *(PULONG)((ULONG_PTR)&DeviceCapabilities + 4);
953 DeviceNode->Address = DeviceCapabilities.Address;
954
955 if (!DeviceCapabilities.UniqueID)
956 {
957 DPRINT("Instance ID is not unique\n");
958 /* FIXME: Add information from parent bus driver to InstancePath */
959 }
960
961 if (!IopCreateUnicodeString(&DeviceNode->InstancePath, InstancePath, PagedPool))
962 {
963 DPRINT("No resources\n");
964 /* FIXME: Cleanup and disable device */
965 }
966
967 DPRINT1("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
968
969 /*
970 * Create registry key for the instance id, if it doesn't exist yet
971 */
972 KeyBuffer = ExAllocatePool(
973 PagedPool,
974 (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
975 wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
976 wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer);
977 Status = IopCreateDeviceKeyPath(KeyBuffer,
978 &InstanceKey);
979 ExFreePool(KeyBuffer);
980 if (!NT_SUCCESS(Status))
981 {
982 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
983 }
984
985
986 {
987 /* Set 'Capabilities' value */
988 RtlInitUnicodeString(&ValueName,
989 L"Capabilities");
990 Status = NtSetValueKey(InstanceKey,
991 &ValueName,
992 0,
993 REG_DWORD,
994 (PVOID)&DeviceNode->CapabilityFlags,
995 sizeof(ULONG));
996
997 /* Set 'UINumber' value */
998 if (DeviceCapabilities.UINumber != (ULONG)-1)
999 {
1000 RtlInitUnicodeString(&ValueName,
1001 L"UINumber");
1002 Status = NtSetValueKey(InstanceKey,
1003 &ValueName,
1004 0,
1005 REG_DWORD,
1006 &DeviceCapabilities.UINumber,
1007 sizeof(ULONG));
1008 }
1009 }
1010
1011 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1012
1013 Stack.Parameters.QueryId.IdType = BusQueryHardwareIDs;
1014 Status = IopInitiatePnpIrp(
1015 DeviceNode->PhysicalDeviceObject,
1016 &IoStatusBlock,
1017 IRP_MN_QUERY_ID,
1018 &Stack);
1019 if (NT_SUCCESS(Status))
1020 {
1021 /*
1022 * FIXME: Check for valid characters, if there is invalid characters
1023 * then bugcheck.
1024 */
1025 TotalLength = 0;
1026 Ptr = (PWSTR)IoStatusBlock.Information;
1027 DPRINT("Hardware IDs:\n");
1028 while (*Ptr)
1029 {
1030 DPRINT(" %S\n", Ptr);
1031 Length = wcslen(Ptr) + 1;
1032
1033 Ptr += Length;
1034 TotalLength += Length;
1035 }
1036 DPRINT("TotalLength: %hu\n", TotalLength);
1037 DPRINT("\n");
1038
1039 RtlInitUnicodeString(&ValueName,
1040 L"HardwareID");
1041 Status = NtSetValueKey(InstanceKey,
1042 &ValueName,
1043 0,
1044 REG_MULTI_SZ,
1045 (PVOID)IoStatusBlock.Information,
1046 (TotalLength + 1) * sizeof(WCHAR));
1047 if (!NT_SUCCESS(Status))
1048 {
1049 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
1050 }
1051 }
1052 else
1053 {
1054 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1055 }
1056
1057 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1058
1059 Stack.Parameters.QueryId.IdType = BusQueryCompatibleIDs;
1060 Status = IopInitiatePnpIrp(
1061 DeviceNode->PhysicalDeviceObject,
1062 &IoStatusBlock,
1063 IRP_MN_QUERY_ID,
1064 &Stack);
1065 if (NT_SUCCESS(Status))
1066 {
1067 /*
1068 * FIXME: Check for valid characters, if there is invalid characters
1069 * then bugcheck.
1070 */
1071 TotalLength = 0;
1072 Ptr = (PWSTR)IoStatusBlock.Information;
1073 DPRINT("Compatible IDs:\n");
1074 while (*Ptr)
1075 {
1076 DPRINT(" %S\n", Ptr);
1077 Length = wcslen(Ptr) + 1;
1078
1079 Ptr += Length;
1080 TotalLength += Length;
1081 }
1082 DPRINT("TotalLength: %hu\n", TotalLength);
1083 DPRINT("\n");
1084
1085 RtlInitUnicodeString(&ValueName,
1086 L"CompatibleIDs");
1087 Status = NtSetValueKey(InstanceKey,
1088 &ValueName,
1089 0,
1090 REG_MULTI_SZ,
1091 (PVOID)IoStatusBlock.Information,
1092 (TotalLength + 1) * sizeof(WCHAR));
1093 if (!NT_SUCCESS(Status))
1094 {
1095 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
1096 }
1097 }
1098 else
1099 {
1100 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1101 }
1102
1103
1104 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1105
1106 Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextDescription;
1107 Stack.Parameters.QueryDeviceText.LocaleId = 0; /* FIXME */
1108 Status = IopInitiatePnpIrp(
1109 DeviceNode->PhysicalDeviceObject,
1110 &IoStatusBlock,
1111 IRP_MN_QUERY_DEVICE_TEXT,
1112 &Stack);
1113 if (NT_SUCCESS(Status))
1114 {
1115 RtlInitUnicodeString(&ValueName,
1116 L"DeviceDesc");
1117 Status = NtSetValueKey(InstanceKey,
1118 &ValueName,
1119 0,
1120 REG_SZ,
1121 (PVOID)IoStatusBlock.Information,
1122 (wcslen((PWSTR)IoStatusBlock.Information) + 1) * sizeof(WCHAR));
1123 if (!NT_SUCCESS(Status))
1124 {
1125 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
1126 }
1127 }
1128 else
1129 {
1130 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1131 }
1132
1133 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1134
1135 Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextLocationInformation;
1136 Stack.Parameters.QueryDeviceText.LocaleId = 0; // FIXME
1137 Status = IopInitiatePnpIrp(
1138 DeviceNode->PhysicalDeviceObject,
1139 &IoStatusBlock,
1140 IRP_MN_QUERY_DEVICE_TEXT,
1141 &Stack);
1142 if (NT_SUCCESS(Status))
1143 {
1144 DPRINT("LocationInformation: %S\n", (PWSTR)IoStatusBlock.Information);
1145 RtlInitUnicodeString(&ValueName,
1146 L"LocationInformation");
1147 Status = NtSetValueKey(InstanceKey,
1148 &ValueName,
1149 0,
1150 REG_SZ,
1151 (PVOID)IoStatusBlock.Information,
1152 (wcslen((PWSTR)IoStatusBlock.Information) + 1) * sizeof(WCHAR));
1153 if (!NT_SUCCESS(Status))
1154 {
1155 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
1156 }
1157 }
1158 else
1159 {
1160 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1161 }
1162
1163 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1164
1165 Status = IopInitiatePnpIrp(
1166 DeviceNode->PhysicalDeviceObject,
1167 &IoStatusBlock,
1168 IRP_MN_QUERY_BUS_INFORMATION,
1169 NULL);
1170 if (NT_SUCCESS(Status))
1171 {
1172 PPNP_BUS_INFORMATION BusInformation =
1173 (PPNP_BUS_INFORMATION)IoStatusBlock.Information;
1174
1175 DeviceNode->BusNumber = BusInformation->BusNumber;
1176 DeviceNode->InterfaceType = BusInformation->LegacyBusType;
1177 memcpy(&DeviceNode->BusTypeGuid,
1178 &BusInformation->BusTypeGuid,
1179 sizeof(GUID));
1180 ExFreePool(BusInformation);
1181 }
1182 else
1183 {
1184 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1185
1186 DeviceNode->BusNumber = -1;
1187 DeviceNode->InterfaceType = -1;
1188 memset(&DeviceNode->BusTypeGuid,
1189 0,
1190 sizeof(GUID));
1191 }
1192
1193 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1194
1195 Status = IopInitiatePnpIrp(
1196 DeviceNode->PhysicalDeviceObject,
1197 &IoStatusBlock,
1198 IRP_MN_QUERY_RESOURCES,
1199 NULL);
1200 if (NT_SUCCESS(Status))
1201 {
1202 DeviceNode->BootResources =
1203 (PCM_RESOURCE_LIST)IoStatusBlock.Information;
1204 DeviceNode->Flags |= DNF_HAS_BOOT_CONFIG;
1205 }
1206 else
1207 {
1208 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1209 DeviceNode->BootResources = NULL;
1210 }
1211
1212 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1213
1214 Status = IopInitiatePnpIrp(
1215 DeviceNode->PhysicalDeviceObject,
1216 &IoStatusBlock,
1217 IRP_MN_QUERY_RESOURCE_REQUIREMENTS,
1218 NULL);
1219 if (NT_SUCCESS(Status))
1220 {
1221 DeviceNode->ResourceRequirements =
1222 (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
1223 }
1224 else
1225 {
1226 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1227 DeviceNode->ResourceRequirements = NULL;
1228 }
1229
1230
1231 if (InstanceKey != NULL)
1232 {
1233 IopSetDeviceInstanceData(InstanceKey, DeviceNode);
1234 }
1235
1236 NtClose(InstanceKey);
1237
1238 DeviceNode->Flags |= DNF_PROCESSED;
1239
1240 return STATUS_SUCCESS;
1241 }
1242
1243 /*
1244 * IopActionConfigureChildServices
1245 *
1246 * Retrieve configuration for all (direct) child nodes of a parent node.
1247 *
1248 * Parameters
1249 * DeviceNode
1250 * Pointer to device node.
1251 * Context
1252 * Pointer to parent node to retrieve child node configuration for.
1253 *
1254 * Remarks
1255 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1256 * when we reach a device node which is not a direct child of the device
1257 * node for which we configure child services for. Any errors that occur is
1258 * logged instead so that all child services have a chance of beeing
1259 * configured.
1260 */
1261
1262 NTSTATUS
1263 IopActionConfigureChildServices(
1264 PDEVICE_NODE DeviceNode,
1265 PVOID Context)
1266 {
1267 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1268 PDEVICE_NODE ParentDeviceNode;
1269 PUNICODE_STRING Service;
1270 NTSTATUS Status;
1271
1272 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode, Context);
1273
1274 ParentDeviceNode = (PDEVICE_NODE)Context;
1275
1276 /*
1277 * We are called for the parent too, but we don't need to do special
1278 * handling for this node
1279 */
1280 if (DeviceNode == ParentDeviceNode)
1281 {
1282 DPRINT("Success\n");
1283 return STATUS_SUCCESS;
1284 }
1285
1286 /*
1287 * Make sure this device node is a direct child of the parent device node
1288 * that is given as an argument
1289 */
1290 if (DeviceNode->Parent != ParentDeviceNode)
1291 {
1292 /* Stop the traversal immediately and indicate successful operation */
1293 DPRINT("Stop\n");
1294 return STATUS_UNSUCCESSFUL;
1295 }
1296
1297 if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED))
1298 {
1299 /*
1300 * Retrieve configuration from Enum key
1301 */
1302
1303 Service = &DeviceNode->ServiceName;
1304
1305 RtlZeroMemory(QueryTable, sizeof(QueryTable));
1306 RtlInitUnicodeString(Service, NULL);
1307
1308 QueryTable[0].Name = L"Service";
1309 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
1310 QueryTable[0].EntryContext = Service;
1311
1312 Status = RtlQueryRegistryValues(RTL_REGISTRY_ENUM,
1313 DeviceNode->InstancePath.Buffer, QueryTable, NULL, NULL);
1314
1315 if (!NT_SUCCESS(Status))
1316 {
1317 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status);
1318 /* FIXME: Log the error */
1319 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1320 DeviceNode->InstancePath.Buffer, Status);
1321 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
1322 return STATUS_SUCCESS;
1323 }
1324
1325 if (Service->Buffer == NULL)
1326 {
1327 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
1328 return STATUS_SUCCESS;
1329 }
1330
1331 DPRINT("Got Service %S\n", Service->Buffer);
1332 }
1333
1334 return STATUS_SUCCESS;
1335 }
1336
1337 /*
1338 * IopActionInitChildServices
1339 *
1340 * Initialize the service for all (direct) child nodes of a parent node
1341 *
1342 * Parameters
1343 * DeviceNode
1344 * Pointer to device node.
1345 * Context
1346 * Pointer to parent node to initialize child node services for.
1347 * BootDrivers
1348 * Load only driver marked as boot start.
1349 *
1350 * Remarks
1351 * If the driver image for a service is not loaded and initialized
1352 * it is done here too. We only return a status code indicating an
1353 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1354 * not a direct child of the device node for which we initialize
1355 * child services for. Any errors that occur is logged instead so
1356 * that all child services have a chance of being initialized.
1357 */
1358
1359 NTSTATUS
1360 IopActionInitChildServices(
1361 PDEVICE_NODE DeviceNode,
1362 PVOID Context,
1363 BOOLEAN BootDrivers)
1364 {
1365 PDEVICE_NODE ParentDeviceNode;
1366 NTSTATUS Status;
1367
1368 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode, Context,
1369 BootDrivers);
1370
1371 ParentDeviceNode = (PDEVICE_NODE)Context;
1372
1373 /*
1374 * We are called for the parent too, but we don't need to do special
1375 * handling for this node
1376 */
1377 if (DeviceNode == ParentDeviceNode)
1378 {
1379 DPRINT("Success\n");
1380 return STATUS_SUCCESS;
1381 }
1382
1383 /*
1384 * Make sure this device node is a direct child of the parent device node
1385 * that is given as an argument
1386 */
1387 #if 0
1388 if (DeviceNode->Parent != ParentDeviceNode)
1389 {
1390 /*
1391 * Stop the traversal immediately and indicate unsuccessful operation
1392 */
1393 DPRINT("Stop\n");
1394 return STATUS_UNSUCCESSFUL;
1395 }
1396 #endif
1397
1398 if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED) &&
1399 !IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) &&
1400 !IopDeviceNodeHasFlag(DeviceNode, DNF_STARTED))
1401 {
1402 PMODULE_OBJECT ModuleObject;
1403 PDRIVER_OBJECT DriverObject;
1404
1405 Status = IopLoadServiceModule(&DeviceNode->ServiceName, &ModuleObject);
1406 if (NT_SUCCESS(Status))
1407 {
1408 Status = IopInitializeDriverModule(DeviceNode, ModuleObject, FALSE, &DriverObject);
1409 if (NT_SUCCESS(Status))
1410 {
1411 /* Attach lower level filter drivers. */
1412 IopAttachFilterDrivers(DeviceNode, TRUE);
1413 /* Initialize the function driver for the device node */
1414 Status = IopInitializeDevice(DeviceNode, DriverObject);
1415 if (NT_SUCCESS(Status))
1416 {
1417 IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
1418 /* Attach upper level filter drivers. */
1419 IopAttachFilterDrivers(DeviceNode, FALSE);
1420 }
1421 }
1422 }
1423 else
1424 {
1425 /*
1426 * Don't disable when trying to load only boot drivers
1427 */
1428 if (!BootDrivers)
1429 {
1430 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
1431 IopDeviceNodeSetFlag(DeviceNode, DNF_START_FAILED);
1432 }
1433 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1434 CPRINT("Initialization of service %S failed (Status %x)\n",
1435 DeviceNode->ServiceName.Buffer, Status);
1436 }
1437 } else
1438 {
1439 DPRINT("Service %S is disabled or already initialized\n",
1440 DeviceNode->ServiceName.Buffer);
1441 }
1442
1443 return STATUS_SUCCESS;
1444 }
1445
1446 /*
1447 * IopActionInitAllServices
1448 *
1449 * Initialize the service for all (direct) child nodes of a parent node. This
1450 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
1451 */
1452
1453 NTSTATUS
1454 IopActionInitAllServices(
1455 PDEVICE_NODE DeviceNode,
1456 PVOID Context)
1457 {
1458 return IopActionInitChildServices(DeviceNode, Context, FALSE);
1459 }
1460
1461 /*
1462 * IopActionInitBootServices
1463 *
1464 * Initialize the boot start services for all (direct) child nodes of a
1465 * parent node. This function just calls IopActionInitChildServices with
1466 * BootDrivers = TRUE.
1467 */
1468
1469 NTSTATUS
1470 IopActionInitBootServices(
1471 PDEVICE_NODE DeviceNode,
1472 PVOID Context)
1473 {
1474 return IopActionInitChildServices(DeviceNode, Context, TRUE);
1475 }
1476
1477 /*
1478 * IopInitializePnpServices
1479 *
1480 * Initialize services for discovered children
1481 *
1482 * Parameters
1483 * DeviceNode
1484 * Top device node to start initializing services.
1485 *
1486 * BootDrivers
1487 * When set to TRUE, only drivers marked as boot start will
1488 * be loaded. Otherwise, all drivers will be loaded.
1489 *
1490 * Return Value
1491 * Status
1492 */
1493
1494 NTSTATUS
1495 IopInitializePnpServices(
1496 IN PDEVICE_NODE DeviceNode,
1497 IN BOOLEAN BootDrivers)
1498 {
1499 DEVICETREE_TRAVERSE_CONTEXT Context;
1500
1501 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode, BootDrivers);
1502
1503 if (BootDrivers)
1504 {
1505 IopInitDeviceTreeTraverseContext(
1506 &Context,
1507 DeviceNode,
1508 IopActionInitBootServices,
1509 DeviceNode);
1510 } else
1511 {
1512 IopInitDeviceTreeTraverseContext(
1513 &Context,
1514 DeviceNode,
1515 IopActionInitAllServices,
1516 DeviceNode);
1517 }
1518
1519 return IopTraverseDeviceTree(&Context);
1520 }
1521
1522
1523 NTSTATUS
1524 IopInvalidateDeviceRelations(
1525 IN PDEVICE_NODE DeviceNode,
1526 IN DEVICE_RELATION_TYPE Type)
1527 {
1528 DEVICETREE_TRAVERSE_CONTEXT Context;
1529 PDEVICE_RELATIONS DeviceRelations;
1530 IO_STATUS_BLOCK IoStatusBlock;
1531 PDEVICE_NODE ChildDeviceNode;
1532 IO_STACK_LOCATION Stack;
1533 BOOL BootDrivers;
1534 OBJECT_ATTRIBUTES ObjectAttributes;
1535 UNICODE_STRING LinkName;
1536 HANDLE Handle;
1537 NTSTATUS Status;
1538 ULONG i;
1539
1540 DPRINT("DeviceNode %x\n", DeviceNode);
1541
1542 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1543
1544 Stack.Parameters.QueryDeviceRelations.Type = Type/*BusRelations*/;
1545
1546 Status = IopInitiatePnpIrp(
1547 DeviceNode->PhysicalDeviceObject,
1548 &IoStatusBlock,
1549 IRP_MN_QUERY_DEVICE_RELATIONS,
1550 &Stack);
1551 if (!NT_SUCCESS(Status))
1552 {
1553 DPRINT("IopInitiatePnpIrp() failed\n");
1554 return Status;
1555 }
1556
1557 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
1558
1559 if ((!DeviceRelations) || (DeviceRelations->Count <= 0))
1560 {
1561 DPRINT("No PDOs\n");
1562 if (DeviceRelations)
1563 {
1564 ExFreePool(DeviceRelations);
1565 }
1566 return STATUS_SUCCESS;
1567 }
1568
1569 DPRINT("Got %d PDOs\n", DeviceRelations->Count);
1570
1571 /*
1572 * Create device nodes for all discovered devices
1573 */
1574
1575 for (i = 0; i < DeviceRelations->Count; i++)
1576 {
1577 Status = IopCreateDeviceNode(
1578 DeviceNode,
1579 DeviceRelations->Objects[i],
1580 &ChildDeviceNode);
1581 DeviceNode->Flags |= DNF_ENUMERATED;
1582 if (!NT_SUCCESS(Status))
1583 {
1584 DPRINT("No resources\n");
1585 for (i = 0; i < DeviceRelations->Count; i++)
1586 ObDereferenceObject(DeviceRelations->Objects[i]);
1587 ExFreePool(DeviceRelations);
1588 return STATUS_INSUFFICIENT_RESOURCES;
1589 }
1590 }
1591 ExFreePool(DeviceRelations);
1592
1593 /*
1594 * Retrieve information about all discovered children from the bus driver
1595 */
1596
1597 IopInitDeviceTreeTraverseContext(
1598 &Context,
1599 DeviceNode,
1600 IopActionInterrogateDeviceStack,
1601 DeviceNode);
1602
1603 Status = IopTraverseDeviceTree(&Context);
1604 if (!NT_SUCCESS(Status))
1605 {
1606 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status);
1607 return Status;
1608 }
1609
1610 /*
1611 * Retrieve configuration from the registry for discovered children
1612 */
1613
1614 IopInitDeviceTreeTraverseContext(
1615 &Context,
1616 DeviceNode,
1617 IopActionConfigureChildServices,
1618 DeviceNode);
1619
1620 Status = IopTraverseDeviceTree(&Context);
1621 if (!NT_SUCCESS(Status))
1622 {
1623 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status);
1624 return Status;
1625 }
1626
1627 /*
1628 * Get the state of the system boot. If the \\SystemRoot link isn't
1629 * created yet, we will assume that it's possible to load only boot
1630 * drivers.
1631 */
1632
1633 RtlInitUnicodeString(&LinkName, L"\\SystemRoot");
1634
1635 InitializeObjectAttributes(
1636 &ObjectAttributes,
1637 &LinkName,
1638 0,
1639 NULL,
1640 NULL);
1641
1642 Status = NtOpenFile(
1643 &Handle,
1644 FILE_ALL_ACCESS,
1645 &ObjectAttributes,
1646 &IoStatusBlock,
1647 0,
1648 0);
1649
1650 BootDrivers = NT_SUCCESS(Status) ? FALSE : TRUE;
1651
1652 NtClose(Handle);
1653
1654 /*
1655 * Initialize services for discovered children. Only boot drivers will
1656 * be loaded from boot driver!
1657 */
1658
1659 Status = IopInitializePnpServices(DeviceNode, BootDrivers);
1660 if (!NT_SUCCESS(Status))
1661 {
1662 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status);
1663 return Status;
1664 }
1665
1666 return STATUS_SUCCESS;
1667 }
1668
1669
1670 VOID INIT_FUNCTION
1671 PnpInit(VOID)
1672 {
1673 PDEVICE_OBJECT Pdo;
1674 NTSTATUS Status;
1675
1676 DPRINT("PnpInit()\n");
1677
1678 KeInitializeSpinLock(&IopDeviceTreeLock);
1679
1680 /*
1681 * Create root device node
1682 */
1683
1684 Status = IopCreateDriverObject(&IopRootDriverObject, NULL, FALSE, NULL, 0);
1685 if (!NT_SUCCESS(Status))
1686 {
1687 CPRINT("IoCreateDriverObject() failed\n");
1688 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
1689 }
1690
1691 Status = IoCreateDevice(IopRootDriverObject, 0, NULL, FILE_DEVICE_CONTROLLER,
1692 0, FALSE, &Pdo);
1693 if (!NT_SUCCESS(Status))
1694 {
1695 CPRINT("IoCreateDevice() failed\n");
1696 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
1697 }
1698
1699 Status = IopCreateDeviceNode(NULL, Pdo, &IopRootDeviceNode);
1700 if (!NT_SUCCESS(Status))
1701 {
1702 CPRINT("Insufficient resources\n");
1703 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
1704 }
1705
1706 IopRootDeviceNode->PhysicalDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
1707 PnpRootDriverEntry(IopRootDriverObject, NULL);
1708 IopRootDriverObject->DriverExtension->AddDevice(
1709 IopRootDriverObject,
1710 IopRootDeviceNode->PhysicalDeviceObject);
1711 }
1712
1713 /* EOF */