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