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