merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / drivers / bus / serenum / fdo.c
1 /* $Id:
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS Serial enumerator driver
5 * FILE: drivers/bus/serenum/fdo.c
6 * PURPOSE: IRP_MJ_PNP operations for FDOs
7 *
8 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
9 */
10
11 #define NDEBUG
12 #include "serenum.h"
13
14 NTSTATUS STDCALL
15 SerenumAddDevice(
16 IN PDRIVER_OBJECT DriverObject,
17 IN PDEVICE_OBJECT Pdo)
18 {
19 PDEVICE_OBJECT Fdo;
20 PFDO_DEVICE_EXTENSION DeviceExtension;
21 NTSTATUS Status;
22
23 DPRINT("Serenum: SerenumAddDevice called. Pdo = %p\n", Pdo);
24
25 /* Create new device object */
26 Status = IoCreateDevice(DriverObject,
27 sizeof(FDO_DEVICE_EXTENSION),
28 NULL,
29 FILE_DEVICE_BUS_EXTENDER,
30 FILE_DEVICE_SECURE_OPEN,
31 FALSE,
32 &Fdo);
33 if (!NT_SUCCESS(Status))
34 {
35 DPRINT("Serenum: IoCreateDevice() failed with status 0x%08lx\n", Status);
36 return Status;
37 }
38 DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
39 RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
40
41 /* Register device interface */
42 Status = IoRegisterDeviceInterface(
43 Pdo,
44 &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR,
45 NULL,
46 &DeviceExtension->SerenumInterfaceName);
47 if (!NT_SUCCESS(Status))
48 {
49 DPRINT("Serenum: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status);
50 IoDeleteDevice(Fdo);
51 return Status;
52 }
53
54 DeviceExtension->Common.IsFDO = TRUE;
55 DeviceExtension->Common.PnpState = dsStopped;
56 DeviceExtension->Pdo = Pdo;
57 IoInitializeRemoveLock(&DeviceExtension->RemoveLock, SERENUM_TAG, 0, 0);
58 Fdo->Flags |= DO_POWER_PAGABLE;
59 Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
60 if (!NT_SUCCESS(Status))
61 {
62 DPRINT("Serenum: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
63 IoDeleteDevice(Fdo);
64 return Status;
65 }
66 Fdo->Flags |= DO_BUFFERED_IO;
67 Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
68
69 return STATUS_SUCCESS;
70 }
71
72 NTSTATUS STDCALL
73 SerenumFdoStartDevice(
74 IN PDEVICE_OBJECT DeviceObject,
75 IN PIRP Irp)
76 {
77 PFDO_DEVICE_EXTENSION DeviceExtension;
78 NTSTATUS Status;
79
80 DPRINT("Serenum: SerenumFdoStartDevice() called\n");
81 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
82
83 ASSERT(DeviceExtension->Common.PnpState == dsStopped);
84
85 Status = IoSetDeviceInterfaceState(&DeviceExtension->SerenumInterfaceName, TRUE);
86 if (!NT_SUCCESS(Status))
87 {
88 DPRINT("Serenum: IoSetDeviceInterfaceState() failed with status 0x%08lx\n", Status);
89 return Status;
90 }
91
92 DeviceExtension->Common.PnpState = dsStarted;
93
94 return STATUS_SUCCESS;
95 }
96
97 NTSTATUS
98 SerenumFdoQueryBusRelations(
99 IN PDEVICE_OBJECT DeviceObject,
100 OUT PDEVICE_RELATIONS* pDeviceRelations)
101 {
102 PFDO_DEVICE_EXTENSION DeviceExtension;
103 PDEVICE_RELATIONS DeviceRelations;
104 ULONG NumPDO;
105 ULONG i;
106 NTSTATUS Status = STATUS_SUCCESS;
107
108 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
109 ASSERT(DeviceExtension->Common.IsFDO);
110
111 /* Do enumeration if needed */
112 if (!(DeviceExtension->Flags & FLAG_ENUMERATION_DONE))
113 {
114 ASSERT(DeviceExtension->AttachedPdo == NULL);
115 /* Detect plug-and-play devices */
116 Status = SerenumDetectPnpDevice(DeviceObject, DeviceExtension->LowerDevice);
117 if (Status == STATUS_DEVICE_NOT_CONNECTED)
118 {
119 /* Detect legacy devices */
120 Status = SerenumDetectLegacyDevice(DeviceObject, DeviceExtension->LowerDevice);
121 if (Status == STATUS_DEVICE_NOT_CONNECTED)
122 Status = STATUS_SUCCESS;
123 }
124 DeviceExtension->Flags |= FLAG_ENUMERATION_DONE;
125 }
126 NumPDO = (DeviceExtension->AttachedPdo != NULL ? 1 : 0);
127
128 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(
129 PagedPool,
130 sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (NumPDO - 1),
131 SERENUM_TAG);
132 if (!DeviceRelations)
133 return STATUS_INSUFFICIENT_RESOURCES;
134
135 /* Fill returned structure */
136 DeviceRelations->Count = NumPDO;
137 for (i = 0; i < NumPDO; i++)
138 {
139 ObReferenceObject(DeviceExtension->AttachedPdo);
140 DeviceRelations->Objects[i] = DeviceExtension->AttachedPdo;
141 }
142
143 *pDeviceRelations = DeviceRelations;
144 return Status;
145 }
146
147 NTSTATUS
148 SerenumFdoPnp(
149 IN PDEVICE_OBJECT DeviceObject,
150 IN PIRP Irp)
151 {
152 ULONG MinorFunction;
153 PIO_STACK_LOCATION Stack;
154 ULONG_PTR Information = 0;
155 NTSTATUS Status;
156
157 Stack = IoGetCurrentIrpStackLocation(Irp);
158 MinorFunction = Stack->MinorFunction;
159
160 switch (MinorFunction)
161 {
162 /* FIXME: do all these minor functions
163 IRP_MN_QUERY_REMOVE_DEVICE 0x1
164 IRP_MN_REMOVE_DEVICE 0x2
165 IRP_MN_CANCEL_REMOVE_DEVICE 0x3
166 IRP_MN_STOP_DEVICE 0x4
167 IRP_MN_QUERY_STOP_DEVICE 0x5
168 IRP_MN_CANCEL_STOP_DEVICE 0x6
169 IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7
170 IRP_MN_QUERY_INTERFACE (optional) 0x8
171 IRP_MN_QUERY_CAPABILITIES (optional) 0x9
172 IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional or required) 0xb
173 IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
174 IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
175 IRP_MN_SURPRISE_REMOVAL 0x17
176 */
177 case IRP_MN_START_DEVICE: /* 0x0 */
178 {
179 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
180 /* Call lower driver */
181 Status = ForwardIrpAndWait(DeviceObject, Irp);
182 if (NT_SUCCESS(Status))
183 Status = SerenumFdoStartDevice(DeviceObject, Irp);
184 break;
185 }
186 case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x7 */
187 {
188 switch (Stack->Parameters.QueryDeviceRelations.Type)
189 {
190 case BusRelations:
191 {
192 PDEVICE_RELATIONS DeviceRelations;
193 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
194 Status = SerenumFdoQueryBusRelations(DeviceObject, &DeviceRelations);
195 Information = (ULONG_PTR)DeviceRelations;
196 break;
197 }
198 default:
199 DPRINT1("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
200 Stack->Parameters.QueryDeviceRelations.Type);
201 return ForwardIrpAndForget(DeviceObject, Irp);
202 }
203 break;
204 }
205 default:
206 {
207 DPRINT1("Serenum: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
208 return ForwardIrpAndForget(DeviceObject, Irp);
209 }
210 }
211
212 Irp->IoStatus.Information = Information;
213 Irp->IoStatus.Status = Status;
214 IoCompleteRequest(Irp, IO_NO_INCREMENT);
215 return Status;
216 }