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