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