cc9fd6d402e219c9f3e0abb81cb6f9efe82214a9
[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/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, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
413 wcscat(KeyName, ENUM_NAME_ROOT);
414 wcscat(KeyName, L"\\");
415 wcscat(KeyName, Device->ServiceName.Buffer);
416 wcscat(KeyName, L"\\");
417 wcscat(KeyName, Device->InstanceID.Buffer);
418
419 DPRINT("KeyName %S\n", KeyName);
420
421 RtlZeroMemory(QueryTable, sizeof(QueryTable));
422
423 RtlInitUnicodeString(DeviceDesc, NULL);
424
425 QueryTable[0].Name = L"DeviceDesc";
426 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
427 QueryTable[0].EntryContext = DeviceDesc;
428
429 Status = RtlQueryRegistryValues(
430 RTL_REGISTRY_ABSOLUTE,
431 KeyName,
432 QueryTable,
433 NULL,
434 NULL);
435
436 DPRINT("RtlQueryRegistryValues() returned status %x\n", Status);
437
438 if (!NT_SUCCESS(Status))
439 {
440 /* FIXME: */
441 }
442
443 DPRINT("Got device description: %S\n", DeviceDesc->Buffer);
444
445 return STATUS_SUCCESS;
446 }
447
448
449 NTSTATUS
450 PnpRootFdoEnumerateDevices(
451 PDEVICE_OBJECT DeviceObject)
452 {
453 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
454 OBJECT_ATTRIBUTES ObjectAttributes;
455 PKEY_BASIC_INFORMATION KeyInfo;
456 UNICODE_STRING KeyName;
457 PPNPROOT_DEVICE Device;
458 WCHAR Buffer[MAX_PATH];
459 HANDLE KeyHandle;
460 ULONG BufferSize;
461 ULONG ResultSize;
462 NTSTATUS Status;
463 ULONG Index;
464
465 DPRINT("Called\n");
466
467 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
468
469 BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH+1) * sizeof(WCHAR);
470 KeyInfo = ExAllocatePool(PagedPool, BufferSize);
471 if (!KeyInfo)
472 {
473 return STATUS_INSUFFICIENT_RESOURCES;
474 }
475
476 RtlRosInitUnicodeStringFromLiteral(
477 &KeyName,
478 L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\" \
479 ENUM_NAME_ROOT);
480
481 InitializeObjectAttributes(
482 &ObjectAttributes,
483 &KeyName,
484 OBJ_CASE_INSENSITIVE,
485 NULL,
486 NULL);
487
488 Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
489 if (!NT_SUCCESS(Status))
490 {
491 DPRINT("NtOpenKey() failed (Status %x)\n", Status);
492 ExFreePool(KeyInfo);
493 return Status;
494 }
495
496 /* FIXME: Disabled due to still using the old method of auto loading drivers e.g.
497 there are more entries in the list than found in the registry as some
498 drivers are passed on the command line */
499 // DeviceExtension->DeviceListCount = 0;
500
501 Index = 0;
502 do {
503 Status = ZwEnumerateKey(
504 KeyHandle,
505 Index,
506 KeyBasicInformation,
507 KeyInfo,
508 BufferSize,
509 &ResultSize);
510 if (!NT_SUCCESS(Status))
511 {
512 DPRINT("ZwEnumerateKey() (Status %x)\n", Status);
513 break;
514 }
515
516 /* Terminate the string */
517 KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0;
518
519 Device = (PPNPROOT_DEVICE)ExAllocatePool(PagedPool, sizeof(PNPROOT_DEVICE));
520 if (!Device)
521 {
522 /* FIXME: */
523 break;
524 }
525
526 RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));
527
528 if (!IopCreateUnicodeString(&Device->ServiceName, KeyInfo->Name, PagedPool))
529 {
530 /* FIXME: */
531 DPRINT("IopCreateUnicodeString() failed\n");
532 }
533
534 wcscpy(Buffer, ENUM_NAME_ROOT);
535 wcscat(Buffer, L"\\");
536 wcscat(Buffer, KeyInfo->Name);
537
538 if (!IopCreateUnicodeString(&Device->DeviceID, Buffer, PagedPool))
539 {
540 /* FIXME: */
541 DPRINT("IopCreateUnicodeString() failed\n");
542 }
543
544 DPRINT("Got entry: %S\n", Device->DeviceID.Buffer);
545
546 if (!IopCreateUnicodeString(
547 &Device->InstanceID,
548 L"0000",
549 PagedPool))
550 {
551 /* FIXME: */
552 DPRINT("IopCreateUnicodeString() failed\n");
553 }
554
555 Status = PnpRootFdoReadDeviceInfo(Device);
556 if (!NT_SUCCESS(Status))
557 {
558 DPRINT("PnpRootFdoReadDeviceInfo() failed with status %x\n", Status);
559 /* FIXME: */
560 }
561
562 ExInterlockedInsertTailList(
563 &DeviceExtension->DeviceListHead,
564 &Device->ListEntry,
565 &DeviceExtension->DeviceListLock);
566
567 DeviceExtension->DeviceListCount++;
568
569 Index++;
570 } while (TRUE);
571
572 DPRINT("Entries found: %d\n", Index);
573
574 NtClose(KeyHandle);
575
576 ExFreePool(KeyInfo);
577
578 return STATUS_SUCCESS;
579 }
580
581
582 NTSTATUS
583 PnpRootQueryBusRelations(
584 IN PDEVICE_OBJECT DeviceObject,
585 IN PIRP Irp,
586 IN PIO_STACK_LOCATION IrpSp)
587 {
588 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
589 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
590 PDEVICE_RELATIONS Relations;
591 PLIST_ENTRY CurrentEntry;
592 PPNPROOT_DEVICE Device;
593 NTSTATUS Status;
594 ULONG Size;
595 ULONG i;
596
597 DPRINT("Called\n");
598
599 Status = PnpRootFdoEnumerateDevices(DeviceObject);
600 if (!NT_SUCCESS(Status))
601 return Status;
602
603 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
604
605 if (Irp->IoStatus.Information)
606 {
607 /* FIXME: Another bus driver has already created a DEVICE_RELATIONS
608 structure so we must merge this structure with our own */
609 }
610
611 Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
612 (DeviceExtension->DeviceListCount - 1);
613
614 Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
615 if (!Relations)
616 return STATUS_INSUFFICIENT_RESOURCES;
617
618 Relations->Count = DeviceExtension->DeviceListCount;
619
620 i = 0;
621 CurrentEntry = DeviceExtension->DeviceListHead.Flink;
622 while (CurrentEntry != &DeviceExtension->DeviceListHead)
623 {
624 Device = CONTAINING_RECORD(CurrentEntry, PNPROOT_DEVICE, ListEntry);
625
626 if (!Device->Pdo)
627 {
628 /* Create a physical device object for the
629 device as it does not already have one */
630 Status = IoCreateDevice(
631 DeviceObject->DriverObject,
632 sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
633 NULL,
634 FILE_DEVICE_CONTROLLER,
635 0,
636 FALSE,
637 &Device->Pdo);
638 if (!NT_SUCCESS(Status))
639 {
640 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
641 ExFreePool(Relations);
642 return Status;
643 }
644
645 DPRINT("Created PDO %x\n", Device->Pdo);
646
647 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
648
649 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
650
651 //Device->Pdo->Flags |= DO_POWER_PAGABLE;
652
653 PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
654
655 RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));
656
657 PdoDeviceExtension->Common.IsFDO = FALSE;
658
659 PdoDeviceExtension->Common.DeviceObject = Device->Pdo;
660
661 PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;
662
663 if (!IopCreateUnicodeString(
664 &PdoDeviceExtension->DeviceID,
665 Device->DeviceID.Buffer,
666 PagedPool))
667 {
668 DPRINT("Insufficient resources\n");
669 /* FIXME: */
670 }
671
672 DPRINT("DeviceID: %S PDO %x\n",
673 PdoDeviceExtension->DeviceID.Buffer,
674 Device->Pdo);
675
676 if (!IopCreateUnicodeString(
677 &PdoDeviceExtension->InstanceID,
678 Device->InstanceID.Buffer,
679 PagedPool))
680 {
681 DPRINT("Insufficient resources\n");
682 /* FIXME: */
683 }
684
685 }
686
687 /* Reference the physical device object. The PnP manager
688 will dereference it again when it is no longer needed */
689 ObReferenceObject(Device->Pdo);
690
691 Relations->Objects[i] = Device->Pdo;
692
693 i++;
694
695 CurrentEntry = CurrentEntry->Flink;
696 }
697
698 if (NT_SUCCESS(Status))
699 {
700 Irp->IoStatus.Information = (ULONG_PTR)Relations;
701 }
702 else
703 {
704 Irp->IoStatus.Information = 0;
705 }
706
707 return Status;
708 }
709
710
711 NTSTATUS
712 PnpRootQueryDeviceRelations(
713 IN PDEVICE_OBJECT DeviceObject,
714 IN PIRP Irp,
715 IN PIO_STACK_LOCATION IrpSp)
716 {
717 NTSTATUS Status;
718
719 DPRINT("Called\n");
720
721 switch (IrpSp->Parameters.QueryDeviceRelations.Type) {
722 case BusRelations:
723 Status = PnpRootQueryBusRelations(DeviceObject, Irp, IrpSp);
724 break;
725
726 default:
727 Status = STATUS_NOT_IMPLEMENTED;
728 }
729
730 return Status;
731 }
732
733
734 NTSTATUS
735 STDCALL
736 PnpRootFdoPnpControl(
737 IN PDEVICE_OBJECT DeviceObject,
738 IN PIRP Irp)
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 {
748 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
749 PIO_STACK_LOCATION IrpSp;
750 NTSTATUS Status;
751
752 DPRINT("Called\n");
753
754 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
755
756 Status = Irp->IoStatus.Status;
757
758 IrpSp = IoGetCurrentIrpStackLocation(Irp);
759
760 switch (IrpSp->MinorFunction) {
761 case IRP_MN_QUERY_DEVICE_RELATIONS:
762 Status = PnpRootQueryDeviceRelations(DeviceObject, Irp, IrpSp);
763 break;
764
765 case IRP_MN_START_DEVICE:
766 DeviceExtension->State = dsStarted;
767 Status = STATUS_SUCCESS;
768 break;
769
770 case IRP_MN_STOP_DEVICE:
771 /* Root device cannot be stopped */
772 Status = STATUS_UNSUCCESSFUL;
773 break;
774
775 default:
776 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
777 Status = STATUS_NOT_IMPLEMENTED;
778 break;
779 }
780
781 if (Status != STATUS_PENDING) {
782 Irp->IoStatus.Status = Status;
783 IoCompleteRequest(Irp, IO_NO_INCREMENT);
784 }
785
786 DPRINT("Leaving. Status 0x%X\n", Status);
787
788 return Status;
789 }
790
791
792 NTSTATUS
793 STDCALL
794 PnpRootFdoPowerControl(
795 IN PDEVICE_OBJECT DeviceObject,
796 IN PIRP Irp)
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 {
806 PIO_STACK_LOCATION IrpSp;
807 NTSTATUS Status;
808
809 DPRINT("Called\n");
810
811 IrpSp = IoGetCurrentIrpStackLocation(Irp);
812
813 switch (IrpSp->MinorFunction) {
814 default:
815 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
816 Status = STATUS_NOT_IMPLEMENTED;
817 break;
818 }
819
820 if (Status != STATUS_PENDING) {
821 Irp->IoStatus.Status = Status;
822 IoCompleteRequest(Irp, IO_NO_INCREMENT);
823 }
824
825 DPRINT("Leaving. Status 0x%X\n", Status);
826
827 return Status;
828 }
829
830
831 NTSTATUS
832 STDCALL
833 PnpRootPnpControl(
834 IN PDEVICE_OBJECT DeviceObject,
835 IN PIRP Irp)
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 {
845 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
846 NTSTATUS Status;
847
848 DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
849
850 DPRINT("DeviceObject %x DeviceExtension %x IsFDO %d\n",
851 DeviceObject,
852 DeviceExtension,
853 DeviceExtension->IsFDO);
854
855 if (DeviceExtension->IsFDO) {
856 Status = PnpRootFdoPnpControl(DeviceObject, Irp);
857 } else {
858 Status = PnpRootPdoPnpControl(DeviceObject, Irp);
859 }
860
861 return Status;
862 }
863
864
865 NTSTATUS
866 STDCALL
867 PnpRootPowerControl(
868 IN PDEVICE_OBJECT DeviceObject,
869 IN PIRP Irp)
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 {
879 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension;
880 NTSTATUS Status;
881
882 DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
883
884 if (DeviceExtension->IsFDO) {
885 Status = PnpRootFdoPowerControl(DeviceObject, Irp);
886 } else {
887 Status = PnpRootPdoPowerControl(DeviceObject, Irp);
888 }
889
890 return Status;
891 }
892
893
894 NTSTATUS
895 STDCALL
896 PnpRootAddDevice(
897 IN PDRIVER_OBJECT DriverObject,
898 IN PDEVICE_OBJECT PhysicalDeviceObject)
899 {
900 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
901 NTSTATUS Status;
902
903 DPRINT("Called\n");
904
905 Status = IoCreateDevice(
906 DriverObject,
907 sizeof(PNPROOT_FDO_DEVICE_EXTENSION),
908 NULL,
909 FILE_DEVICE_BUS_EXTENDER,
910 FILE_DEVICE_SECURE_OPEN,
911 TRUE,
912 &PnpRootDeviceObject);
913 if (!NT_SUCCESS(Status)) {
914 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
915 }
916
917 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;
918
919 RtlZeroMemory(DeviceExtension, sizeof(PNPROOT_FDO_DEVICE_EXTENSION));
920
921 DeviceExtension->Common.IsFDO = TRUE;
922
923 DeviceExtension->State = dsStopped;
924
925 DeviceExtension->Ldo = IoAttachDeviceToDeviceStack(
926 PnpRootDeviceObject,
927 PhysicalDeviceObject);
928
929 if (!PnpRootDeviceObject) {
930 CPRINT("PnpRootDeviceObject 0x%X\n", PnpRootDeviceObject);
931 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
932 }
933
934 if (!PhysicalDeviceObject) {
935 CPRINT("PhysicalDeviceObject 0x%X\n", PhysicalDeviceObject);
936 KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
937 }
938
939 InitializeListHead(&DeviceExtension->DeviceListHead);
940
941 DeviceExtension->DeviceListCount = 0;
942
943 KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
944
945 PnpRootDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
946
947 //PnpRootDeviceObject->Flags |= DO_POWER_PAGABLE;
948
949 DPRINT("Done AddDevice()\n");
950
951 return STATUS_SUCCESS;
952 }
953
954
955 NTSTATUS
956 STDCALL
957 PnpRootDriverEntry(
958 IN PDRIVER_OBJECT DriverObject,
959 IN PUNICODE_STRING RegistryPath)
960 {
961 DPRINT("Called\n");
962
963 DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH) PnpRootPnpControl;
964 DriverObject->MajorFunction[IRP_MJ_POWER] = (PDRIVER_DISPATCH) PnpRootPowerControl;
965 DriverObject->DriverExtension->AddDevice = PnpRootAddDevice;
966
967 return STATUS_SUCCESS;
968 }
969
970 /* EOF */