Use W32API for NTOSKRNL.
[reactos.git] / reactos / ntoskrnl / io / pnpmgr.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/pnpmgr.c
5 * PURPOSE: Initializes the PnP manager
6 *
7 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #include <ddk/wdmguid.h>
14
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* FIXME: Header mess */
19 #undef DeviceCapabilities
20
21 /* GLOBALS *******************************************************************/
22
23 PDEVICE_NODE IopRootDeviceNode;
24 KSPIN_LOCK IopDeviceTreeLock;
25
26 /* DATA **********************************************************************/
27
28 PDRIVER_OBJECT IopRootDriverObject;
29
30 /* FUNCTIONS *****************************************************************/
31
32 PDEVICE_NODE FASTCALL
33 IopGetDeviceNode(
34 PDEVICE_OBJECT DeviceObject)
35 {
36 return DeviceObject->DeviceObjectExtension->DeviceNode;
37 }
38
39 /*
40 * @implemented
41 */
42 VOID
43 STDCALL
44 IoInvalidateDeviceRelations(
45 IN PDEVICE_OBJECT DeviceObject,
46 IN DEVICE_RELATION_TYPE Type)
47 {
48 IopInvalidateDeviceRelations(IopGetDeviceNode(DeviceObject), Type);
49 }
50
51 /*
52 * @unimplemented
53 */
54 NTSTATUS
55 STDCALL
56 IoGetDeviceProperty(
57 IN PDEVICE_OBJECT DeviceObject,
58 IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
59 IN ULONG BufferLength,
60 OUT PVOID PropertyBuffer,
61 OUT PULONG ResultLength)
62 {
63 PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
64 ULONG Length;
65 PVOID Data = NULL;
66 PWSTR Ptr;
67
68 DPRINT("IoGetDeviceProperty(%x %d)\n", DeviceObject, DeviceProperty);
69
70 if (DeviceNode == NULL)
71 return STATUS_INVALID_DEVICE_REQUEST;
72
73 switch (DeviceProperty)
74 {
75 case DevicePropertyBusNumber:
76 Length = sizeof(ULONG);
77 Data = &DeviceNode->ChildBusNumber;
78 break;
79
80 /* Complete, untested */
81 case DevicePropertyBusTypeGuid:
82 *ResultLength = 39 * sizeof(WCHAR);
83 if (BufferLength < (39 * sizeof(WCHAR)))
84 return STATUS_BUFFER_TOO_SMALL;
85 swprintf((PWSTR)PropertyBuffer,
86 L"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
87 DeviceNode->BusTypeGuid.Data1,
88 DeviceNode->BusTypeGuid.Data2,
89 DeviceNode->BusTypeGuid.Data3,
90 DeviceNode->BusTypeGuid.Data4[0],
91 DeviceNode->BusTypeGuid.Data4[1],
92 DeviceNode->BusTypeGuid.Data4[2],
93 DeviceNode->BusTypeGuid.Data4[3],
94 DeviceNode->BusTypeGuid.Data4[4],
95 DeviceNode->BusTypeGuid.Data4[5],
96 DeviceNode->BusTypeGuid.Data4[6],
97 DeviceNode->BusTypeGuid.Data4[7]);
98 return STATUS_SUCCESS;
99
100 case DevicePropertyLegacyBusType:
101 Length = sizeof(INTERFACE_TYPE);
102 Data = &DeviceNode->ChildInterfaceType;
103 break;
104
105 case DevicePropertyAddress:
106 Length = sizeof(ULONG);
107 Data = &DeviceNode->Address;
108 break;
109
110 // case DevicePropertyUINumber:
111 // if (DeviceNode->CapabilityFlags == NULL)
112 // return STATUS_INVALID_DEVICE_REQUEST;
113 // Length = sizeof(ULONG);
114 // Data = &DeviceNode->CapabilityFlags->UINumber;
115 // break;
116
117 case DevicePropertyClassName:
118 case DevicePropertyClassGuid:
119 case DevicePropertyDriverKeyName:
120 case DevicePropertyManufacturer:
121 case DevicePropertyFriendlyName:
122 case DevicePropertyHardwareID:
123 case DevicePropertyCompatibleIDs:
124 case DevicePropertyDeviceDescription:
125 case DevicePropertyLocationInformation:
126 case DevicePropertyUINumber:
127 {
128 LPWSTR RegistryPropertyName, KeyNameBuffer;
129 UNICODE_STRING KeyName, ValueName;
130 OBJECT_ATTRIBUTES ObjectAttributes;
131 KEY_VALUE_PARTIAL_INFORMATION *ValueInformation;
132 ULONG ValueInformationLength;
133 HANDLE KeyHandle;
134 NTSTATUS Status;
135
136 switch (DeviceProperty)
137 {
138 case DevicePropertyClassName:
139 RegistryPropertyName = L"Class"; break;
140 case DevicePropertyClassGuid:
141 RegistryPropertyName = L"ClassGuid"; break;
142 case DevicePropertyDriverKeyName:
143 RegistryPropertyName = L"Driver"; break;
144 case DevicePropertyManufacturer:
145 RegistryPropertyName = L"Mfg"; break;
146 case DevicePropertyFriendlyName:
147 RegistryPropertyName = L"FriendlyName"; break;
148 case DevicePropertyHardwareID:
149 RegistryPropertyName = L"HardwareID"; break;
150 case DevicePropertyCompatibleIDs:
151 RegistryPropertyName = L"CompatibleIDs"; break;
152 case DevicePropertyDeviceDescription:
153 RegistryPropertyName = L"DeviceDesc"; break;
154 case DevicePropertyLocationInformation:
155 RegistryPropertyName = L"LocationInformation"; break;
156 case DevicePropertyUINumber:
157 RegistryPropertyName = L"UINumber"; break;
158 default:
159 RegistryPropertyName = NULL; break;
160 }
161
162 KeyNameBuffer = ExAllocatePool(PagedPool,
163 (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
164
165 DPRINT("KeyNameBuffer: %x, value %S\n",
166 KeyNameBuffer, RegistryPropertyName);
167
168 if (KeyNameBuffer == NULL)
169 return STATUS_INSUFFICIENT_RESOURCES;
170
171 wcscpy(KeyNameBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
172 wcscat(KeyNameBuffer, DeviceNode->InstancePath.Buffer);
173 RtlInitUnicodeString(&KeyName, KeyNameBuffer);
174 InitializeObjectAttributes(&ObjectAttributes, &KeyName,
175 OBJ_CASE_INSENSITIVE, NULL, NULL);
176
177 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
178 ExFreePool(KeyNameBuffer);
179 if (!NT_SUCCESS(Status))
180 return Status;
181
182 RtlInitUnicodeString(&ValueName, RegistryPropertyName);
183 ValueInformationLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,
184 Data[0]) + BufferLength;
185 ValueInformation = ExAllocatePool(PagedPool, ValueInformationLength);
186 if (ValueInformation == NULL)
187 {
188 ZwClose(KeyHandle);
189 return STATUS_INSUFFICIENT_RESOURCES;
190 }
191
192 Status = ZwQueryValueKey(KeyHandle, &ValueName,
193 KeyValuePartialInformation, ValueInformation,
194 ValueInformationLength,
195 &ValueInformationLength);
196 *ResultLength = ValueInformation->DataLength;
197 ZwClose(KeyHandle);
198
199 if (ValueInformation->DataLength > BufferLength)
200 Status = STATUS_BUFFER_TOO_SMALL;
201
202 if (!NT_SUCCESS(Status))
203 {
204 ExFreePool(ValueInformation);
205 return Status;
206 }
207
208 /* FIXME: Verify the value (NULL-terminated, correct format). */
209
210 RtlCopyMemory(PropertyBuffer, ValueInformation->Data,
211 ValueInformation->DataLength);
212 ExFreePool(ValueInformation);
213
214 return STATUS_SUCCESS;
215 }
216
217 case DevicePropertyBootConfiguration:
218 Length = 0;
219 if (DeviceNode->BootResources->Count != 0)
220 {
221 Length = CM_RESOURCE_LIST_SIZE(DeviceNode->BootResources);
222 }
223 Data = &DeviceNode->BootResources;
224 break;
225
226 /* FIXME: use a translated boot configuration instead */
227 case DevicePropertyBootConfigurationTranslated:
228 Length = 0;
229 if (DeviceNode->BootResources->Count != 0)
230 {
231 Length = CM_RESOURCE_LIST_SIZE(DeviceNode->BootResources);
232 }
233 Data = &DeviceNode->BootResources;
234 break;
235
236 case DevicePropertyEnumeratorName:
237 Ptr = wcschr(DeviceNode->InstancePath.Buffer, L'\\');
238 if (Ptr != NULL)
239 {
240 Length = (ULONG)((ULONG_PTR)Ptr - (ULONG_PTR)DeviceNode->InstancePath.Buffer) + sizeof(WCHAR);
241 Data = DeviceNode->InstancePath.Buffer;
242 }
243 else
244 {
245 Length = 0;
246 Data = NULL;
247 }
248 break;
249
250 case DevicePropertyPhysicalDeviceObjectName:
251 Length = DeviceNode->InstancePath.Length + sizeof(WCHAR);
252 Data = DeviceNode->InstancePath.Buffer;
253 break;
254
255 default:
256 return STATUS_INVALID_PARAMETER_2;
257 }
258
259 *ResultLength = Length;
260 if (BufferLength < Length)
261 return STATUS_BUFFER_TOO_SMALL;
262 RtlCopyMemory(PropertyBuffer, Data, Length);
263
264 /* Terminate the string */
265 if (DeviceProperty == DevicePropertyEnumeratorName
266 || DeviceProperty == DevicePropertyPhysicalDeviceObjectName)
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 * @name IoOpenDeviceRegistryKey
287 *
288 * Open a registry key unique for a specified driver or device instance.
289 *
290 * @param DeviceObject Device to get the registry key for.
291 * @param DevInstKeyType Type of the key to return.
292 * @param DesiredAccess Access mask (eg. KEY_READ | KEY_WRITE).
293 * @param DevInstRegKey Handle to the opened registry key on
294 * successful return.
295 *
296 * @return Status.
297 *
298 * @implemented
299 */
300 NTSTATUS
301 STDCALL
302 IoOpenDeviceRegistryKey(
303 IN PDEVICE_OBJECT DeviceObject,
304 IN ULONG DevInstKeyType,
305 IN ACCESS_MASK DesiredAccess,
306 OUT PHANDLE DevInstRegKey)
307 {
308 static WCHAR RootKeyName[] =
309 L"\\Registry\\Machine\\System\\CurrentControlSet\\";
310 static WCHAR ProfileKeyName[] =
311 L"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
312 static WCHAR ClassKeyName[] = L"Control\\Class\\";
313 static WCHAR EnumKeyName[] = L"Enum\\";
314 static WCHAR DeviceParametersKeyName[] = L"Device Parameters\\";
315 ULONG KeyNameLength;
316 LPWSTR KeyNameBuffer;
317 UNICODE_STRING KeyName;
318 ULONG DriverKeyLength;
319 OBJECT_ATTRIBUTES ObjectAttributes;
320 PDEVICE_NODE DeviceNode = NULL;
321 NTSTATUS Status;
322
323 if ((DevInstKeyType & (PLUGPLAY_REGKEY_DEVICE | PLUGPLAY_REGKEY_DRIVER)) == 0)
324 return STATUS_INVALID_PARAMETER;
325
326 /*
327 * Calculate the length of the base key name. This is the full
328 * name for driver key or the name excluding "Device Parameters"
329 * subkey for device key.
330 */
331
332 KeyNameLength = sizeof(RootKeyName);
333 if (DevInstKeyType & PLUGPLAY_REGKEY_CURRENT_HWPROFILE)
334 KeyNameLength += sizeof(ProfileKeyName) - sizeof(UNICODE_NULL);
335 if (DevInstKeyType & PLUGPLAY_REGKEY_DRIVER)
336 {
337 KeyNameLength += sizeof(ClassKeyName) - sizeof(UNICODE_NULL);
338 Status = IoGetDeviceProperty(DeviceObject, DevicePropertyDriverKeyName,
339 0, NULL, &DriverKeyLength);
340 if (Status != STATUS_BUFFER_TOO_SMALL)
341 return Status;
342 KeyNameLength += DriverKeyLength;
343 }
344 else
345 {
346 DeviceNode = IopGetDeviceNode(DeviceObject);
347 KeyNameLength += sizeof(EnumKeyName) - sizeof(UNICODE_NULL) +
348 DeviceNode->InstancePath.Length;
349 }
350
351 /*
352 * Now allocate the buffer for the key name...
353 */
354
355 KeyNameBuffer = ExAllocatePool(PagedPool, KeyNameLength);
356 if (KeyNameBuffer == NULL)
357 return STATUS_INSUFFICIENT_RESOURCES;
358
359 KeyName.Length = 0;
360 KeyName.MaximumLength = KeyNameLength;
361 KeyName.Buffer = KeyNameBuffer;
362
363 /*
364 * ...and build the key name.
365 */
366
367 KeyName.Length += sizeof(RootKeyName) - sizeof(UNICODE_NULL);
368 RtlCopyMemory(KeyNameBuffer, RootKeyName, KeyName.Length);
369
370 if (DevInstKeyType & PLUGPLAY_REGKEY_CURRENT_HWPROFILE)
371 RtlAppendUnicodeToString(&KeyName, ProfileKeyName);
372
373 if (DevInstKeyType & PLUGPLAY_REGKEY_DRIVER)
374 {
375 RtlAppendUnicodeToString(&KeyName, ClassKeyName);
376 Status = IoGetDeviceProperty(DeviceObject, DevicePropertyDriverKeyName,
377 DriverKeyLength, KeyNameBuffer +
378 (KeyName.Length / sizeof(WCHAR)),
379 &DriverKeyLength);
380 if (!NT_SUCCESS(Status))
381 {
382 ExFreePool(KeyNameBuffer);
383 return Status;
384 }
385 KeyName.Length += DriverKeyLength - sizeof(UNICODE_NULL);
386 }
387 else
388 {
389 RtlAppendUnicodeToString(&KeyName, EnumKeyName);
390 Status = RtlAppendUnicodeStringToString(&KeyName, &DeviceNode->InstancePath);
391 if (DeviceNode->InstancePath.Length == 0)
392 {
393 ExFreePool(KeyNameBuffer);
394 return Status;
395 }
396 }
397
398 /*
399 * Open the base key.
400 */
401
402 InitializeObjectAttributes(&ObjectAttributes, &KeyName,
403 OBJ_CASE_INSENSITIVE, NULL, NULL);
404 Status = ZwOpenKey(DevInstRegKey, DesiredAccess, &ObjectAttributes);
405 ExFreePool(KeyNameBuffer);
406
407 /*
408 * For driver key we're done now. Also if the base key doesn't
409 * exist we can bail out with error...
410 */
411
412 if ((DevInstKeyType & PLUGPLAY_REGKEY_DRIVER) || !NT_SUCCESS(Status))
413 return Status;
414
415 /*
416 * Let's go further. For device key we must open "Device Parameters"
417 * subkey and create it if it doesn't exist yet.
418 */
419
420 RtlInitUnicodeString(&KeyName, DeviceParametersKeyName);
421 InitializeObjectAttributes(&ObjectAttributes, &KeyName,
422 OBJ_CASE_INSENSITIVE, *DevInstRegKey, NULL);
423 Status = ZwCreateKey(DevInstRegKey, DesiredAccess, &ObjectAttributes,
424 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
425 ZwClose(ObjectAttributes.RootDirectory);
426
427 return Status;
428 }
429
430 /*
431 * @unimplemented
432 */
433 VOID
434 STDCALL
435 IoRequestDeviceEject(
436 IN PDEVICE_OBJECT PhysicalDeviceObject
437 )
438 {
439 UNIMPLEMENTED;
440 }
441
442
443 BOOLEAN
444 IopCreateUnicodeString(
445 PUNICODE_STRING Destination,
446 PWSTR Source,
447 POOL_TYPE PoolType)
448 {
449 ULONG Length;
450
451 if (!Source)
452 {
453 RtlInitUnicodeString(Destination, NULL);
454 return TRUE;
455 }
456
457 Length = (wcslen(Source) + 1) * sizeof(WCHAR);
458
459 Destination->Buffer = ExAllocatePool(PoolType, Length);
460
461 if (Destination->Buffer == NULL)
462 {
463 return FALSE;
464 }
465
466 RtlCopyMemory(Destination->Buffer, Source, Length);
467
468 Destination->MaximumLength = Length;
469
470 Destination->Length = Length - sizeof(WCHAR);
471
472 return TRUE;
473 }
474
475 NTSTATUS
476 IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject)
477 {
478 KIRQL OldIrql;
479
480 if (PopSystemPowerDeviceNode)
481 {
482 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
483 *DeviceObject = PopSystemPowerDeviceNode->PhysicalDeviceObject;
484 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
485
486 return STATUS_SUCCESS;
487 }
488
489 return STATUS_UNSUCCESSFUL;
490 }
491
492 /*
493 * DESCRIPTION
494 * Creates a device node
495 *
496 * ARGUMENTS
497 * ParentNode = Pointer to parent device node
498 * PhysicalDeviceObject = Pointer to PDO for device object. Pass NULL
499 * to have the root device node create one
500 * (eg. for legacy drivers)
501 * DeviceNode = Pointer to storage for created device node
502 *
503 * RETURN VALUE
504 * Status
505 */
506 NTSTATUS
507 IopCreateDeviceNode(PDEVICE_NODE ParentNode,
508 PDEVICE_OBJECT PhysicalDeviceObject,
509 PDEVICE_NODE *DeviceNode)
510 {
511 PDEVICE_NODE Node;
512 NTSTATUS Status;
513 KIRQL OldIrql;
514
515 DPRINT("ParentNode %x PhysicalDeviceObject %x\n",
516 ParentNode, PhysicalDeviceObject);
517
518 Node = (PDEVICE_NODE)ExAllocatePool(NonPagedPool, sizeof(DEVICE_NODE));
519 if (!Node)
520 {
521 return STATUS_INSUFFICIENT_RESOURCES;
522 }
523
524 RtlZeroMemory(Node, sizeof(DEVICE_NODE));
525
526 if (!PhysicalDeviceObject)
527 {
528 Status = PnpRootCreateDevice(&PhysicalDeviceObject);
529 if (!NT_SUCCESS(Status))
530 {
531 ExFreePool(Node);
532 return Status;
533 }
534
535 /* This is for drivers passed on the command line to ntoskrnl.exe */
536 IopDeviceNodeSetFlag(Node, DNF_STARTED);
537 IopDeviceNodeSetFlag(Node, DNF_LEGACY_DRIVER);
538 }
539
540 Node->PhysicalDeviceObject = PhysicalDeviceObject;
541
542 PhysicalDeviceObject->DeviceObjectExtension->DeviceNode = Node;
543
544 if (ParentNode)
545 {
546 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
547 Node->Parent = ParentNode;
548 Node->NextSibling = ParentNode->Child;
549 if (ParentNode->Child != NULL)
550 {
551 ParentNode->Child->PrevSibling = Node;
552 }
553 ParentNode->Child = Node;
554 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
555 }
556
557 *DeviceNode = Node;
558
559 return STATUS_SUCCESS;
560 }
561
562 NTSTATUS
563 IopFreeDeviceNode(PDEVICE_NODE DeviceNode)
564 {
565 KIRQL OldIrql;
566
567 /* All children must be deleted before a parent is deleted */
568 ASSERT(!DeviceNode->Child);
569
570 KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
571
572 ASSERT(DeviceNode->PhysicalDeviceObject);
573
574 ObDereferenceObject(DeviceNode->PhysicalDeviceObject);
575
576 /* Unlink from parent if it exists */
577
578 if ((DeviceNode->Parent) && (DeviceNode->Parent->Child == DeviceNode))
579 {
580 DeviceNode->Parent->Child = DeviceNode->NextSibling;
581 }
582
583 /* Unlink from sibling list */
584
585 if (DeviceNode->PrevSibling)
586 {
587 DeviceNode->PrevSibling->NextSibling = DeviceNode->NextSibling;
588 }
589
590 if (DeviceNode->NextSibling)
591 {
592 DeviceNode->NextSibling->PrevSibling = DeviceNode->PrevSibling;
593 }
594
595 KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
596
597 RtlFreeUnicodeString(&DeviceNode->InstancePath);
598
599 RtlFreeUnicodeString(&DeviceNode->ServiceName);
600
601 if (DeviceNode->ResourceList)
602 {
603 ExFreePool(DeviceNode->ResourceList);
604 }
605
606 if (DeviceNode->ResourceListTranslated)
607 {
608 ExFreePool(DeviceNode->ResourceListTranslated);
609 }
610
611 if (DeviceNode->ResourceRequirements)
612 {
613 ExFreePool(DeviceNode->ResourceRequirements);
614 }
615
616 if (DeviceNode->BootResources)
617 {
618 ExFreePool(DeviceNode->BootResources);
619 }
620
621 ExFreePool(DeviceNode);
622
623 return STATUS_SUCCESS;
624 }
625
626 NTSTATUS
627 IopInitiatePnpIrp(
628 PDEVICE_OBJECT DeviceObject,
629 PIO_STATUS_BLOCK IoStatusBlock,
630 ULONG MinorFunction,
631 PIO_STACK_LOCATION Stack OPTIONAL)
632 {
633 PDEVICE_OBJECT TopDeviceObject;
634 PIO_STACK_LOCATION IrpSp;
635 NTSTATUS Status;
636 KEVENT Event;
637 PIRP Irp;
638
639 /* Always call the top of the device stack */
640 TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
641
642 KeInitializeEvent(
643 &Event,
644 NotificationEvent,
645 FALSE);
646
647 Irp = IoBuildSynchronousFsdRequest(
648 IRP_MJ_PNP,
649 TopDeviceObject,
650 NULL,
651 0,
652 NULL,
653 &Event,
654 IoStatusBlock);
655
656 /* PNP IRPs are always initialized with a status code of
657 STATUS_NOT_IMPLEMENTED */
658 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
659 Irp->IoStatus.Information = 0;
660
661 IrpSp = IoGetNextIrpStackLocation(Irp);
662 IrpSp->MinorFunction = MinorFunction;
663
664 if (Stack)
665 {
666 RtlMoveMemory(
667 &IrpSp->Parameters,
668 &Stack->Parameters,
669 sizeof(Stack->Parameters));
670 }
671
672 Status = IoCallDriver(TopDeviceObject, Irp);
673 if (Status == STATUS_PENDING)
674 {
675 KeWaitForSingleObject(
676 &Event,
677 Executive,
678 KernelMode,
679 FALSE,
680 NULL);
681 Status = IoStatusBlock->Status;
682 }
683
684 ObDereferenceObject(TopDeviceObject);
685
686 return Status;
687 }
688
689
690 NTSTATUS
691 IopTraverseDeviceTreeNode(
692 PDEVICETREE_TRAVERSE_CONTEXT Context)
693 {
694 PDEVICE_NODE ParentDeviceNode;
695 PDEVICE_NODE ChildDeviceNode;
696 NTSTATUS Status;
697
698 /* Copy context data so we don't overwrite it in subsequent calls to this function */
699 ParentDeviceNode = Context->DeviceNode;
700
701 /* Call the action routine */
702 Status = (Context->Action)(ParentDeviceNode, Context->Context);
703 if (!NT_SUCCESS(Status))
704 {
705 return Status;
706 }
707
708 /* Traversal of all children nodes */
709 for (ChildDeviceNode = ParentDeviceNode->Child;
710 ChildDeviceNode != NULL;
711 ChildDeviceNode = ChildDeviceNode->NextSibling)
712 {
713 /* Pass the current device node to the action routine */
714 Context->DeviceNode = ChildDeviceNode;
715
716 Status = IopTraverseDeviceTreeNode(Context);
717 if (!NT_SUCCESS(Status))
718 {
719 return Status;
720 }
721 }
722
723 return Status;
724 }
725
726
727 NTSTATUS
728 IopTraverseDeviceTree(
729 PDEVICETREE_TRAVERSE_CONTEXT Context)
730 {
731 NTSTATUS Status;
732
733 DPRINT("Context %x\n", Context);
734
735 DPRINT("IopTraverseDeviceTree(DeviceNode %x FirstDeviceNode %x Action %x Context %x)\n",
736 Context->DeviceNode, Context->FirstDeviceNode, Context->Action, Context->Context);
737
738 /* Start from the specified device node */
739 Context->DeviceNode = Context->FirstDeviceNode;
740
741 /* Recursively traverse the device tree */
742 Status = IopTraverseDeviceTreeNode(Context);
743 if (Status == STATUS_UNSUCCESSFUL)
744 {
745 /* The action routine just wanted to terminate the traversal with status
746 code STATUS_SUCCESS */
747 Status = STATUS_SUCCESS;
748 }
749
750 return Status;
751 }
752
753
754 static NTSTATUS
755 IopCreateDeviceKeyPath(PWSTR Path,
756 PHANDLE Handle)
757 {
758 OBJECT_ATTRIBUTES ObjectAttributes;
759 WCHAR KeyBuffer[MAX_PATH];
760 UNICODE_STRING KeyName;
761 HANDLE KeyHandle;
762 NTSTATUS Status;
763 PWCHAR Current;
764 PWCHAR Next;
765
766 *Handle = NULL;
767
768 if (_wcsnicmp(Path, L"\\Registry\\", 10) != 0)
769 {
770 return STATUS_INVALID_PARAMETER;
771 }
772
773 wcsncpy (KeyBuffer, Path, MAX_PATH-1);
774
775 /* Skip \\Registry\\ */
776 Current = KeyBuffer;
777 Current = wcschr (Current, L'\\') + 1;
778 Current = wcschr (Current, L'\\') + 1;
779
780 while (TRUE)
781 {
782 Next = wcschr (Current, L'\\');
783 if (Next == NULL)
784 {
785 /* The end */
786 }
787 else
788 {
789 *Next = 0;
790 }
791
792 RtlInitUnicodeString (&KeyName, KeyBuffer);
793 InitializeObjectAttributes (&ObjectAttributes,
794 &KeyName,
795 OBJ_CASE_INSENSITIVE,
796 NULL,
797 NULL);
798
799 DPRINT("Create '%S'\n", KeyName.Buffer);
800
801 Status = ZwCreateKey (&KeyHandle,
802 KEY_ALL_ACCESS,
803 &ObjectAttributes,
804 0,
805 NULL,
806 0,
807 NULL);
808 if (!NT_SUCCESS (Status))
809 {
810 DPRINT ("ZwCreateKey() failed with status %x\n", Status);
811 return Status;
812 }
813
814 if (Next == NULL)
815 {
816 *Handle = KeyHandle;
817 return STATUS_SUCCESS;
818 }
819 else
820 {
821 ZwClose (KeyHandle);
822 *Next = L'\\';
823 }
824
825 Current = Next + 1;
826 }
827
828 return STATUS_UNSUCCESSFUL;
829 }
830
831
832 static NTSTATUS
833 IopSetDeviceInstanceData(HANDLE InstanceKey,
834 PDEVICE_NODE DeviceNode)
835 {
836 OBJECT_ATTRIBUTES ObjectAttributes;
837 UNICODE_STRING KeyName;
838 HANDLE LogConfKey;
839 ULONG ResCount;
840 ULONG ListSize;
841 NTSTATUS Status;
842
843 DPRINT("IopSetDeviceInstanceData() called\n");
844
845 /* Create the 'LogConf' key */
846 RtlInitUnicodeString(&KeyName,
847 L"LogConf");
848 InitializeObjectAttributes(&ObjectAttributes,
849 &KeyName,
850 OBJ_CASE_INSENSITIVE,
851 InstanceKey,
852 NULL);
853 Status = ZwCreateKey(&LogConfKey,
854 KEY_ALL_ACCESS,
855 &ObjectAttributes,
856 0,
857 NULL,
858 0,
859 NULL);
860 if (NT_SUCCESS(Status))
861 {
862 /* Set 'BootConfig' value */
863 if (DeviceNode->BootResources != NULL)
864 {
865 ResCount = DeviceNode->BootResources->Count;
866 if (ResCount != 0)
867 {
868 ListSize = CM_RESOURCE_LIST_SIZE(DeviceNode->BootResources);
869
870 RtlInitUnicodeString(&KeyName,
871 L"BootConfig");
872 Status = ZwSetValueKey(LogConfKey,
873 &KeyName,
874 0,
875 REG_RESOURCE_LIST,
876 &DeviceNode->BootResources,
877 ListSize);
878 }
879 }
880
881 /* Set 'BasicConfigVector' value */
882 if (DeviceNode->ResourceRequirements != NULL &&
883 DeviceNode->ResourceRequirements->ListSize != 0)
884 {
885 RtlInitUnicodeString(&KeyName,
886 L"BasicConfigVector");
887 Status = ZwSetValueKey(LogConfKey,
888 &KeyName,
889 0,
890 REG_RESOURCE_REQUIREMENTS_LIST,
891 DeviceNode->ResourceRequirements,
892 DeviceNode->ResourceRequirements->ListSize);
893 }
894
895 ZwClose(LogConfKey);
896 }
897
898 #if 0
899 if (DeviceNode->PhysicalDeviceObject != NULL)
900 {
901 /* Create the 'Control' key */
902 RtlInitUnicodeString(&KeyName,
903 L"Control");
904 InitializeObjectAttributes(&ObjectAttributes,
905 &KeyName,
906 OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
907 InstanceKey,
908 NULL);
909 Status = ZwCreateKey(&LogConfKey,
910 KEY_ALL_ACCESS,
911 &ObjectAttributes,
912 0,
913 NULL,
914 REG_OPTION_VOLATILE,
915 NULL);
916 if (NT_SUCCESS(Status))
917 {
918 ULONG Reference = (ULONG)DeviceNode->PhysicalDeviceObject;
919 RtlInitUnicodeString(&KeyName,
920 L"DeviceReference");
921 Status = ZwSetValueKey(LogConfKey,
922 &KeyName,
923 0,
924 REG_DWORD,
925 &Reference,
926 sizeof(PVOID));
927
928 ZwClose(LogConfKey);
929 }
930 }
931 #endif
932
933 DPRINT("IopSetDeviceInstanceData() done\n");
934
935 return STATUS_SUCCESS;
936 }
937
938
939 NTSTATUS
940 IopAssignDeviceResources(
941 PDEVICE_NODE DeviceNode)
942 {
943 PIO_RESOURCE_LIST ResourceList;
944 PIO_RESOURCE_DESCRIPTOR ResourceDescriptor;
945 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw, DescriptorTranslated;
946 ULONG NumberOfResources = 0;
947 ULONG i;
948 NTSTATUS Status;
949
950 /* Fill DeviceNode->ResourceList and DeviceNode->ResourceListTranslated;
951 * by using DeviceNode->ResourceRequirements */
952
953 if (!DeviceNode->ResourceRequirements
954 || DeviceNode->ResourceRequirements->AlternativeLists == 0)
955 {
956 DeviceNode->ResourceList = DeviceNode->ResourceListTranslated = NULL;
957 return STATUS_SUCCESS;
958 }
959
960 /* FIXME: that's here that PnP arbiter should go */
961 /* Actually, simply use resource list #0 as assigned resource list */
962 ResourceList = &DeviceNode->ResourceRequirements->List[0];
963 if (ResourceList->Version != 1 || ResourceList->Revision != 1)
964 {
965 Status = STATUS_REVISION_MISMATCH;
966 goto ByeBye;
967 }
968
969 DeviceNode->ResourceList = ExAllocatePool(PagedPool,
970 sizeof(CM_RESOURCE_LIST) + ResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
971 if (!DeviceNode->ResourceList)
972 {
973 Status = STATUS_INSUFFICIENT_RESOURCES;
974 goto ByeBye;
975 }
976
977 DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool,
978 sizeof(CM_RESOURCE_LIST) + ResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
979 if (!DeviceNode->ResourceListTranslated)
980 {
981 Status = STATUS_INSUFFICIENT_RESOURCES;
982 goto ByeBye;
983 }
984
985 DeviceNode->ResourceList->Count = 1;
986 DeviceNode->ResourceList->List[0].InterfaceType = DeviceNode->ResourceRequirements->InterfaceType;
987 DeviceNode->ResourceList->List[0].BusNumber = DeviceNode->ResourceRequirements->BusNumber;
988 DeviceNode->ResourceList->List[0].PartialResourceList.Version = 1;
989 DeviceNode->ResourceList->List[0].PartialResourceList.Revision = 1;
990
991 DeviceNode->ResourceListTranslated->Count = 1;
992 DeviceNode->ResourceListTranslated->List[0].InterfaceType = DeviceNode->ResourceRequirements->InterfaceType;
993 DeviceNode->ResourceListTranslated->List[0].BusNumber = DeviceNode->ResourceRequirements->BusNumber;
994 DeviceNode->ResourceListTranslated->List[0].PartialResourceList.Version = 1;
995 DeviceNode->ResourceListTranslated->List[0].PartialResourceList.Revision = 1;
996
997 for (i = 0; i < ResourceList->Count; i++)
998 {
999 ResourceDescriptor = &ResourceList->Descriptors[i];
1000
1001 if (ResourceDescriptor->Option == 0 || ResourceDescriptor->Option == IO_RESOURCE_PREFERRED)
1002 {
1003 DescriptorRaw = &DeviceNode->ResourceList->List[0].PartialResourceList.PartialDescriptors[NumberOfResources];
1004 DescriptorTranslated = &DeviceNode->ResourceListTranslated->List[0].PartialResourceList.PartialDescriptors[NumberOfResources];
1005 NumberOfResources++;
1006
1007 /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */
1008 DescriptorRaw->Type = DescriptorTranslated->Type = ResourceDescriptor->Type;
1009 DescriptorRaw->ShareDisposition = DescriptorTranslated->ShareDisposition = ResourceDescriptor->ShareDisposition;
1010 DescriptorRaw->Flags = DescriptorTranslated->Flags = ResourceDescriptor->Flags;
1011 switch (ResourceDescriptor->Type)
1012 {
1013 case CmResourceTypePort:
1014 {
1015 ULONG AddressSpace = 0; /* IO space */
1016 DescriptorRaw->u.Port.Start = ResourceDescriptor->u.Port.MinimumAddress;
1017 DescriptorRaw->u.Port.Length = DescriptorTranslated->u.Port.Length
1018 = ResourceDescriptor->u.Port.Length;
1019 if (!HalTranslateBusAddress(
1020 DeviceNode->ResourceRequirements->InterfaceType,
1021 DeviceNode->ResourceRequirements->BusNumber,
1022 DescriptorRaw->u.Port.Start,
1023 &AddressSpace,
1024 &DescriptorTranslated->u.Port.Start))
1025 {
1026 Status = STATUS_UNSUCCESSFUL;
1027 goto ByeBye;
1028 }
1029 break;
1030 }
1031 case CmResourceTypeInterrupt:
1032 {
1033 DescriptorRaw->u.Interrupt.Level = 0;
1034 /* FIXME: if IRQ 9 is in the possible range, use it.
1035 * This should be a PCI device */
1036 if (ResourceDescriptor->u.Interrupt.MinimumVector <= 9
1037 && ResourceDescriptor->u.Interrupt.MaximumVector >= 9)
1038 DescriptorRaw->u.Interrupt.Vector = 9;
1039 else
1040 DescriptorRaw->u.Interrupt.Vector = ResourceDescriptor->u.Interrupt.MinimumVector;
1041
1042 DescriptorTranslated->u.Interrupt.Vector = HalGetInterruptVector(
1043 DeviceNode->ResourceRequirements->InterfaceType,
1044 DeviceNode->ResourceRequirements->BusNumber,
1045 DescriptorRaw->u.Interrupt.Level,
1046 DescriptorRaw->u.Interrupt.Vector,
1047 (PKIRQL)&DescriptorTranslated->u.Interrupt.Level,
1048 &DescriptorRaw->u.Interrupt.Affinity);
1049 DescriptorTranslated->u.Interrupt.Affinity = DescriptorRaw->u.Interrupt.Affinity;
1050 break;
1051 }
1052 case CmResourceTypeMemory:
1053 {
1054 ULONG AddressSpace = 1; /* Memory space */
1055 DescriptorRaw->u.Memory.Start = ResourceDescriptor->u.Memory.MinimumAddress;
1056 DescriptorRaw->u.Memory.Length = DescriptorTranslated->u.Memory.Length
1057 = ResourceDescriptor->u.Memory.Length;
1058 if (!HalTranslateBusAddress(
1059 DeviceNode->ResourceRequirements->InterfaceType,
1060 DeviceNode->ResourceRequirements->BusNumber,
1061 DescriptorRaw->u.Memory.Start,
1062 &AddressSpace,
1063 &DescriptorTranslated->u.Memory.Start))
1064 {
1065 Status = STATUS_UNSUCCESSFUL;
1066 goto ByeBye;
1067 }
1068 break;
1069 }
1070 case CmResourceTypeDma:
1071 {
1072 DescriptorRaw->u.Dma.Channel = DescriptorTranslated->u.Dma.Channel
1073 = ResourceDescriptor->u.Dma.MinimumChannel;
1074 DescriptorRaw->u.Dma.Port = DescriptorTranslated->u.Dma.Port
1075 = 0; /* FIXME */
1076 DescriptorRaw->u.Dma.Reserved1 = DescriptorTranslated->u.Dma.Reserved1
1077 = 0;
1078 break;
1079 }
1080 /*case CmResourceTypeBusNumber:
1081 {
1082 DescriptorRaw->u.BusNumber.Start = DescriptorTranslated->u.BusNumber.Start
1083 = ResourceDescriptor->u.BusNumber.MinBusNumber;
1084 DescriptorRaw->u.BusNumber.Length = DescriptorTranslated->u.BusNumber.Length
1085 = ResourceDescriptor->u.BusNumber.Length;
1086 DescriptorRaw->u.BusNumber.Reserved = DescriptorTranslated->u.BusNumber.Reserved
1087 = ResourceDescriptor->u.BusNumber.Reserved;
1088 break;
1089 }*/
1090 /*CmResourceTypeDevicePrivate:
1091 case CmResourceTypePcCardConfig:
1092 case CmResourceTypeMfCardConfig:
1093 {
1094 RtlCopyMemory(
1095 &DescriptorRaw->u.DevicePrivate,
1096 &ResourceDescriptor->u.DevicePrivate,
1097 sizeof(ResourceDescriptor->u.DevicePrivate));
1098 RtlCopyMemory(
1099 &DescriptorTranslated->u.DevicePrivate,
1100 &ResourceDescriptor->u.DevicePrivate,
1101 sizeof(ResourceDescriptor->u.DevicePrivate));
1102 break;
1103 }*/
1104 default:
1105 DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor->Type);
1106 NumberOfResources--;
1107 }
1108 }
1109
1110 }
1111
1112 DeviceNode->ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
1113 DeviceNode->ResourceListTranslated->List[0].PartialResourceList.Count = NumberOfResources;
1114
1115 return STATUS_SUCCESS;
1116
1117 ByeBye:
1118 if (DeviceNode->ResourceList)
1119 {
1120 ExFreePool(DeviceNode->ResourceList);
1121 DeviceNode->ResourceList = NULL;
1122 }
1123 if (DeviceNode->ResourceListTranslated)
1124 {
1125 ExFreePool(DeviceNode->ResourceListTranslated);
1126 DeviceNode->ResourceListTranslated = NULL;
1127 }
1128
1129 return Status;
1130 }
1131
1132
1133 /*
1134 * IopActionInterrogateDeviceStack
1135 *
1136 * Retrieve information for all (direct) child nodes of a parent node.
1137 *
1138 * Parameters
1139 * DeviceNode
1140 * Pointer to device node.
1141 * Context
1142 * Pointer to parent node to retrieve child node information for.
1143 *
1144 * Remarks
1145 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1146 * when we reach a device node which is not a direct child of the device
1147 * node for which we retrieve information of child nodes for. Any errors
1148 * that occur is logged instead so that all child services have a chance
1149 * of being interrogated.
1150 */
1151
1152 NTSTATUS
1153 IopActionInterrogateDeviceStack(
1154 PDEVICE_NODE DeviceNode,
1155 PVOID Context)
1156 {
1157 IO_STATUS_BLOCK IoStatusBlock;
1158 PDEVICE_NODE ParentDeviceNode;
1159 WCHAR InstancePath[MAX_PATH];
1160 IO_STACK_LOCATION Stack;
1161 NTSTATUS Status;
1162 PWSTR KeyBuffer;
1163 PWSTR Ptr;
1164 USHORT Length;
1165 USHORT TotalLength;
1166 HANDLE InstanceKey = NULL;
1167 UNICODE_STRING ValueName;
1168 DEVICE_CAPABILITIES DeviceCapabilities;
1169
1170 DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode, Context);
1171 DPRINT("PDO %x\n", DeviceNode->PhysicalDeviceObject);
1172
1173 ParentDeviceNode = (PDEVICE_NODE)Context;
1174
1175 /*
1176 * We are called for the parent too, but we don't need to do special
1177 * handling for this node
1178 */
1179
1180 if (DeviceNode == ParentDeviceNode)
1181 {
1182 DPRINT("Success\n");
1183 return STATUS_SUCCESS;
1184 }
1185
1186 /*
1187 * Make sure this device node is a direct child of the parent device node
1188 * that is given as an argument
1189 */
1190
1191 if (DeviceNode->Parent != ParentDeviceNode)
1192 {
1193 /* Stop the traversal immediately and indicate successful operation */
1194 DPRINT("Stop\n");
1195 return STATUS_UNSUCCESSFUL;
1196 }
1197
1198 /*
1199 * FIXME: For critical errors, cleanup and disable device, but always
1200 * return STATUS_SUCCESS.
1201 */
1202
1203 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
1204
1205 Stack.Parameters.QueryId.IdType = BusQueryDeviceID;
1206 Status = IopInitiatePnpIrp(
1207 DeviceNode->PhysicalDeviceObject,
1208 &IoStatusBlock,
1209 IRP_MN_QUERY_ID,
1210 &Stack);
1211 if (NT_SUCCESS(Status))
1212 {
1213 /* Copy the device id string */
1214 wcscpy(InstancePath, (PWSTR)IoStatusBlock.Information);
1215
1216 /*
1217 * FIXME: Check for valid characters, if there is invalid characters
1218 * then bugcheck.
1219 */
1220 }
1221 else
1222 {
1223 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1224 }
1225
1226 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
1227
1228 Stack.Parameters.QueryId.IdType = BusQueryInstanceID;
1229 Status = IopInitiatePnpIrp(
1230 DeviceNode->PhysicalDeviceObject,
1231 &IoStatusBlock,
1232 IRP_MN_QUERY_ID,
1233 &Stack);
1234 if (NT_SUCCESS(Status))
1235 {
1236 /* Append the instance id string */
1237 wcscat(InstancePath, L"\\");
1238 wcscat(InstancePath, (PWSTR)IoStatusBlock.Information);
1239
1240 /*
1241 * FIXME: Check for valid characters, if there is invalid characters
1242 * then bugcheck
1243 */
1244 }
1245 else
1246 {
1247 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1248 }
1249
1250 RtlZeroMemory(&DeviceCapabilities, sizeof(DEVICE_CAPABILITIES));
1251 DeviceCapabilities.Size = sizeof(DEVICE_CAPABILITIES);
1252 DeviceCapabilities.Version = 1;
1253 DeviceCapabilities.Address = -1;
1254 DeviceCapabilities.UINumber = -1;
1255
1256 Stack.Parameters.DeviceCapabilities.Capabilities = &DeviceCapabilities;
1257 Status = IopInitiatePnpIrp(
1258 DeviceNode->PhysicalDeviceObject,
1259 &IoStatusBlock,
1260 IRP_MN_QUERY_CAPABILITIES,
1261 &Stack);
1262 if (NT_SUCCESS(Status))
1263 {
1264 }
1265 else
1266 {
1267 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1268 }
1269
1270 DeviceNode->CapabilityFlags = *(PULONG)((ULONG_PTR)&DeviceCapabilities + 4);
1271 DeviceNode->Address = DeviceCapabilities.Address;
1272
1273 if (!DeviceCapabilities.UniqueID)
1274 {
1275 DPRINT("Instance ID is not unique\n");
1276 /* FIXME: Add information from parent bus driver to InstancePath */
1277 }
1278
1279 if (!IopCreateUnicodeString(&DeviceNode->InstancePath, InstancePath, PagedPool))
1280 {
1281 DPRINT("No resources\n");
1282 /* FIXME: Cleanup and disable device */
1283 }
1284
1285 DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
1286
1287 /*
1288 * Create registry key for the instance id, if it doesn't exist yet
1289 */
1290 KeyBuffer = ExAllocatePool(
1291 PagedPool,
1292 (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
1293 wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1294 wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer);
1295 Status = IopCreateDeviceKeyPath(KeyBuffer,
1296 &InstanceKey);
1297 ExFreePool(KeyBuffer);
1298 if (!NT_SUCCESS(Status))
1299 {
1300 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
1301 }
1302
1303
1304 {
1305 /* Set 'Capabilities' value */
1306 RtlInitUnicodeString(&ValueName,
1307 L"Capabilities");
1308 Status = ZwSetValueKey(InstanceKey,
1309 &ValueName,
1310 0,
1311 REG_DWORD,
1312 (PVOID)&DeviceNode->CapabilityFlags,
1313 sizeof(ULONG));
1314
1315 /* Set 'UINumber' value */
1316 if (DeviceCapabilities.UINumber != (ULONG)-1)
1317 {
1318 RtlInitUnicodeString(&ValueName,
1319 L"UINumber");
1320 Status = ZwSetValueKey(InstanceKey,
1321 &ValueName,
1322 0,
1323 REG_DWORD,
1324 &DeviceCapabilities.UINumber,
1325 sizeof(ULONG));
1326 }
1327 }
1328
1329 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
1330
1331 Stack.Parameters.QueryId.IdType = BusQueryHardwareIDs;
1332 Status = IopInitiatePnpIrp(
1333 DeviceNode->PhysicalDeviceObject,
1334 &IoStatusBlock,
1335 IRP_MN_QUERY_ID,
1336 &Stack);
1337 if (NT_SUCCESS(Status))
1338 {
1339 /*
1340 * FIXME: Check for valid characters, if there is invalid characters
1341 * then bugcheck.
1342 */
1343 TotalLength = 0;
1344 Ptr = (PWSTR)IoStatusBlock.Information;
1345 DPRINT("Hardware IDs:\n");
1346 while (*Ptr)
1347 {
1348 DPRINT(" %S\n", Ptr);
1349 Length = wcslen(Ptr) + 1;
1350
1351 Ptr += Length;
1352 TotalLength += Length;
1353 }
1354 DPRINT("TotalLength: %hu\n", TotalLength);
1355 DPRINT("\n");
1356
1357 RtlInitUnicodeString(&ValueName,
1358 L"HardwareID");
1359 Status = ZwSetValueKey(InstanceKey,
1360 &ValueName,
1361 0,
1362 REG_MULTI_SZ,
1363 (PVOID)IoStatusBlock.Information,
1364 (TotalLength + 1) * sizeof(WCHAR));
1365 if (!NT_SUCCESS(Status))
1366 {
1367 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
1368 }
1369 }
1370 else
1371 {
1372 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1373 }
1374
1375 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1376
1377 Stack.Parameters.QueryId.IdType = BusQueryCompatibleIDs;
1378 Status = IopInitiatePnpIrp(
1379 DeviceNode->PhysicalDeviceObject,
1380 &IoStatusBlock,
1381 IRP_MN_QUERY_ID,
1382 &Stack);
1383 if (NT_SUCCESS(Status))
1384 {
1385 /*
1386 * FIXME: Check for valid characters, if there is invalid characters
1387 * then bugcheck.
1388 */
1389 TotalLength = 0;
1390 Ptr = (PWSTR)IoStatusBlock.Information;
1391 DPRINT("Compatible IDs:\n");
1392 while (*Ptr)
1393 {
1394 DPRINT(" %S\n", Ptr);
1395 Length = wcslen(Ptr) + 1;
1396
1397 Ptr += Length;
1398 TotalLength += Length;
1399 }
1400 DPRINT("TotalLength: %hu\n", TotalLength);
1401 DPRINT("\n");
1402
1403 RtlInitUnicodeString(&ValueName,
1404 L"CompatibleIDs");
1405 Status = ZwSetValueKey(InstanceKey,
1406 &ValueName,
1407 0,
1408 REG_MULTI_SZ,
1409 (PVOID)IoStatusBlock.Information,
1410 (TotalLength + 1) * sizeof(WCHAR));
1411 if (!NT_SUCCESS(Status))
1412 {
1413 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
1414 }
1415 }
1416 else
1417 {
1418 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1419 }
1420
1421
1422 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
1423
1424 Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextDescription;
1425 Stack.Parameters.QueryDeviceText.LocaleId = 0; /* FIXME */
1426 Status = IopInitiatePnpIrp(
1427 DeviceNode->PhysicalDeviceObject,
1428 &IoStatusBlock,
1429 IRP_MN_QUERY_DEVICE_TEXT,
1430 &Stack);
1431 if (NT_SUCCESS(Status))
1432 {
1433 RtlInitUnicodeString(&ValueName,
1434 L"DeviceDesc");
1435 Status = ZwSetValueKey(InstanceKey,
1436 &ValueName,
1437 0,
1438 REG_SZ,
1439 (PVOID)IoStatusBlock.Information,
1440 (wcslen((PWSTR)IoStatusBlock.Information) + 1) * sizeof(WCHAR));
1441 if (!NT_SUCCESS(Status))
1442 {
1443 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
1444 }
1445 }
1446 else
1447 {
1448 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1449 }
1450
1451 DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
1452
1453 Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextLocationInformation;
1454 Stack.Parameters.QueryDeviceText.LocaleId = 0; // FIXME
1455 Status = IopInitiatePnpIrp(
1456 DeviceNode->PhysicalDeviceObject,
1457 &IoStatusBlock,
1458 IRP_MN_QUERY_DEVICE_TEXT,
1459 &Stack);
1460 if (NT_SUCCESS(Status))
1461 {
1462 DPRINT("LocationInformation: %S\n", (PWSTR)IoStatusBlock.Information);
1463 RtlInitUnicodeString(&ValueName,
1464 L"LocationInformation");
1465 Status = ZwSetValueKey(InstanceKey,
1466 &ValueName,
1467 0,
1468 REG_SZ,
1469 (PVOID)IoStatusBlock.Information,
1470 (wcslen((PWSTR)IoStatusBlock.Information) + 1) * sizeof(WCHAR));
1471 if (!NT_SUCCESS(Status))
1472 {
1473 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
1474 }
1475 }
1476 else
1477 {
1478 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1479 }
1480
1481 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1482
1483 Status = IopInitiatePnpIrp(
1484 DeviceNode->PhysicalDeviceObject,
1485 &IoStatusBlock,
1486 IRP_MN_QUERY_BUS_INFORMATION,
1487 NULL);
1488 if (NT_SUCCESS(Status))
1489 {
1490 PPNP_BUS_INFORMATION BusInformation =
1491 (PPNP_BUS_INFORMATION)IoStatusBlock.Information;
1492
1493 DeviceNode->ChildBusNumber = BusInformation->BusNumber;
1494 DeviceNode->ChildInterfaceType = BusInformation->LegacyBusType;
1495 memcpy(&DeviceNode->BusTypeGuid,
1496 &BusInformation->BusTypeGuid,
1497 sizeof(GUID));
1498 ExFreePool(BusInformation);
1499 }
1500 else
1501 {
1502 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1503
1504 DeviceNode->ChildBusNumber = -1;
1505 DeviceNode->ChildInterfaceType = -1;
1506 memset(&DeviceNode->BusTypeGuid,
1507 0,
1508 sizeof(GUID));
1509 }
1510
1511 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1512
1513 Status = IopInitiatePnpIrp(
1514 DeviceNode->PhysicalDeviceObject,
1515 &IoStatusBlock,
1516 IRP_MN_QUERY_RESOURCES,
1517 NULL);
1518 if (NT_SUCCESS(Status))
1519 {
1520 DeviceNode->BootResources =
1521 (PCM_RESOURCE_LIST)IoStatusBlock.Information;
1522 DeviceNode->Flags |= DNF_HAS_BOOT_CONFIG;
1523 }
1524 else
1525 {
1526 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1527 DeviceNode->BootResources = NULL;
1528 }
1529
1530 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1531
1532 Status = IopInitiatePnpIrp(
1533 DeviceNode->PhysicalDeviceObject,
1534 &IoStatusBlock,
1535 IRP_MN_QUERY_RESOURCE_REQUIREMENTS,
1536 NULL);
1537 if (NT_SUCCESS(Status))
1538 {
1539 DeviceNode->ResourceRequirements =
1540 (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
1541 }
1542 else
1543 {
1544 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1545 DeviceNode->ResourceRequirements = NULL;
1546 }
1547
1548
1549 if (InstanceKey != NULL)
1550 {
1551 IopSetDeviceInstanceData(InstanceKey, DeviceNode);
1552 }
1553
1554 ZwClose(InstanceKey);
1555
1556 Status = IopAssignDeviceResources(DeviceNode);
1557 if (!NT_SUCCESS(Status))
1558 {
1559 DPRINT("IopAssignDeviceResources() failed (Status %x)\n", Status);
1560 }
1561
1562 DeviceNode->Flags |= DNF_PROCESSED;
1563
1564 /* Report the device to the user-mode pnp manager */
1565 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,
1566 &DeviceNode->InstancePath);
1567
1568 return STATUS_SUCCESS;
1569 }
1570
1571 /*
1572 * IopActionConfigureChildServices
1573 *
1574 * Retrieve configuration for all (direct) child nodes of a parent node.
1575 *
1576 * Parameters
1577 * DeviceNode
1578 * Pointer to device node.
1579 * Context
1580 * Pointer to parent node to retrieve child node configuration for.
1581 *
1582 * Remarks
1583 * We only return a status code indicating an error (STATUS_UNSUCCESSFUL)
1584 * when we reach a device node which is not a direct child of the device
1585 * node for which we configure child services for. Any errors that occur is
1586 * logged instead so that all child services have a chance of beeing
1587 * configured.
1588 */
1589
1590 NTSTATUS
1591 IopActionConfigureChildServices(
1592 PDEVICE_NODE DeviceNode,
1593 PVOID Context)
1594 {
1595 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1596 PDEVICE_NODE ParentDeviceNode;
1597 PUNICODE_STRING Service;
1598 NTSTATUS Status;
1599
1600 DPRINT("IopActionConfigureChildServices(%p, %p)\n", DeviceNode, Context);
1601
1602 ParentDeviceNode = (PDEVICE_NODE)Context;
1603
1604 /*
1605 * We are called for the parent too, but we don't need to do special
1606 * handling for this node
1607 */
1608 if (DeviceNode == ParentDeviceNode)
1609 {
1610 DPRINT("Success\n");
1611 return STATUS_SUCCESS;
1612 }
1613
1614 /*
1615 * Make sure this device node is a direct child of the parent device node
1616 * that is given as an argument
1617 */
1618 if (DeviceNode->Parent != ParentDeviceNode)
1619 {
1620 /* Stop the traversal immediately and indicate successful operation */
1621 DPRINT("Stop\n");
1622 return STATUS_UNSUCCESSFUL;
1623 }
1624
1625 if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED))
1626 {
1627 WCHAR RegKeyBuffer[MAX_PATH];
1628 UNICODE_STRING RegKey;
1629
1630 RegKey.Length = 0;
1631 RegKey.MaximumLength = sizeof(RegKeyBuffer);
1632 RegKey.Buffer = RegKeyBuffer;
1633
1634 /*
1635 * Retrieve configuration from Enum key
1636 */
1637
1638 Service = &DeviceNode->ServiceName;
1639
1640 RtlZeroMemory(QueryTable, sizeof(QueryTable));
1641 RtlInitUnicodeString(Service, NULL);
1642
1643 QueryTable[0].Name = L"Service";
1644 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
1645 QueryTable[0].EntryContext = Service;
1646
1647 RtlAppendUnicodeToString(&RegKey, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
1648 RtlAppendUnicodeStringToString(&RegKey, &DeviceNode->InstancePath);
1649
1650 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
1651 RegKey.Buffer, QueryTable, NULL, NULL);
1652
1653 if (!NT_SUCCESS(Status))
1654 {
1655 DPRINT("RtlQueryRegistryValues() failed (Status %x)\n", Status);
1656 /* FIXME: Log the error */
1657 CPRINT("Could not retrieve configuration for device %S (Status %x)\n",
1658 DeviceNode->InstancePath.Buffer, Status);
1659 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
1660 return STATUS_SUCCESS;
1661 }
1662
1663 if (Service->Buffer == NULL)
1664 {
1665 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
1666 return STATUS_SUCCESS;
1667 }
1668
1669 DPRINT("Got Service %S\n", Service->Buffer);
1670 }
1671
1672 return STATUS_SUCCESS;
1673 }
1674
1675 /*
1676 * IopActionInitChildServices
1677 *
1678 * Initialize the service for all (direct) child nodes of a parent node
1679 *
1680 * Parameters
1681 * DeviceNode
1682 * Pointer to device node.
1683 * Context
1684 * Pointer to parent node to initialize child node services for.
1685 * BootDrivers
1686 * Load only driver marked as boot start.
1687 *
1688 * Remarks
1689 * If the driver image for a service is not loaded and initialized
1690 * it is done here too. We only return a status code indicating an
1691 * error (STATUS_UNSUCCESSFUL) when we reach a device node which is
1692 * not a direct child of the device node for which we initialize
1693 * child services for. Any errors that occur is logged instead so
1694 * that all child services have a chance of being initialized.
1695 */
1696
1697 NTSTATUS
1698 IopActionInitChildServices(
1699 PDEVICE_NODE DeviceNode,
1700 PVOID Context,
1701 BOOLEAN BootDrivers)
1702 {
1703 PDEVICE_NODE ParentDeviceNode;
1704 NTSTATUS Status;
1705
1706 DPRINT("IopActionInitChildServices(%p, %p, %d)\n", DeviceNode, Context,
1707 BootDrivers);
1708
1709 ParentDeviceNode = (PDEVICE_NODE)Context;
1710
1711 /*
1712 * We are called for the parent too, but we don't need to do special
1713 * handling for this node
1714 */
1715 if (DeviceNode == ParentDeviceNode)
1716 {
1717 DPRINT("Success\n");
1718 return STATUS_SUCCESS;
1719 }
1720
1721 /*
1722 * Make sure this device node is a direct child of the parent device node
1723 * that is given as an argument
1724 */
1725 #if 0
1726 if (DeviceNode->Parent != ParentDeviceNode)
1727 {
1728 /*
1729 * Stop the traversal immediately and indicate unsuccessful operation
1730 */
1731 DPRINT("Stop\n");
1732 return STATUS_UNSUCCESSFUL;
1733 }
1734 #endif
1735
1736 if (!IopDeviceNodeHasFlag(DeviceNode, DNF_DISABLED) &&
1737 !IopDeviceNodeHasFlag(DeviceNode, DNF_ADDED) &&
1738 !IopDeviceNodeHasFlag(DeviceNode, DNF_STARTED))
1739 {
1740 PMODULE_OBJECT ModuleObject;
1741 PDRIVER_OBJECT DriverObject;
1742
1743 Status = IopLoadServiceModule(&DeviceNode->ServiceName, &ModuleObject);
1744 if (NT_SUCCESS(Status) || Status == STATUS_IMAGE_ALREADY_LOADED)
1745 {
1746 if (Status != STATUS_IMAGE_ALREADY_LOADED)
1747 Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
1748 &DeviceNode->ServiceName, FALSE, &DriverObject);
1749 else
1750 {
1751 /* get existing DriverObject pointer */
1752 Status = IopGetDriverObject(
1753 &DriverObject,
1754 &DeviceNode->ServiceName,
1755 FALSE);
1756 }
1757 if (NT_SUCCESS(Status))
1758 {
1759 /* Attach lower level filter drivers. */
1760 IopAttachFilterDrivers(DeviceNode, TRUE);
1761 /* Initialize the function driver for the device node */
1762 Status = IopInitializeDevice(DeviceNode, DriverObject);
1763 if (NT_SUCCESS(Status))
1764 {
1765 /* Attach upper level filter drivers. */
1766 IopAttachFilterDrivers(DeviceNode, FALSE);
1767 IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
1768
1769 Status = IopStartDevice(DeviceNode);
1770 }
1771 }
1772 }
1773 else
1774 {
1775 /*
1776 * Don't disable when trying to load only boot drivers
1777 */
1778 if (!BootDrivers)
1779 {
1780 IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
1781 IopDeviceNodeSetFlag(DeviceNode, DNF_START_FAILED);
1782 }
1783 /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
1784 CPRINT("Initialization of service %S failed (Status %x)\n",
1785 DeviceNode->ServiceName.Buffer, Status);
1786 }
1787 } else
1788 {
1789 DPRINT("Service %S is disabled or already initialized\n",
1790 DeviceNode->ServiceName.Buffer);
1791 }
1792
1793 return STATUS_SUCCESS;
1794 }
1795
1796 /*
1797 * IopActionInitAllServices
1798 *
1799 * Initialize the service for all (direct) child nodes of a parent node. This
1800 * function just calls IopActionInitChildServices with BootDrivers = FALSE.
1801 */
1802
1803 NTSTATUS
1804 IopActionInitAllServices(
1805 PDEVICE_NODE DeviceNode,
1806 PVOID Context)
1807 {
1808 return IopActionInitChildServices(DeviceNode, Context, FALSE);
1809 }
1810
1811 /*
1812 * IopActionInitBootServices
1813 *
1814 * Initialize the boot start services for all (direct) child nodes of a
1815 * parent node. This function just calls IopActionInitChildServices with
1816 * BootDrivers = TRUE.
1817 */
1818 NTSTATUS
1819 IopActionInitBootServices(
1820 PDEVICE_NODE DeviceNode,
1821 PVOID Context)
1822 {
1823 return IopActionInitChildServices(DeviceNode, Context, TRUE);
1824 }
1825
1826 /*
1827 * IopInitializePnpServices
1828 *
1829 * Initialize services for discovered children
1830 *
1831 * Parameters
1832 * DeviceNode
1833 * Top device node to start initializing services.
1834 *
1835 * BootDrivers
1836 * When set to TRUE, only drivers marked as boot start will
1837 * be loaded. Otherwise, all drivers will be loaded.
1838 *
1839 * Return Value
1840 * Status
1841 */
1842 NTSTATUS
1843 IopInitializePnpServices(
1844 IN PDEVICE_NODE DeviceNode,
1845 IN BOOLEAN BootDrivers)
1846 {
1847 DEVICETREE_TRAVERSE_CONTEXT Context;
1848
1849 DPRINT("IopInitializePnpServices(%p, %d)\n", DeviceNode, BootDrivers);
1850
1851 if (BootDrivers)
1852 {
1853 IopInitDeviceTreeTraverseContext(
1854 &Context,
1855 DeviceNode,
1856 IopActionInitBootServices,
1857 DeviceNode);
1858 }
1859 else
1860 {
1861 IopInitDeviceTreeTraverseContext(
1862 &Context,
1863 DeviceNode,
1864 IopActionInitAllServices,
1865 DeviceNode);
1866 }
1867
1868 return IopTraverseDeviceTree(&Context);
1869 }
1870
1871
1872 NTSTATUS
1873 IopInvalidateDeviceRelations(
1874 IN PDEVICE_NODE DeviceNode,
1875 IN DEVICE_RELATION_TYPE Type)
1876 {
1877 DEVICETREE_TRAVERSE_CONTEXT Context;
1878 PDEVICE_RELATIONS DeviceRelations;
1879 IO_STATUS_BLOCK IoStatusBlock;
1880 PDEVICE_NODE ChildDeviceNode;
1881 IO_STACK_LOCATION Stack;
1882 BOOL BootDrivers;
1883 OBJECT_ATTRIBUTES ObjectAttributes;
1884 UNICODE_STRING LinkName;
1885 HANDLE Handle;
1886 NTSTATUS Status;
1887 ULONG i;
1888
1889 DPRINT("DeviceNode %x\n", DeviceNode);
1890
1891 DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
1892
1893 Stack.Parameters.QueryDeviceRelations.Type = Type/*BusRelations*/;
1894
1895 Status = IopInitiatePnpIrp(
1896 DeviceNode->PhysicalDeviceObject,
1897 &IoStatusBlock,
1898 IRP_MN_QUERY_DEVICE_RELATIONS,
1899 &Stack);
1900 if (!NT_SUCCESS(Status))
1901 {
1902 DPRINT("IopInitiatePnpIrp() failed\n");
1903 return Status;
1904 }
1905
1906 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
1907
1908 if ((!DeviceRelations) || (DeviceRelations->Count <= 0))
1909 {
1910 DPRINT("No PDOs\n");
1911 if (DeviceRelations)
1912 {
1913 ExFreePool(DeviceRelations);
1914 }
1915 return STATUS_SUCCESS;
1916 }
1917
1918 DPRINT("Got %d PDOs\n", DeviceRelations->Count);
1919
1920 /*
1921 * Create device nodes for all discovered devices
1922 */
1923
1924 for (i = 0; i < DeviceRelations->Count; i++)
1925 {
1926 Status = IopCreateDeviceNode(
1927 DeviceNode,
1928 DeviceRelations->Objects[i],
1929 &ChildDeviceNode);
1930 DeviceNode->Flags |= DNF_ENUMERATED;
1931 if (!NT_SUCCESS(Status))
1932 {
1933 DPRINT("No resources\n");
1934 for (i = 0; i < DeviceRelations->Count; i++)
1935 ObDereferenceObject(DeviceRelations->Objects[i]);
1936 ExFreePool(DeviceRelations);
1937 return STATUS_INSUFFICIENT_RESOURCES;
1938 }
1939 }
1940 ExFreePool(DeviceRelations);
1941
1942 /*
1943 * Retrieve information about all discovered children from the bus driver
1944 */
1945
1946 IopInitDeviceTreeTraverseContext(
1947 &Context,
1948 DeviceNode,
1949 IopActionInterrogateDeviceStack,
1950 DeviceNode);
1951
1952 Status = IopTraverseDeviceTree(&Context);
1953 if (!NT_SUCCESS(Status))
1954 {
1955 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status);
1956 return Status;
1957 }
1958
1959 /*
1960 * Retrieve configuration from the registry for discovered children
1961 */
1962
1963 IopInitDeviceTreeTraverseContext(
1964 &Context,
1965 DeviceNode,
1966 IopActionConfigureChildServices,
1967 DeviceNode);
1968
1969 Status = IopTraverseDeviceTree(&Context);
1970 if (!NT_SUCCESS(Status))
1971 {
1972 DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status);
1973 return Status;
1974 }
1975
1976 /*
1977 * Get the state of the system boot. If the \\SystemRoot link isn't
1978 * created yet, we will assume that it's possible to load only boot
1979 * drivers.
1980 */
1981
1982 RtlInitUnicodeString(&LinkName, L"\\SystemRoot");
1983
1984 InitializeObjectAttributes(
1985 &ObjectAttributes,
1986 &LinkName,
1987 0,
1988 NULL,
1989 NULL);
1990
1991 Status = ZwOpenFile(
1992 &Handle,
1993 FILE_ALL_ACCESS,
1994 &ObjectAttributes,
1995 &IoStatusBlock,
1996 0,
1997 0);
1998 if(NT_SUCCESS(Status))
1999 {
2000 BootDrivers = FALSE;
2001 ZwClose(Handle);
2002 }
2003 else
2004 BootDrivers = TRUE;
2005
2006 /*
2007 * Initialize services for discovered children. Only boot drivers will
2008 * be loaded from boot driver!
2009 */
2010
2011 Status = IopInitializePnpServices(DeviceNode, BootDrivers);
2012 if (!NT_SUCCESS(Status))
2013 {
2014 DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status);
2015 return Status;
2016 }
2017
2018 return STATUS_SUCCESS;
2019 }
2020
2021
2022 static NTSTATUS INIT_FUNCTION
2023 IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode)
2024 {
2025 #if 0
2026 PWSTR KeyBuffer;
2027 HANDLE InstanceKey = NULL;
2028 NTSTATUS Status;
2029
2030 /* Create registry key for the instance id, if it doesn't exist yet */
2031 KeyBuffer = ExAllocatePool(PagedPool,
2032 (49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
2033 wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
2034 wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer);
2035 Status = IopCreateDeviceKeyPath(KeyBuffer,
2036 &InstanceKey);
2037 ExFreePool(KeyBuffer);
2038 if (!NT_SUCCESS(Status))
2039 {
2040 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
2041 return Status;
2042 }
2043
2044 /* FIXME: Set 'ConfigFlags' value */
2045
2046 ZwClose(InstanceKey);
2047
2048 return Status;
2049 #endif
2050 return STATUS_SUCCESS;
2051 }
2052
2053
2054 VOID INIT_FUNCTION
2055 PnpInit(VOID)
2056 {
2057 PDEVICE_OBJECT Pdo;
2058 NTSTATUS Status;
2059
2060 DPRINT("PnpInit()\n");
2061
2062 KeInitializeSpinLock(&IopDeviceTreeLock);
2063
2064 /* Initialize PnP-Event notification support */
2065 Status = IopInitPlugPlayEvents();
2066 if (!NT_SUCCESS(Status))
2067 {
2068 CPRINT("IopInitPlugPlayEvents() failed\n");
2069 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
2070 }
2071
2072 /*
2073 * Create root device node
2074 */
2075
2076 Status = IopCreateDriverObject(&IopRootDriverObject, NULL, 0, FALSE, NULL, 0);
2077 if (!NT_SUCCESS(Status))
2078 {
2079 CPRINT("IoCreateDriverObject() failed\n");
2080 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
2081 }
2082
2083 Status = IoCreateDevice(IopRootDriverObject, 0, NULL, FILE_DEVICE_CONTROLLER,
2084 0, FALSE, &Pdo);
2085 if (!NT_SUCCESS(Status))
2086 {
2087 CPRINT("IoCreateDevice() failed\n");
2088 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
2089 }
2090
2091 Status = IopCreateDeviceNode(NULL, Pdo, &IopRootDeviceNode);
2092 if (!NT_SUCCESS(Status))
2093 {
2094 CPRINT("Insufficient resources\n");
2095 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
2096 }
2097
2098 if (!IopCreateUnicodeString(&IopRootDeviceNode->InstancePath,
2099 L"HTREE\\ROOT\\0",
2100 PagedPool))
2101 {
2102 CPRINT("Failed to create the instance path!\n");
2103 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, STATUS_UNSUCCESSFUL, 0, 0, 0);
2104 }
2105
2106 /* Report the device to the user-mode pnp manager */
2107 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,
2108 &IopRootDeviceNode->InstancePath);
2109
2110 IopRootDeviceNode->PhysicalDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
2111 PnpRootDriverEntry(IopRootDriverObject, NULL);
2112 IopRootDriverObject->DriverExtension->AddDevice(
2113 IopRootDriverObject,
2114 IopRootDeviceNode->PhysicalDeviceObject);
2115 }
2116
2117
2118 VOID INIT_FUNCTION
2119 PnpInit2(VOID)
2120 {
2121 NTSTATUS Status;
2122
2123 /* Set root device instance data */
2124 Status = IopSetRootDeviceInstanceData(IopRootDeviceNode);
2125 if (!NT_SUCCESS(Status))
2126 {
2127 CPRINT("Failed to set instance data\n");
2128 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
2129 }
2130 }
2131
2132 /* EOF */