- replaced IopCreateUnicodeString with RtlCreateUnicodeString
[reactos.git] / reactos / ntoskrnl / io / pnproot.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/pnproot.c
6 * PURPOSE: PnP manager root device
7 *
8 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS *******************************************************************/
18
19 #define ENUM_NAME_ROOT L"Root"
20
21 /* DATA **********************************************************************/
22
23 typedef struct _PNPROOT_DEVICE
24 {
25 // Entry on device list
26 LIST_ENTRY ListEntry;
27 // Physical Device Object of device
28 PDEVICE_OBJECT Pdo;
29 // Service name
30 UNICODE_STRING ServiceName;
31 // Device ID
32 UNICODE_STRING DeviceID;
33 // Instance ID
34 UNICODE_STRING InstanceID;
35 // Device description
36 UNICODE_STRING DeviceDescription;
37 // Resource requirement list
38 PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList;
39 } PNPROOT_DEVICE, *PPNPROOT_DEVICE;
40
41 typedef enum
42 {
43 dsStopped,
44 dsStarted,
45 dsPaused,
46 dsRemoved,
47 dsSurpriseRemoved
48 } PNPROOT_DEVICE_STATE;
49
50
51 #include <pshpack1.h>
52
53 typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION
54 {
55 // Pointer to device object, this device extension is associated with
56 PDEVICE_OBJECT DeviceObject;
57 // Wether this device extension is for an FDO or PDO
58 BOOLEAN IsFDO;
59 // Wether the device is removed
60 BOOLEAN Removed;
61 // Current device power state for the device
62 DEVICE_POWER_STATE DevicePowerState;
63 } PNPROOT_COMMON_DEVICE_EXTENSION, *PPNPROOT_COMMON_DEVICE_EXTENSION;
64
65
66 /* Physical Device Object device extension for a child device */
67 typedef struct _PNPROOT_PDO_DEVICE_EXTENSION
68 {
69 // Common device data
70 PNPROOT_COMMON_DEVICE_EXTENSION Common;
71 // Device ID
72 UNICODE_STRING DeviceID;
73 // Instance ID
74 UNICODE_STRING InstanceID;
75 // Resource requirement list
76 PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList;
77 } PNPROOT_PDO_DEVICE_EXTENSION, *PPNPROOT_PDO_DEVICE_EXTENSION;
78
79
80 /* Functional Device Object device extension for the PCI driver device object */
81 typedef struct _PNPROOT_FDO_DEVICE_EXTENSION
82 {
83 // Common device data
84 PNPROOT_COMMON_DEVICE_EXTENSION Common;
85 // Physical Device Object
86 PDEVICE_OBJECT Pdo;
87 // Lower device object
88 PDEVICE_OBJECT Ldo;
89 // Current state of the driver
90 PNPROOT_DEVICE_STATE State;
91 // Namespace device list
92 LIST_ENTRY DeviceListHead;
93 // Number of (not removed) devices in device list
94 ULONG DeviceListCount;
95 // Lock for namespace device list
96 // FIXME: Use fast mutex instead?
97 KSPIN_LOCK DeviceListLock;
98 } PNPROOT_FDO_DEVICE_EXTENSION, *PPNPROOT_FDO_DEVICE_EXTENSION;
99
100 #include <poppack.h>
101
102
103
104 PDEVICE_OBJECT PnpRootDeviceObject;
105
106
107 /* FUNCTIONS *****************************************************************/
108
109 /* Physical Device Object routines */
110
111 NTSTATUS
112 PnpRootCreateDevice(
113 PDEVICE_OBJECT *PhysicalDeviceObject)
114 {
115 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
116 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
117 PPNPROOT_DEVICE Device;
118 NTSTATUS Status;
119
120 /* This function should be obsoleted soon */
121
122 DPRINT("Called\n");
123
124 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
125
126 Device = (PPNPROOT_DEVICE)ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
127 if (!Device)
128 return STATUS_INSUFFICIENT_RESOURCES;
129
130 RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
131
132 Status = IoCreateDevice(
133 PnpRootDeviceObject->DriverObject,
134 sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
135 NULL,
136 FILE_DEVICE_CONTROLLER,
137 FILE_AUTOGENERATED_DEVICE_NAME,
138 FALSE,
139 &Device->Pdo);
140 if (!NT_SUCCESS(Status)) {
141 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
142 ExFreePool(Device);
143 return Status;
144 }
145
146 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
147
148 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
149
150 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
151
152 PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
153
154 RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
155
156 PdoDeviceExtension->Common.IsFDO = FALSE;
157
158 PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
159
160 PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
161
162 if (!RtlCreateUnicodeString(
163 &PdoDeviceExtension->DeviceID,
164 ENUM_NAME_ROOT \
165 L"\\LEGACY_UNKNOWN"))
166 {
167 /* FIXME: */
168 DPRINT("RtlCreateUnicodeString() failed\n");
169 }
170
171 if (!RtlCreateUnicodeString(
172 &PdoDeviceExtension->InstanceID,
173 L"0000"))
174 {
175 /* FIXME: */
176 DPRINT("RtlCreateUnicodeString() failed\n");
177 }
178
179 ExInterlockedInsertTailList(
180 &DeviceExtension->DeviceListHead,
181 &Device->ListEntry,
182 &DeviceExtension->DeviceListLock);
183
184 DeviceExtension->DeviceListCount++;
185
186 *PhysicalDeviceObject = Device->Pdo;
187
188 return STATUS_SUCCESS;
189 }
190
191
192 NTSTATUS
193 PdoQueryId(
194 IN PDEVICE_OBJECT DeviceObject,
195 IN PIRP Irp,
196 PIO_STACK_LOCATION IrpSp)
197 {
198 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
199 UNICODE_STRING String;
200 NTSTATUS Status;
201
202 DPRINT("Called\n");
203
204 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
205
206 // Irp->IoStatus.Information = 0;
207
208 Status = STATUS_SUCCESS;
209
210 RtlInitUnicodeString(&String, NULL);
211
212 switch (IrpSp->Parameters.QueryId.IdType) {
213 case BusQueryDeviceID:
214 Status = RtlDuplicateUnicodeString(TRUE,
215 &DeviceExtension->DeviceID,
216 &String);
217
218 DPRINT("DeviceID: %wZ\n", &String);
219
220 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
221 break;
222
223 case BusQueryHardwareIDs:
224 case BusQueryCompatibleIDs:
225 Status = STATUS_NOT_IMPLEMENTED;
226 break;
227
228 case BusQueryInstanceID:
229 Status = RtlDuplicateUnicodeString(TRUE,
230 &DeviceExtension->InstanceID,
231 &String);
232
233 DPRINT("InstanceID: %S\n", String.Buffer);
234
235 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
236 break;
237
238 case BusQueryDeviceSerialNumber:
239 default:
240 Status = STATUS_NOT_IMPLEMENTED;
241 }
242
243 return Status;
244 }
245
246
247 NTSTATUS
248 PdoQueryResources(
249 IN PDEVICE_OBJECT DeviceObject,
250 IN PIRP Irp,
251 PIO_STACK_LOCATION IrpSp)
252 {
253 PCM_RESOURCE_LIST ResourceList;
254 ULONG ResourceListSize = FIELD_OFFSET(CM_RESOURCE_LIST, List);
255
256 ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
257 if (ResourceList == NULL)
258 return STATUS_INSUFFICIENT_RESOURCES;
259
260 ResourceList->Count = 0;
261
262 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
263
264 return STATUS_SUCCESS;
265 }
266
267
268 NTSTATUS
269 PdoQueryResourceRequirements(
270 IN PDEVICE_OBJECT DeviceObject,
271 IN PIRP Irp,
272 PIO_STACK_LOCATION IrpSp)
273 {
274 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
275 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
276 ULONG ResourceListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List);
277
278 DPRINT("Called\n");
279
280 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
281
282 if (DeviceExtension->ResourceRequirementsList == NULL)
283 {
284 /* Create an empty resource list */
285 ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
286 if (ResourceList == NULL)
287 return STATUS_INSUFFICIENT_RESOURCES;
288
289 RtlZeroMemory(ResourceList, ResourceListSize);
290 ResourceList->ListSize = ResourceListSize;
291
292 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
293 }
294 else
295 {
296 /* Copy existing resource requirement list */
297 ResourceList = ExAllocatePool(PagedPool, DeviceExtension->ResourceRequirementsList->ListSize);
298 if (ResourceList == NULL)
299 return STATUS_INSUFFICIENT_RESOURCES;
300
301 RtlCopyMemory(
302 ResourceList,
303 DeviceExtension->ResourceRequirementsList,
304 DeviceExtension->ResourceRequirementsList->ListSize);
305 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
306 }
307
308 return STATUS_SUCCESS;
309 }
310
311
312 /*
313 * FUNCTION: Handle Plug and Play IRPs for the child device
314 * ARGUMENTS:
315 * DeviceObject = Pointer to physical device object of the child device
316 * Irp = Pointer to IRP that should be handled
317 * RETURNS:
318 * Status
319 */
320 NTSTATUS
321 PnpRootPdoPnpControl(
322 PDEVICE_OBJECT DeviceObject,
323 PIRP Irp)
324 {
325 PIO_STACK_LOCATION IrpSp;
326 NTSTATUS Status;
327
328 DPRINT("Called\n");
329
330 Status = Irp->IoStatus.Status;
331
332 IrpSp = IoGetCurrentIrpStackLocation(Irp);
333
334 switch (IrpSp->MinorFunction) {
335 #if 0
336 case IRP_MN_QUERY_BUS_INFORMATION:
337 break;
338
339 case IRP_MN_QUERY_DEVICE_RELATIONS:
340 /* FIXME: Handle for TargetDeviceRelation */
341 break;
342 #endif
343
344 case IRP_MN_QUERY_ID:
345 Status = PdoQueryId(DeviceObject, Irp, IrpSp);
346 break;
347
348 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
349 Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
350 break;
351
352 case IRP_MN_QUERY_RESOURCES:
353 Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
354 break;
355
356 case IRP_MN_START_DEVICE:
357 case IRP_MN_QUERY_STOP_DEVICE:
358 case IRP_MN_CANCEL_STOP_DEVICE:
359 case IRP_MN_STOP_DEVICE:
360 case IRP_MN_QUERY_REMOVE_DEVICE:
361 case IRP_MN_CANCEL_REMOVE_DEVICE:
362 case IRP_MN_REMOVE_DEVICE:
363 case IRP_MN_SURPRISE_REMOVAL:
364 Status = STATUS_SUCCESS;
365 break;
366
367 default:
368 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
369 break;
370 }
371
372 Irp->IoStatus.Status = Status;
373 IoCompleteRequest(Irp, IO_NO_INCREMENT);
374
375 DPRINT("Leaving. Status 0x%X\n", Status);
376
377 return Status;
378 }
379
380
381 /*
382 * FUNCTION: Handle power management IRPs for the child device
383 * ARGUMENTS:
384 * DeviceObject = Pointer to physical device object of the child device
385 * Irp = Pointer to IRP that should be handled
386 * RETURNS:
387 * Status
388 */
389 NTSTATUS
390 PnpRootPdoPowerControl(
391 PDEVICE_OBJECT DeviceObject,
392 PIRP Irp)
393 {
394 PIO_STACK_LOCATION IrpSp;
395 NTSTATUS Status;
396
397 DPRINT("Called\n");
398
399 Status = Irp->IoStatus.Status;
400
401 IrpSp = IoGetCurrentIrpStackLocation(Irp);
402
403 switch (IrpSp->MinorFunction) {
404 default:
405 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
406 Status = STATUS_NOT_IMPLEMENTED;
407 break;
408 }
409
410 Irp->IoStatus.Status = Status;
411 IoCompleteRequest(Irp, IO_NO_INCREMENT);
412
413 DPRINT("Leaving. Status 0x%X\n", Status);
414
415 return Status;
416 }
417
418
419 /* Functional Device Object routines */
420
421 static NTSTATUS
422 PnpRootReadRegistryBinary(
423 IN PWSTR KeyName,
424 IN PWSTR ValueKeyName,
425 OUT PVOID* Buffer)
426 {
427 OBJECT_ATTRIBUTES ObjectAttributes;
428 UNICODE_STRING KeyNameU;
429 UNICODE_STRING ValueKeyNameU;
430 KEY_VALUE_PARTIAL_INFORMATION Size;
431 PKEY_VALUE_PARTIAL_INFORMATION Data = NULL;
432 ULONG DataSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION);
433 HANDLE KeyHandle;
434 NTSTATUS Status;
435
436 DPRINT("Called\n");
437
438 RtlInitUnicodeString(&KeyNameU, KeyName);
439 RtlInitUnicodeString(&ValueKeyNameU, ValueKeyName);
440
441 InitializeObjectAttributes(
442 &ObjectAttributes,
443 &KeyNameU,
444 OBJ_CASE_INSENSITIVE,
445 NULL, /* Root dir */
446 NULL); /* Security descriptor */
447 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
448 if (!NT_SUCCESS(Status))
449 {
450 DPRINT("ZwOpenKey() failed (Status 0x%08lx)\n", Status);
451 return Status;
452 }
453
454 Status = ZwQueryValueKey(
455 KeyHandle,
456 &ValueKeyNameU,
457 KeyValuePartialInformation,
458 &Size, DataSize,
459 &DataSize);
460 if (Status != STATUS_BUFFER_OVERFLOW)
461 {
462 DPRINT("ZwQueryValueKey() failed (Status 0x%08lx)\n", Status);
463 ZwClose(KeyHandle);
464 return Status;
465 }
466
467 while (Status == STATUS_BUFFER_OVERFLOW)
468 {
469 if (Data)
470 ExFreePoolWithTag(Data, TAG_PNP_ROOT);
471 Data = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, DataSize, TAG_PNP_ROOT);
472 if (!Data)
473 {
474 DPRINT("ExAllocatePoolWithTag() failed\n", Status);
475 ZwClose(KeyHandle);
476 return Status;
477 }
478
479 Status = ZwQueryValueKey(
480 KeyHandle,
481 &ValueKeyNameU,
482 KeyValuePartialInformation,
483 Data, DataSize,
484 &DataSize);
485 if (NT_SUCCESS(Status))
486 {
487 *Buffer = ExAllocatePoolWithTag(PagedPool, Data->DataLength, TAG_PNP_ROOT);
488 if (!*Buffer)
489 {
490 DPRINT("ExAllocatePoolWithTag() failed\n", Status);
491 ExFreePoolWithTag(Data, TAG_PNP_ROOT);
492 ZwClose(KeyHandle);
493 return Status;
494 }
495
496 RtlCopyMemory(
497 *Buffer,
498 Data->Data,
499 Data->DataLength);
500 break;
501 }
502 }
503
504 if (Data)
505 ExFreePoolWithTag(Data, TAG_PNP_ROOT);
506 ZwClose(KeyHandle);
507
508 return Status;
509 }
510
511 NTSTATUS
512 PnpRootFdoReadDeviceInfo(
513 PPNPROOT_DEVICE Device)
514 {
515 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
516 PUNICODE_STRING DeviceDesc;
517 WCHAR KeyName[MAX_PATH];
518 NTSTATUS Status;
519
520 DPRINT("Called\n");
521
522 /* Retrieve configuration from Enum key */
523
524 DeviceDesc = &Device->DeviceDescription;
525
526 wcscpy(KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
527 wcscat(KeyName, ENUM_NAME_ROOT);
528 wcscat(KeyName, L"\\");
529 wcscat(KeyName, Device->ServiceName.Buffer);
530 wcscat(KeyName, L"\\");
531 wcscat(KeyName, Device->InstanceID.Buffer);
532
533 DPRINT("KeyName %S\n", KeyName);
534
535 /* 1. Read informations in instance key */
536 RtlZeroMemory(QueryTable, sizeof(QueryTable));
537
538 RtlInitUnicodeString(DeviceDesc, NULL);
539
540 QueryTable[0].Name = L"DeviceDesc";
541 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
542 QueryTable[0].EntryContext = DeviceDesc;
543
544 Status = RtlQueryRegistryValues(
545 RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
546 KeyName,
547 QueryTable,
548 NULL,
549 NULL);
550
551 DPRINT("RtlQueryRegistryValues() returned status 0x%08lx\n", Status);
552
553 if (!NT_SUCCESS(Status))
554 {
555 /* FIXME: */
556 }
557
558 DPRINT("Got device description: %S\n", DeviceDesc->Buffer);
559
560 /* 2. Read informations in instance key, LogConf subkey */
561 RtlZeroMemory(QueryTable, sizeof(QueryTable));
562 wcscat(KeyName, L"\\LogConf");
563
564 Status = PnpRootReadRegistryBinary(
565 KeyName,
566 L"BasicConfigVector",
567 (PVOID*)&Device->ResourceRequirementsList);
568
569 DPRINT("PnpRootReadRegistryBinary() returned status 0x%08lx\n", Status);
570
571 if (!NT_SUCCESS(Status))
572 {
573 /* FIXME: */
574 }
575
576 return STATUS_SUCCESS;
577 }
578
579
580 NTSTATUS
581 PnpRootFdoEnumerateDevices(
582 PDEVICE_OBJECT DeviceObject)
583 {
584 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
585 OBJECT_ATTRIBUTES ObjectAttributes, SubKeyAttributes;
586 PKEY_BASIC_INFORMATION KeyInfo, SubKeyInfo;
587 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\" ENUM_NAME_ROOT);
588 UNICODE_STRING SubKeyName;
589 PPNPROOT_DEVICE Device;
590 WCHAR Buffer[MAX_PATH];
591 HANDLE KeyHandle, SubKeyHandle;
592 ULONG BufferSize;
593 ULONG ResultSize;
594 NTSTATUS Status;
595 ULONG Index1, Index2;
596
597 DPRINT("Called\n");
598
599 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
600
601 BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH+1) * sizeof(WCHAR);
602 KeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT);
603 if (!KeyInfo)
604 {
605 return STATUS_INSUFFICIENT_RESOURCES;
606 }
607 SubKeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT);
608 if (!SubKeyInfo)
609 {
610 ExFreePoolWithTag(KeyInfo, TAG_PNP_ROOT);
611 return STATUS_INSUFFICIENT_RESOURCES;
612 }
613
614 InitializeObjectAttributes(
615 &ObjectAttributes,
616 &KeyName,
617 OBJ_CASE_INSENSITIVE,
618 NULL,
619 NULL);
620
621 Status = ZwOpenKey(&KeyHandle, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes);
622 if (!NT_SUCCESS(Status))
623 {
624 DPRINT("ZwOpenKey() failed (Status 0x%08lx)\n", Status);
625 ExFreePoolWithTag(KeyInfo, TAG_PNP_ROOT);
626 ExFreePoolWithTag(SubKeyInfo, TAG_PNP_ROOT);
627 return Status;
628 }
629
630 /* FIXME: Disabled due to still using the old method of auto loading drivers e.g.
631 there are more entries in the list than found in the registry as some
632 drivers are passed on the command line */
633 // DeviceExtension->DeviceListCount = 0;
634
635 /* Devices are sub-sub-keys of 'KeyName'. KeyName is already opened as
636 * KeyHandle. We'll first do a first enumeration to have first level keys,
637 * and an inner one to have the real devices list.
638 */
639 Index1 = 0;
640
641 while (TRUE)
642 {
643 Status = ZwEnumerateKey(
644 KeyHandle,
645 Index1,
646 KeyBasicInformation,
647 KeyInfo,
648 BufferSize,
649 &ResultSize);
650 if (!NT_SUCCESS(Status))
651 {
652 DPRINT("ZwEnumerateKey() (Status 0x%08lx)\n", Status);
653 break;
654 }
655
656 /* Terminate the string */
657 KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0;
658
659 /* Open the key */
660 RtlInitUnicodeString(&SubKeyName, KeyInfo->Name);
661 InitializeObjectAttributes(
662 &SubKeyAttributes,
663 &SubKeyName,
664 0, /* Attributes */
665 KeyHandle,
666 NULL); /* Security descriptor */
667 Status = ZwOpenKey(&SubKeyHandle, KEY_ENUMERATE_SUB_KEYS, &SubKeyAttributes);
668 if (!NT_SUCCESS(Status))
669 {
670 DPRINT("ZwOpenKey() failed (Status 0x%08lx)\n", Status);
671 break;
672 }
673
674 /* Enumerate the sub-keys */
675 Index2 = 0;
676 while (TRUE)
677 {
678 Status = ZwEnumerateKey(
679 SubKeyHandle,
680 Index2,
681 KeyBasicInformation,
682 SubKeyInfo,
683 BufferSize,
684 &ResultSize);
685 if (!NT_SUCCESS(Status))
686 {
687 DPRINT("ZwEnumerateKey() (Status 0x%08lx)\n", Status);
688 break;
689 }
690
691 /* Terminate the string */
692 SubKeyInfo->Name[SubKeyInfo->NameLength / sizeof(WCHAR)] = 0;
693
694 Device = (PPNPROOT_DEVICE)ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
695 if (!Device)
696 {
697 /* FIXME: */
698 DPRINT("ExAllocatePoolWithTag() failed\n");
699 break;
700 }
701
702 RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
703
704 if (!RtlCreateUnicodeString(&Device->ServiceName, KeyInfo->Name))
705 {
706 /* FIXME: */
707 DPRINT("RtlCreateUnicodeString() failed\n");
708 }
709
710 wcscpy(Buffer, ENUM_NAME_ROOT);
711 wcscat(Buffer, L"\\");
712 wcscat(Buffer, KeyInfo->Name);
713
714 if (!RtlCreateUnicodeString(&Device->DeviceID, Buffer))
715 {
716 /* FIXME: */
717 DPRINT("RtlCreateUnicodeString() failed\n");
718 }
719
720 DPRINT("Got entry: %S\n", Device->DeviceID.Buffer);
721
722 if (!RtlCreateUnicodeString(
723 &Device->InstanceID,
724 SubKeyInfo->Name))
725 {
726 /* FIXME: */
727 DPRINT("RtlCreateUnicodeString() failed\n");
728 }
729
730 Status = PnpRootFdoReadDeviceInfo(Device);
731 if (!NT_SUCCESS(Status))
732 {
733 /* FIXME */
734 DPRINT("PnpRootFdoReadDeviceInfo() failed with status 0x%08lx\n", Status);
735 }
736
737 ExInterlockedInsertTailList(
738 &DeviceExtension->DeviceListHead,
739 &Device->ListEntry,
740 &DeviceExtension->DeviceListLock);
741
742 DeviceExtension->DeviceListCount++;
743
744 Index2++;
745 }
746
747 ZwClose(SubKeyHandle);
748 Index1++;
749 }
750
751 ZwClose(KeyHandle);
752
753 ExFreePoolWithTag(KeyInfo, TAG_PNP_ROOT);
754 ExFreePoolWithTag(SubKeyInfo, TAG_PNP_ROOT);
755
756 return STATUS_SUCCESS;
757 }
758
759
760 NTSTATUS
761 PnpRootQueryBusRelations(
762 IN PDEVICE_OBJECT DeviceObject,
763 IN PIRP Irp,
764 IN PIO_STACK_LOCATION IrpSp)
765 {
766 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
767 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
768 PDEVICE_RELATIONS Relations;
769 PLIST_ENTRY CurrentEntry;
770 PPNPROOT_DEVICE Device;
771 NTSTATUS Status;
772 ULONG Size;
773 ULONG i;
774
775 DPRINT("Called\n");
776
777 Status = PnpRootFdoEnumerateDevices(DeviceObject);
778 if (!NT_SUCCESS(Status))
779 return Status;
780
781 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
782
783 if (Irp->IoStatus.Information)
784 {
785 /* FIXME: Another bus driver has already created a DEVICE_RELATIONS
786 structure so we must merge this structure with our own */
787 }
788
789 Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
790 (DeviceExtension->DeviceListCount - 1);
791
792 Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
793 if (!Relations)
794 return STATUS_INSUFFICIENT_RESOURCES;
795
796 Relations->Count = DeviceExtension->DeviceListCount;
797
798 i = 0;
799 CurrentEntry = DeviceExtension->DeviceListHead.Flink;
800 while (CurrentEntry != &DeviceExtension->DeviceListHead)
801 {
802 Device = CONTAINING_RECORD(CurrentEntry, PNPROOT_DEVICE, ListEntry);
803
804 if (!Device->Pdo)
805 {
806 /* Create a physical device object for the
807 device as it does not already have one */
808 Status = IoCreateDevice(
809 DeviceObject->DriverObject,
810 sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
811 NULL,
812 FILE_DEVICE_CONTROLLER,
813 FILE_AUTOGENERATED_DEVICE_NAME,
814 FALSE,
815 &Device->Pdo);
816 if (!NT_SUCCESS(Status))
817 {
818 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
819 ExFreePool(Relations);
820 return Status;
821 }
822
823 DPRINT("Created PDO 0x%p\n", Device->Pdo);
824
825 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
826
827 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
828
829 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
830
831 PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
832
833 RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
834
835 PdoDeviceExtension->Common.IsFDO = FALSE;
836
837 PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
838
839 PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
840
841 if (!RtlCreateUnicodeString(
842 &PdoDeviceExtension->DeviceID,
843 Device->DeviceID.Buffer))
844 {
845 DPRINT("Insufficient resources\n");
846 /* FIXME: */
847 }
848
849 DPRINT("DeviceID: %wZ PDO %p\n",
850 &PdoDeviceExtension->DeviceID,
851 Device->Pdo);
852
853 if (!RtlCreateUnicodeString(
854 &PdoDeviceExtension->InstanceID,
855 Device->InstanceID.Buffer))
856 {
857 DPRINT("Insufficient resources\n");
858 /* FIXME: */
859 }
860
861 DPRINT("InstanceID: %wZ PDO %p\n",
862 &PdoDeviceExtension->InstanceID,
863 Device->Pdo);
864
865 if (Device->ResourceRequirementsList != NULL)
866 {
867 PdoDeviceExtension->ResourceRequirementsList = ExAllocatePoolWithTag(
868 PagedPool,
869 Device->ResourceRequirementsList->ListSize,
870 TAG_PNP_ROOT);
871 if (PdoDeviceExtension->ResourceRequirementsList)
872 {
873 RtlCopyMemory(
874 PdoDeviceExtension->ResourceRequirementsList,
875 Device->ResourceRequirementsList,
876 Device->ResourceRequirementsList->ListSize);
877 }
878 else
879 {
880 /* FIXME */
881 DPRINT("ExAllocatePoolWithTag() failed\n");
882 }
883 }
884
885 DPRINT("ResourceRequirementsList: %p PDO %p\n",
886 PdoDeviceExtension->ResourceRequirementsList,
887 Device->Pdo);
888 }
889
890 /* Reference the physical device object. The PnP manager
891 will dereference it again when it is no longer needed */
892 ObReferenceObject(Device->Pdo);
893
894 Relations->Objects[i] = Device->Pdo;
895
896 i++;
897
898 CurrentEntry = CurrentEntry->Flink;
899 }
900
901 if (NT_SUCCESS(Status))
902 {
903 Irp->IoStatus.Information = (ULONG_PTR)Relations;
904 }
905 else
906 {
907 Irp->IoStatus.Information = 0;
908 }
909
910 return Status;
911 }
912
913
914 NTSTATUS
915 PnpRootQueryDeviceRelations(
916 IN PDEVICE_OBJECT DeviceObject,
917 IN PIRP Irp,
918 IN PIO_STACK_LOCATION IrpSp)
919 {
920 NTSTATUS Status;
921
922 DPRINT("Called\n");
923
924 switch (IrpSp->Parameters.QueryDeviceRelations.Type) {
925 case BusRelations:
926 Status = PnpRootQueryBusRelations(DeviceObject, Irp, IrpSp);
927 break;
928
929 default:
930 Status = STATUS_NOT_IMPLEMENTED;
931 }
932
933 return Status;
934 }
935
936
937 /*
938 * FUNCTION: Handle Plug and Play IRPs for the root bus device object
939 * ARGUMENTS:
940 * DeviceObject = Pointer to functional device object of the root bus driver
941 * Irp = Pointer to IRP that should be handled
942 * RETURNS:
943 * Status
944 */
945 NTSTATUS
946 STDCALL
947 PnpRootFdoPnpControl(
948 IN PDEVICE_OBJECT DeviceObject,
949 IN PIRP Irp)
950 {
951 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
952 PIO_STACK_LOCATION IrpSp;
953 NTSTATUS Status;
954
955 DPRINT("Called\n");
956
957 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
958
959 Status = Irp->IoStatus.Status;
960
961 IrpSp = IoGetCurrentIrpStackLocation(Irp);
962
963 switch (IrpSp->MinorFunction) {
964 case IRP_MN_QUERY_DEVICE_RELATIONS:
965 Status = PnpRootQueryDeviceRelations(DeviceObject, Irp, IrpSp);
966 break;
967
968 case IRP_MN_START_DEVICE:
969 DeviceExtension->State = dsStarted;
970 Status = STATUS_SUCCESS;
971 break;
972
973 case IRP_MN_STOP_DEVICE:
974 /* Root device cannot be stopped */
975 Status = STATUS_UNSUCCESSFUL;
976 break;
977
978 default:
979 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
980 Status = STATUS_NOT_IMPLEMENTED;
981 break;
982 }
983
984 if (Status != STATUS_PENDING) {
985 Irp->IoStatus.Status = Status;
986 IoCompleteRequest(Irp, IO_NO_INCREMENT);
987 }
988
989 DPRINT("Leaving. Status 0x%X\n", Status);
990
991 return Status;
992 }
993
994
995 /*
996 * FUNCTION: Handle power management IRPs for the root bus device object
997 * ARGUMENTS:
998 * DeviceObject = Pointer to functional device object of the root bus driver
999 * Irp = Pointer to IRP that should be handled
1000 * RETURNS:
1001 * Status
1002 */
1003 NTSTATUS
1004 STDCALL
1005 PnpRootFdoPowerControl(
1006 IN PDEVICE_OBJECT DeviceObject,
1007 IN PIRP Irp)
1008 {
1009 PIO_STACK_LOCATION IrpSp;
1010 NTSTATUS Status;
1011
1012 DPRINT("Called\n");
1013
1014 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1015
1016 switch (IrpSp->MinorFunction) {
1017 default:
1018 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
1019 Status = STATUS_NOT_IMPLEMENTED;
1020 break;
1021 }
1022
1023 if (Status != STATUS_PENDING) {
1024 Irp->IoStatus.Status = Status;
1025 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1026 }
1027
1028 DPRINT("Leaving. Status 0x%X\n", Status);
1029
1030 return Status;
1031 }
1032
1033
1034 /*
1035 * FUNCTION: Handle Plug and Play IRPs
1036 * ARGUMENTS:
1037 * DeviceObject = Pointer to PDO or FDO
1038 * Irp = Pointer to IRP that should be handled
1039 * RETURNS:
1040 * Status
1041 */
1042 NTSTATUS
1043 STDCALL
1044 PnpRootPnpControl(
1045 IN PDEVICE_OBJECT DeviceObject,
1046 IN PIRP Irp)
1047 {
1048 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
1049 NTSTATUS Status;
1050
1051 DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1052
1053 DPRINT("DeviceObject 0x%p DeviceExtension 0x%p IsFDO %d\n",
1054 DeviceObject,
1055 DeviceExtension,
1056 DeviceExtension->IsFDO);
1057
1058 if (DeviceExtension->IsFDO) {
1059 Status = PnpRootFdoPnpControl(DeviceObject, Irp);
1060 } else {
1061 Status = PnpRootPdoPnpControl(DeviceObject, Irp);
1062 }
1063
1064 return Status;
1065 }
1066
1067
1068 /*
1069 * FUNCTION: Handle power management IRPs
1070 * ARGUMENTS:
1071 * DeviceObject = Pointer to PDO or FDO
1072 * Irp = Pointer to IRP that should be handled
1073 * RETURNS:
1074 * Status
1075 */
1076 NTSTATUS
1077 STDCALL
1078 PnpRootPowerControl(
1079 IN PDEVICE_OBJECT DeviceObject,
1080 IN PIRP Irp)
1081 {
1082 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
1083 NTSTATUS Status;
1084
1085 DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1086
1087 if (DeviceExtension->IsFDO) {
1088 Status = PnpRootFdoPowerControl(DeviceObject, Irp);
1089 } else {
1090 Status = PnpRootPdoPowerControl(DeviceObject, Irp);
1091 }
1092
1093 return Status;
1094 }
1095
1096
1097 NTSTATUS
1098 STDCALL
1099 PnpRootAddDevice(
1100 IN PDRIVER_OBJECT DriverObject,
1101 IN PDEVICE_OBJECT PhysicalDeviceObject)
1102 {
1103 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
1104 NTSTATUS Status;
1105
1106 DPRINT("Called\n");
1107
1108 Status = IoCreateDevice(
1109 DriverObject,
1110 sizeof(PNPROOT_FDO_DEVICE_EXTENSION),
1111 NULL,
1112 FILE_DEVICE_BUS_EXTENDER,
1113 FILE_DEVICE_SECURE_OPEN,
1114 TRUE,
1115 &PnpRootDeviceObject);
1116 if (!NT_SUCCESS(Status)) {
1117 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
1118 }
1119
1120 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
1121
1122 RtlZeroMemory(DeviceExtension, sizeof(PNPROOT_FDO_DEVICE_EXTENSION));
1123
1124 DeviceExtension->Common.IsFDO = TRUE;
1125
1126 DeviceExtension->State = dsStopped;
1127
1128 DeviceExtension->Ldo = IoAttachDeviceToDeviceStack(
1129 PnpRootDeviceObject,
1130 PhysicalDeviceObject);
1131
1132 if (!PnpRootDeviceObject) {
1133 CPRINT("PnpRootDeviceObject 0x%p\n", PnpRootDeviceObject);
1134 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
1135 }
1136
1137 if (!PhysicalDeviceObject) {
1138 CPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject);
1139 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
1140 }
1141
1142 InitializeListHead(&DeviceExtension->DeviceListHead);
1143
1144 DeviceExtension->DeviceListCount = 0;
1145
1146 KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
1147
1148 PnpRootDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
1149
1150 //PnpRootDeviceObject->Flags |= DO_POWER_PAGABLE;
1151
1152 DPRINT("Done AddDevice()\n");
1153
1154 return STATUS_SUCCESS;
1155 }
1156
1157
1158 NTSTATUS
1159 STDCALL
1160 PnpRootDriverEntry(
1161 IN PDRIVER_OBJECT DriverObject,
1162 IN PUNICODE_STRING RegistryPath)
1163 {
1164 DPRINT("Called\n");
1165
1166 DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH) PnpRootPnpControl;
1167 DriverObject->MajorFunction[IRP_MJ_POWER] = (PDRIVER_DISPATCH) PnpRootPowerControl;
1168 DriverObject->DriverExtension->AddDevice = PnpRootAddDevice;
1169
1170 return STATUS_SUCCESS;
1171 }
1172
1173 /* EOF */