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