Copy rpoolmgr.h from trunk
[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 } PNPROOT_DEVICE, *PPNPROOT_DEVICE;
38
39 typedef enum
40 {
41 dsStopped,
42 dsStarted,
43 dsPaused,
44 dsRemoved,
45 dsSurpriseRemoved
46 } PNPROOT_DEVICE_STATE;
47
48
49 #include <pshpack1.h>
50
51 typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION
52 {
53 // Pointer to device object, this device extension is associated with
54 PDEVICE_OBJECT DeviceObject;
55 // Wether this device extension is for an FDO or PDO
56 BOOLEAN IsFDO;
57 // Wether the device is removed
58 BOOLEAN Removed;
59 // Current device power state for the device
60 DEVICE_POWER_STATE DevicePowerState;
61 } PNPROOT_COMMON_DEVICE_EXTENSION, *PPNPROOT_COMMON_DEVICE_EXTENSION;
62
63
64 /* Physical Device Object device extension for a child device */
65 typedef struct _PNPROOT_PDO_DEVICE_EXTENSION
66 {
67 // Common device data
68 PNPROOT_COMMON_DEVICE_EXTENSION Common;
69 // Device ID
70 UNICODE_STRING DeviceID;
71 // Instance ID
72 UNICODE_STRING InstanceID;
73 } PNPROOT_PDO_DEVICE_EXTENSION, *PPNPROOT_PDO_DEVICE_EXTENSION;
74
75
76 /* Functional Device Object device extension for the PCI driver device object */
77 typedef struct _PNPROOT_FDO_DEVICE_EXTENSION
78 {
79 // Common device data
80 PNPROOT_COMMON_DEVICE_EXTENSION Common;
81 // Physical Device Object
82 PDEVICE_OBJECT Pdo;
83 // Lower device object
84 PDEVICE_OBJECT Ldo;
85 // Current state of the driver
86 PNPROOT_DEVICE_STATE State;
87 // Namespace device list
88 LIST_ENTRY DeviceListHead;
89 // Number of (not removed) devices in device list
90 ULONG DeviceListCount;
91 // Lock for namespace device list
92 // FIXME: Use fast mutex instead?
93 KSPIN_LOCK DeviceListLock;
94 } PNPROOT_FDO_DEVICE_EXTENSION, *PPNPROOT_FDO_DEVICE_EXTENSION;
95
96 #include <poppack.h>
97
98
99
100 PDEVICE_OBJECT PnpRootDeviceObject;
101
102
103 /* FUNCTIONS *****************************************************************/
104
105 /* Physical Device Object routines */
106
107 NTSTATUS
108 PnpRootCreateDevice(
109 PDEVICE_OBJECT *PhysicalDeviceObject)
110 {
111 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
112 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
113 PPNPROOT_DEVICE Device;
114 NTSTATUS Status;
115
116 /* This function should be obsoleted soon */
117
118 DPRINT("Called\n");
119
120 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
121
122 Device = (PPNPROOT_DEVICE)ExAllocatePool(PagedPool, sizeof(PNPROOT_DEVICE));
123 if (!Device)
124 return STATUS_INSUFFICIENT_RESOURCES;
125
126 RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
127
128 Status = IoCreateDevice(
129 PnpRootDeviceObject->DriverObject,
130 sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
131 NULL,
132 FILE_DEVICE_CONTROLLER,
133 FILE_AUTOGENERATED_DEVICE_NAME,
134 FALSE,
135 &Device->Pdo);
136 if (!NT_SUCCESS(Status)) {
137 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
138 ExFreePool(Device);
139 return Status;
140 }
141
142 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
143
144 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
145
146 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
147
148 PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
149
150 RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
151
152 PdoDeviceExtension->Common.IsFDO = FALSE;
153
154 PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
155
156 PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
157
158 if (!IopCreateUnicodeString(
159 &PdoDeviceExtension->DeviceID,
160 ENUM_NAME_ROOT \
161 L"\\LEGACY_UNKNOWN",
162 PagedPool))
163 {
164 /* FIXME: */
165 DPRINT("IopCreateUnicodeString() failed\n");
166 }
167
168 if (!IopCreateUnicodeString(
169 &PdoDeviceExtension->InstanceID,
170 L"0000",
171 PagedPool))
172 {
173 /* FIXME: */
174 DPRINT("IopCreateUnicodeString() failed\n");
175 }
176
177 ExInterlockedInsertTailList(
178 &DeviceExtension->DeviceListHead,
179 &Device->ListEntry,
180 &DeviceExtension->DeviceListLock);
181
182 DeviceExtension->DeviceListCount++;
183
184 *PhysicalDeviceObject = Device->Pdo;
185
186 return STATUS_SUCCESS;
187 }
188
189
190 NTSTATUS
191 PdoQueryId(
192 IN PDEVICE_OBJECT DeviceObject,
193 IN PIRP Irp,
194 PIO_STACK_LOCATION IrpSp)
195 {
196 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
197 UNICODE_STRING String;
198 NTSTATUS Status;
199
200 DPRINT("Called\n");
201
202 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
203
204 // Irp->IoStatus.Information = 0;
205
206 Status = STATUS_SUCCESS;
207
208 RtlInitUnicodeString(&String, NULL);
209
210 switch (IrpSp->Parameters.QueryId.IdType) {
211 case BusQueryDeviceID:
212 Status = IopCreateUnicodeString(
213 &String,
214 DeviceExtension->DeviceID.Buffer,
215 PagedPool);
216
217 DPRINT("DeviceID: %S\n", String.Buffer);
218
219 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
220 break;
221
222 case BusQueryHardwareIDs:
223 case BusQueryCompatibleIDs:
224 Status = STATUS_NOT_IMPLEMENTED;
225 break;
226
227 case BusQueryInstanceID:
228 Status = IopCreateUnicodeString(
229 &String,
230 DeviceExtension->InstanceID.Buffer,
231 PagedPool);
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 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
275 ULONG ResourceListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List);
276
277 ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
278 if (ResourceList == NULL)
279 return STATUS_INSUFFICIENT_RESOURCES;
280
281 RtlZeroMemory(ResourceList, ResourceListSize);
282 ResourceList->ListSize = ResourceListSize;
283
284 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
285
286 return STATUS_SUCCESS;
287 }
288
289
290 /*
291 * FUNCTION: Handle Plug and Play IRPs for the child device
292 * ARGUMENTS:
293 * DeviceObject = Pointer to physical device object of the child device
294 * Irp = Pointer to IRP that should be handled
295 * RETURNS:
296 * Status
297 */
298 NTSTATUS
299 PnpRootPdoPnpControl(
300 PDEVICE_OBJECT DeviceObject,
301 PIRP Irp)
302 {
303 PIO_STACK_LOCATION IrpSp;
304 NTSTATUS Status;
305
306 DPRINT("Called\n");
307
308 Status = Irp->IoStatus.Status;
309
310 IrpSp = IoGetCurrentIrpStackLocation(Irp);
311
312 switch (IrpSp->MinorFunction) {
313 #if 0
314 case IRP_MN_QUERY_BUS_INFORMATION:
315 break;
316
317 case IRP_MN_QUERY_DEVICE_RELATIONS:
318 /* FIXME: Handle for TargetDeviceRelation */
319 break;
320 #endif
321
322 case IRP_MN_QUERY_ID:
323 Status = PdoQueryId(DeviceObject, Irp, IrpSp);
324 break;
325
326 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
327 Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
328 break;
329
330 case IRP_MN_QUERY_RESOURCES:
331 Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
332 break;
333
334 case IRP_MN_START_DEVICE:
335 case IRP_MN_QUERY_STOP_DEVICE:
336 case IRP_MN_CANCEL_STOP_DEVICE:
337 case IRP_MN_STOP_DEVICE:
338 case IRP_MN_QUERY_REMOVE_DEVICE:
339 case IRP_MN_CANCEL_REMOVE_DEVICE:
340 case IRP_MN_REMOVE_DEVICE:
341 case IRP_MN_SURPRISE_REMOVAL:
342 Status = STATUS_SUCCESS;
343 break;
344
345 default:
346 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
347 break;
348 }
349
350 Irp->IoStatus.Status = Status;
351 IoCompleteRequest(Irp, IO_NO_INCREMENT);
352
353 DPRINT("Leaving. Status 0x%X\n", Status);
354
355 return Status;
356 }
357
358
359 /*
360 * FUNCTION: Handle power management IRPs for the child device
361 * ARGUMENTS:
362 * DeviceObject = Pointer to physical device object of the child device
363 * Irp = Pointer to IRP that should be handled
364 * RETURNS:
365 * Status
366 */
367 NTSTATUS
368 PnpRootPdoPowerControl(
369 PDEVICE_OBJECT DeviceObject,
370 PIRP Irp)
371 {
372 PIO_STACK_LOCATION IrpSp;
373 NTSTATUS Status;
374
375 DPRINT("Called\n");
376
377 Status = Irp->IoStatus.Status;
378
379 IrpSp = IoGetCurrentIrpStackLocation(Irp);
380
381 switch (IrpSp->MinorFunction) {
382 default:
383 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
384 Status = STATUS_NOT_IMPLEMENTED;
385 break;
386 }
387
388 Irp->IoStatus.Status = Status;
389 IoCompleteRequest(Irp, IO_NO_INCREMENT);
390
391 DPRINT("Leaving. Status 0x%X\n", Status);
392
393 return Status;
394 }
395
396
397 /* Functional Device Object routines */
398
399 NTSTATUS
400 PnpRootFdoReadDeviceInfo(
401 PPNPROOT_DEVICE Device)
402 {
403 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
404 PUNICODE_STRING DeviceDesc;
405 WCHAR KeyName[MAX_PATH];
406 NTSTATUS Status;
407
408 DPRINT("Called\n");
409
410 /* Retrieve configuration from Enum key */
411
412 DeviceDesc = &Device->DeviceDescription;
413
414 wcscpy(KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
415 wcscat(KeyName, ENUM_NAME_ROOT);
416 wcscat(KeyName, L"\\");
417 wcscat(KeyName, Device->ServiceName.Buffer);
418 wcscat(KeyName, L"\\");
419 wcscat(KeyName, Device->InstanceID.Buffer);
420
421 DPRINT("KeyName %S\n", KeyName);
422
423 RtlZeroMemory(QueryTable, sizeof(QueryTable));
424
425 RtlInitUnicodeString(DeviceDesc, NULL);
426
427 QueryTable[0].Name = L"DeviceDesc";
428 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
429 QueryTable[0].EntryContext = DeviceDesc;
430
431 Status = RtlQueryRegistryValues(
432 RTL_REGISTRY_ABSOLUTE,
433 KeyName,
434 QueryTable,
435 NULL,
436 NULL);
437
438 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status);
439
440 if (!NT_SUCCESS(Status))
441 {
442 /* FIXME: */
443 }
444
445 DPRINT("Got device description: %S\n", DeviceDesc->Buffer);
446
447 return STATUS_SUCCESS;
448 }
449
450
451 NTSTATUS
452 PnpRootFdoEnumerateDevices(
453 PDEVICE_OBJECT DeviceObject)
454 {
455 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
456 OBJECT_ATTRIBUTES ObjectAttributes;
457 PKEY_BASIC_INFORMATION KeyInfo;
458 UNICODE_STRING KeyName;
459 PPNPROOT_DEVICE Device;
460 WCHAR Buffer[MAX_PATH];
461 HANDLE KeyHandle;
462 ULONG BufferSize;
463 ULONG ResultSize;
464 NTSTATUS Status;
465 ULONG Index;
466
467 DPRINT("Called\n");
468
469 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
470
471 BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH+1) * sizeof(WCHAR);
472 KeyInfo = ExAllocatePool(PagedPool, BufferSize);
473 if (!KeyInfo)
474 {
475 return STATUS_INSUFFICIENT_RESOURCES;
476 }
477
478 RtlRosInitUnicodeStringFromLiteral(
479 &KeyName,
480 L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\" \
481 ENUM_NAME_ROOT);
482
483 InitializeObjectAttributes(
484 &ObjectAttributes,
485 &KeyName,
486 OBJ_CASE_INSENSITIVE,
487 NULL,
488 NULL);
489
490 Status = ZwOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
491 if (!NT_SUCCESS(Status))
492 {
493 DPRINT("ZwOpenKey() failed (Status %x)\n", Status);
494 ExFreePool(KeyInfo);
495 return Status;
496 }
497
498 /* FIXME: Disabled due to still using the old method of auto loading drivers e.g.
499 there are more entries in the list than found in the registry as some
500 drivers are passed on the command line */
501 // DeviceExtension->DeviceListCount = 0;
502
503 Index = 0;
504 do {
505 Status = ZwEnumerateKey(
506 KeyHandle,
507 Index,
508 KeyBasicInformation,
509 KeyInfo,
510 BufferSize,
511 &ResultSize);
512 if (!NT_SUCCESS(Status))
513 {
514 DPRINT("ZwEnumerateKey() (Status %x)\n", Status);
515 break;
516 }
517
518 /* Terminate the string */
519 KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0;
520
521 Device = (PPNPROOT_DEVICE)ExAllocatePool(PagedPool, sizeof(PNPROOT_DEVICE));
522 if (!Device)
523 {
524 /* FIXME: */
525 break;
526 }
527
528 RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
529
530 if (!IopCreateUnicodeString(&Device->ServiceName, KeyInfo->Name, PagedPool))
531 {
532 /* FIXME: */
533 DPRINT("IopCreateUnicodeString() failed\n");
534 }
535
536 wcscpy(Buffer, ENUM_NAME_ROOT);
537 wcscat(Buffer, L"\\");
538 wcscat(Buffer, KeyInfo->Name);
539
540 if (!IopCreateUnicodeString(&Device->DeviceID, Buffer, PagedPool))
541 {
542 /* FIXME: */
543 DPRINT("IopCreateUnicodeString() failed\n");
544 }
545
546 DPRINT("Got entry: %S\n", Device->DeviceID.Buffer);
547
548 if (!IopCreateUnicodeString(
549 &Device->InstanceID,
550 L"0000",
551 PagedPool))
552 {
553 /* FIXME: */
554 DPRINT("IopCreateUnicodeString() failed\n");
555 }
556
557 Status = PnpRootFdoReadDeviceInfo(Device);
558 if (!NT_SUCCESS(Status))
559 {
560 DPRINT("PnpRootFdoReadDeviceInfo() failed with status %x\n", Status);
561 /* FIXME: */
562 }
563
564 ExInterlockedInsertTailList(
565 &DeviceExtension->DeviceListHead,
566 &Device->ListEntry,
567 &DeviceExtension->DeviceListLock);
568
569 DeviceExtension->DeviceListCount++;
570
571 Index++;
572 } while (TRUE);
573
574 DPRINT("Entries found: %d\n", Index);
575
576 ZwClose(KeyHandle);
577
578 ExFreePool(KeyInfo);
579
580 return STATUS_SUCCESS;
581 }
582
583
584 NTSTATUS
585 PnpRootQueryBusRelations(
586 IN PDEVICE_OBJECT DeviceObject,
587 IN PIRP Irp,
588 IN PIO_STACK_LOCATION IrpSp)
589 {
590 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
591 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
592 PDEVICE_RELATIONS Relations;
593 PLIST_ENTRY CurrentEntry;
594 PPNPROOT_DEVICE Device;
595 NTSTATUS Status;
596 ULONG Size;
597 ULONG i;
598
599 DPRINT("Called\n");
600
601 Status = PnpRootFdoEnumerateDevices(DeviceObject);
602 if (!NT_SUCCESS(Status))
603 return Status;
604
605 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
606
607 if (Irp->IoStatus.Information)
608 {
609 /* FIXME: Another bus driver has already created a DEVICE_RELATIONS
610 structure so we must merge this structure with our own */
611 }
612
613 Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
614 (DeviceExtension->DeviceListCount - 1);
615
616 Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
617 if (!Relations)
618 return STATUS_INSUFFICIENT_RESOURCES;
619
620 Relations->Count = DeviceExtension->DeviceListCount;
621
622 i = 0;
623 CurrentEntry = DeviceExtension->DeviceListHead.Flink;
624 while (CurrentEntry != &DeviceExtension->DeviceListHead)
625 {
626 Device = CONTAINING_RECORD(CurrentEntry, PNPROOT_DEVICE, ListEntry);
627
628 if (!Device->Pdo)
629 {
630 /* Create a physical device object for the
631 device as it does not already have one */
632 Status = IoCreateDevice(
633 DeviceObject->DriverObject,
634 sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
635 NULL,
636 FILE_DEVICE_CONTROLLER,
637 FILE_AUTOGENERATED_DEVICE_NAME,
638 FALSE,
639 &Device->Pdo);
640 if (!NT_SUCCESS(Status))
641 {
642 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
643 ExFreePool(Relations);
644 return Status;
645 }
646
647 DPRINT("Created PDO %x\n", Device->Pdo);
648
649 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
650
651 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
652
653 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
654
655 PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
656
657 RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
658
659 PdoDeviceExtension->Common.IsFDO = FALSE;
660
661 PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
662
663 PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
664
665 if (!IopCreateUnicodeString(
666 &PdoDeviceExtension->DeviceID,
667 Device->DeviceID.Buffer,
668 PagedPool))
669 {
670 DPRINT("Insufficient resources\n");
671 /* FIXME: */
672 }
673
674 DPRINT1("DeviceID: %wZ PDO %p\n",
675 &PdoDeviceExtension->DeviceID,
676 Device->Pdo);
677
678 if (!IopCreateUnicodeString(
679 &PdoDeviceExtension->InstanceID,
680 Device->InstanceID.Buffer,
681 PagedPool))
682 {
683 DPRINT("Insufficient resources\n");
684 /* FIXME: */
685 }
686
687 DPRINT1("InstanceID: %wZ PDO %p\n",
688 &PdoDeviceExtension->InstanceID,
689 Device->Pdo);
690 }
691
692 /* Reference the physical device object. The PnP manager
693 will dereference it again when it is no longer needed */
694 ObReferenceObject(Device->Pdo);
695
696 Relations->Objects[i] = Device->Pdo;
697
698 i++;
699
700 CurrentEntry = CurrentEntry->Flink;
701 }
702
703 if (NT_SUCCESS(Status))
704 {
705 Irp->IoStatus.Information = (ULONG_PTR)Relations;
706 }
707 else
708 {
709 Irp->IoStatus.Information = 0;
710 }
711
712 return Status;
713 }
714
715
716 NTSTATUS
717 PnpRootQueryDeviceRelations(
718 IN PDEVICE_OBJECT DeviceObject,
719 IN PIRP Irp,
720 IN PIO_STACK_LOCATION IrpSp)
721 {
722 NTSTATUS Status;
723
724 DPRINT("Called\n");
725
726 switch (IrpSp->Parameters.QueryDeviceRelations.Type) {
727 case BusRelations:
728 Status = PnpRootQueryBusRelations(DeviceObject, Irp, IrpSp);
729 break;
730
731 default:
732 Status = STATUS_NOT_IMPLEMENTED;
733 }
734
735 return Status;
736 }
737
738
739 /*
740 * FUNCTION: Handle Plug and Play IRPs for the root bus device object
741 * ARGUMENTS:
742 * DeviceObject = Pointer to functional device object of the root bus driver
743 * Irp = Pointer to IRP that should be handled
744 * RETURNS:
745 * Status
746 */
747 NTSTATUS
748 STDCALL
749 PnpRootFdoPnpControl(
750 IN PDEVICE_OBJECT DeviceObject,
751 IN PIRP Irp)
752 {
753 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
754 PIO_STACK_LOCATION IrpSp;
755 NTSTATUS Status;
756
757 DPRINT("Called\n");
758
759 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
760
761 Status = Irp->IoStatus.Status;
762
763 IrpSp = IoGetCurrentIrpStackLocation(Irp);
764
765 switch (IrpSp->MinorFunction) {
766 case IRP_MN_QUERY_DEVICE_RELATIONS:
767 Status = PnpRootQueryDeviceRelations(DeviceObject, Irp, IrpSp);
768 break;
769
770 case IRP_MN_START_DEVICE:
771 DeviceExtension->State = dsStarted;
772 Status = STATUS_SUCCESS;
773 break;
774
775 case IRP_MN_STOP_DEVICE:
776 /* Root device cannot be stopped */
777 Status = STATUS_UNSUCCESSFUL;
778 break;
779
780 default:
781 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
782 Status = STATUS_NOT_IMPLEMENTED;
783 break;
784 }
785
786 if (Status != STATUS_PENDING) {
787 Irp->IoStatus.Status = Status;
788 IoCompleteRequest(Irp, IO_NO_INCREMENT);
789 }
790
791 DPRINT("Leaving. Status 0x%X\n", Status);
792
793 return Status;
794 }
795
796
797 /*
798 * FUNCTION: Handle power management IRPs for the root bus device object
799 * ARGUMENTS:
800 * DeviceObject = Pointer to functional device object of the root bus driver
801 * Irp = Pointer to IRP that should be handled
802 * RETURNS:
803 * Status
804 */
805 NTSTATUS
806 STDCALL
807 PnpRootFdoPowerControl(
808 IN PDEVICE_OBJECT DeviceObject,
809 IN PIRP Irp)
810 {
811 PIO_STACK_LOCATION IrpSp;
812 NTSTATUS Status;
813
814 DPRINT("Called\n");
815
816 IrpSp = IoGetCurrentIrpStackLocation(Irp);
817
818 switch (IrpSp->MinorFunction) {
819 default:
820 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
821 Status = STATUS_NOT_IMPLEMENTED;
822 break;
823 }
824
825 if (Status != STATUS_PENDING) {
826 Irp->IoStatus.Status = Status;
827 IoCompleteRequest(Irp, IO_NO_INCREMENT);
828 }
829
830 DPRINT("Leaving. Status 0x%X\n", Status);
831
832 return Status;
833 }
834
835
836 /*
837 * FUNCTION: Handle Plug and Play IRPs
838 * ARGUMENTS:
839 * DeviceObject = Pointer to PDO or FDO
840 * Irp = Pointer to IRP that should be handled
841 * RETURNS:
842 * Status
843 */
844 NTSTATUS
845 STDCALL
846 PnpRootPnpControl(
847 IN PDEVICE_OBJECT DeviceObject,
848 IN PIRP Irp)
849 {
850 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
851 NTSTATUS Status;
852
853 DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
854
855 DPRINT("DeviceObject %x DeviceExtension %x IsFDO %d\n",
856 DeviceObject,
857 DeviceExtension,
858 DeviceExtension->IsFDO);
859
860 if (DeviceExtension->IsFDO) {
861 Status = PnpRootFdoPnpControl(DeviceObject, Irp);
862 } else {
863 Status = PnpRootPdoPnpControl(DeviceObject, Irp);
864 }
865
866 return Status;
867 }
868
869
870 /*
871 * FUNCTION: Handle power management IRPs
872 * ARGUMENTS:
873 * DeviceObject = Pointer to PDO or FDO
874 * Irp = Pointer to IRP that should be handled
875 * RETURNS:
876 * Status
877 */
878 NTSTATUS
879 STDCALL
880 PnpRootPowerControl(
881 IN PDEVICE_OBJECT DeviceObject,
882 IN PIRP Irp)
883 {
884 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
885 NTSTATUS Status;
886
887 DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
888
889 if (DeviceExtension->IsFDO) {
890 Status = PnpRootFdoPowerControl(DeviceObject, Irp);
891 } else {
892 Status = PnpRootPdoPowerControl(DeviceObject, Irp);
893 }
894
895 return Status;
896 }
897
898
899 NTSTATUS
900 STDCALL
901 PnpRootAddDevice(
902 IN PDRIVER_OBJECT DriverObject,
903 IN PDEVICE_OBJECT PhysicalDeviceObject)
904 {
905 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
906 NTSTATUS Status;
907
908 DPRINT("Called\n");
909
910 Status = IoCreateDevice(
911 DriverObject,
912 sizeof(PNPROOT_FDO_DEVICE_EXTENSION),
913 NULL,
914 FILE_DEVICE_BUS_EXTENDER,
915 FILE_DEVICE_SECURE_OPEN,
916 TRUE,
917 &PnpRootDeviceObject);
918 if (!NT_SUCCESS(Status)) {
919 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
920 }
921
922 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
923
924 RtlZeroMemory(DeviceExtension, sizeof(PNPROOT_FDO_DEVICE_EXTENSION));
925
926 DeviceExtension->Common.IsFDO = TRUE;
927
928 DeviceExtension->State = dsStopped;
929
930 DeviceExtension->Ldo = IoAttachDeviceToDeviceStack(
931 PnpRootDeviceObject,
932 PhysicalDeviceObject);
933
934 if (!PnpRootDeviceObject) {
935 CPRINT("PnpRootDeviceObject 0x%X\n", PnpRootDeviceObject);
936 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
937 }
938
939 if (!PhysicalDeviceObject) {
940 CPRINT("PhysicalDeviceObject 0x%X\n", PhysicalDeviceObject);
941 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
942 }
943
944 InitializeListHead(&DeviceExtension->DeviceListHead);
945
946 DeviceExtension->DeviceListCount = 0;
947
948 KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
949
950 PnpRootDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
951
952 //PnpRootDeviceObject->Flags |= DO_POWER_PAGABLE;
953
954 DPRINT("Done AddDevice()\n");
955
956 return STATUS_SUCCESS;
957 }
958
959
960 NTSTATUS
961 STDCALL
962 PnpRootDriverEntry(
963 IN PDRIVER_OBJECT DriverObject,
964 IN PUNICODE_STRING RegistryPath)
965 {
966 DPRINT("Called\n");
967
968 DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH) PnpRootPnpControl;
969 DriverObject->MajorFunction[IRP_MJ_POWER] = (PDRIVER_DISPATCH) PnpRootPowerControl;
970 DriverObject->DriverExtension->AddDevice = PnpRootAddDevice;
971
972 return STATUS_SUCCESS;
973 }
974
975 /* EOF */