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