merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / drivers / bus / serenum / pdo.c
1 /* $Id:
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS Serial enumerator driver
5 * FILE: drivers/bus/serenum/pdo.c
6 * PURPOSE: IRP_MJ_PNP operations for PDOs
7 *
8 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
9 */
10
11 #define NDEBUG
12 #include "serenum.h"
13
14 static NTSTATUS
15 SerenumPdoStartDevice(
16 IN PDEVICE_OBJECT DeviceObject)
17 {
18 PPDO_DEVICE_EXTENSION DeviceExtension;
19
20 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
21
22 ASSERT(DeviceExtension->Common.PnpState == dsStopped);
23
24 DeviceExtension->Common.PnpState = dsStarted;
25 return STATUS_SUCCESS;
26 }
27
28 static NTSTATUS
29 SerenumPdoQueryId(
30 IN PDEVICE_OBJECT DeviceObject,
31 IN PIRP Irp,
32 OUT ULONG_PTR* Information)
33 {
34 PPDO_DEVICE_EXTENSION DeviceExtension;
35 ULONG IdType;
36 PUNICODE_STRING SourceString;
37 UNICODE_STRING String;
38 NTSTATUS Status;
39
40 IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
41 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
42 RtlInitUnicodeString(&String, NULL);
43
44 switch (IdType)
45 {
46 case BusQueryDeviceID:
47 {
48 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
49 SourceString = &DeviceExtension->DeviceId;
50 break;
51 }
52 case BusQueryHardwareIDs:
53 {
54 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
55 SourceString = &DeviceExtension->HardwareIds;
56 break;
57 }
58 case BusQueryCompatibleIDs:
59 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
60 SourceString = &DeviceExtension->CompatibleIds;
61 break;
62 case BusQueryInstanceID:
63 {
64 /* We don't have any instance id to report, and
65 * this query is optional, so ignore it.
66 */
67 *Information = Irp->IoStatus.Information;
68 return Irp->IoStatus.Status;
69 }
70 default:
71 DPRINT1("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
72 return STATUS_NOT_SUPPORTED;
73 }
74
75 Status = SerenumDuplicateUnicodeString(
76 &String,
77 SourceString,
78 PagedPool);
79 *Information = (ULONG_PTR)String.Buffer;
80 return Status;
81 }
82
83 static NTSTATUS
84 SerenumPdoQueryDeviceRelations(
85 IN PDEVICE_OBJECT DeviceObject,
86 OUT PDEVICE_RELATIONS* pDeviceRelations)
87 {
88 PFDO_DEVICE_EXTENSION DeviceExtension;
89 PDEVICE_RELATIONS DeviceRelations;
90
91 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
92 ASSERT(DeviceExtension->Common.IsFDO);
93
94 DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(
95 PagedPool,
96 sizeof(DEVICE_RELATIONS),
97 SERENUM_TAG);
98 if (!DeviceRelations)
99 return STATUS_INSUFFICIENT_RESOURCES;
100
101 ObReferenceObject(DeviceObject);
102 DeviceRelations->Count = 1;
103 DeviceRelations->Objects[0] = DeviceObject;
104
105 *pDeviceRelations = DeviceRelations;
106 return STATUS_SUCCESS;
107 }
108
109 NTSTATUS
110 SerenumPdoPnp(
111 IN PDEVICE_OBJECT DeviceObject,
112 IN PIRP Irp)
113 {
114 ULONG MinorFunction;
115 PIO_STACK_LOCATION Stack;
116 ULONG_PTR Information = 0;
117 NTSTATUS Status;
118
119 Stack = IoGetCurrentIrpStackLocation(Irp);
120 MinorFunction = Stack->MinorFunction;
121
122 switch (MinorFunction)
123 {
124 /* FIXME: do all these minor functions
125 IRP_MN_QUERY_REMOVE_DEVICE 0x1
126 IRP_MN_REMOVE_DEVICE 0x2
127 IRP_MN_CANCEL_REMOVE_DEVICE 0x3
128 IRP_MN_STOP_DEVICE 0x4
129 IRP_MN_QUERY_STOP_DEVICE 0x5
130 IRP_MN_CANCEL_STOP_DEVICE 0x6
131 IRP_MN_QUERY_DEVICE_RELATIONS / EjectionRelations (optional) 0x7
132 IRP_MN_QUERY_INTERFACE (required or optional) 0x8
133 IRP_MN_READ_CONFIG (required or optional) 0xf
134 IRP_MN_WRITE_CONFIG (required or optional) 0x10
135 IRP_MN_EJECT (required or optional) 0x11
136 IRP_MN_SET_LOCK (required or optional) 0x12
137 IRP_MN_QUERY_ID / BusQueryDeviceID 0x13
138 IRP_MN_QUERY_ID / BusQueryCompatibleIDs (optional) 0x13
139 IRP_MN_QUERY_ID / BusQueryInstanceID (optional) 0x13
140 IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
141 IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
142 IRP_MN_SURPRISE_REMOVAL 0x17
143 */
144 case IRP_MN_START_DEVICE: /* 0x0 */
145 {
146 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
147 Status = SerenumPdoStartDevice(DeviceObject);
148 break;
149 }
150 case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x7 */
151 {
152 switch (Stack->Parameters.QueryDeviceRelations.Type)
153 {
154 case RemovalRelations:
155 {
156 return ForwardIrpToAttachedFdoAndForget(DeviceObject, Irp);
157 }
158 case TargetDeviceRelation:
159 {
160 PDEVICE_RELATIONS DeviceRelations = NULL;
161 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
162 Status = SerenumPdoQueryDeviceRelations(DeviceObject, &DeviceRelations);
163 Information = (ULONG_PTR)DeviceRelations;
164 break;
165 }
166 default:
167 {
168 DPRINT1("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
169 Stack->Parameters.QueryDeviceRelations.Type);
170 Status = STATUS_NOT_IMPLEMENTED;
171 break;
172 }
173 }
174 break;
175 }
176 case IRP_MN_QUERY_CAPABILITIES: /* 0x9 */
177 {
178 PDEVICE_CAPABILITIES DeviceCapabilities;
179 ULONG i;
180 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
181
182 DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
183 /* FIXME: capabilities can change with connected device */
184 DeviceCapabilities->LockSupported = FALSE;
185 DeviceCapabilities->EjectSupported = FALSE;
186 DeviceCapabilities->Removable = TRUE;
187 DeviceCapabilities->DockDevice = FALSE;
188 DeviceCapabilities->UniqueID = FALSE;
189 DeviceCapabilities->SilentInstall = FALSE;
190 DeviceCapabilities->RawDeviceOK = TRUE;
191 DeviceCapabilities->SurpriseRemovalOK = TRUE;
192 DeviceCapabilities->HardwareDisabled = FALSE; /* FIXME */
193 //DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */
194 DeviceCapabilities->DeviceState[0] = PowerDeviceD0; /* FIXME */
195 for (i = 0; i < PowerSystemMaximum; i++)
196 DeviceCapabilities->DeviceState[i] = PowerDeviceD3; /* FIXME */
197 //DeviceCapabilities->DeviceWake = PowerDeviceUndefined; /* FIXME */
198 DeviceCapabilities->D1Latency = 0; /* FIXME */
199 DeviceCapabilities->D2Latency = 0; /* FIXME */
200 DeviceCapabilities->D3Latency = 0; /* FIXME */
201 Status = STATUS_SUCCESS;
202 break;
203 }
204 case IRP_MN_QUERY_RESOURCES: /* 0xa */
205 {
206 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
207 /* Serial devices don't need resources, except the ones of
208 * the serial port. This PDO is the serial device PDO, so
209 * report no resource by not changing Information and
210 * Status
211 */
212 Information = Irp->IoStatus.Information;
213 Status = Irp->IoStatus.Status;
214 break;
215 }
216 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0xb */
217 {
218 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
219 /* Serial devices don't need resources, except the ones of
220 * the serial port. This PDO is the serial device PDO, so
221 * report no resource by not changing Information and
222 * Status
223 */
224 Information = Irp->IoStatus.Information;
225 Status = Irp->IoStatus.Status;
226 break;
227 }
228 case IRP_MN_QUERY_DEVICE_TEXT: /* 0xc */
229 {
230 switch (Stack->Parameters.QueryDeviceText.DeviceTextType)
231 {
232 case DeviceTextDescription:
233 {
234 PUNICODE_STRING Source;
235 PWSTR Description;
236 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
237
238 Source = &((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->DeviceDescription;
239 Description = ExAllocatePool(PagedPool, Source->Length + sizeof(WCHAR));
240 if (!Description)
241 Status = STATUS_INSUFFICIENT_RESOURCES;
242 else
243 {
244 RtlCopyMemory(Description, Source->Buffer, Source->Length);
245 Description[Source->Length / sizeof(WCHAR)] = L'\0';
246 Information = (ULONG_PTR)Description;
247 Status = STATUS_SUCCESS;
248 }
249 break;
250 }
251 case DeviceTextLocationInformation:
252 {
253 /* We don't have any text location to report,
254 * and this query is optional, so ignore it.
255 */
256 Information = Irp->IoStatus.Information;
257 Status = Irp->IoStatus.Status;
258 break;
259 }
260 default:
261 {
262 DPRINT1("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown type 0x%lx\n",
263 Stack->Parameters.QueryDeviceText.DeviceTextType);
264 Status = STATUS_NOT_SUPPORTED;
265 }
266 }
267 break;
268 }
269 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0xd */
270 {
271 return ForwardIrpToAttachedFdoAndForget(DeviceObject, Irp);
272 }
273 case IRP_MN_QUERY_ID: /* 0x13 */
274 {
275 Status = SerenumPdoQueryId(DeviceObject, Irp, &Information);
276 break;
277 }
278 case IRP_MN_QUERY_BUS_INFORMATION: /* 0x15 */
279 {
280 PPNP_BUS_INFORMATION BusInfo;
281 DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
282
283 BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
284 if (!BusInfo)
285 Status = STATUS_INSUFFICIENT_RESOURCES;
286 else
287 {
288 BusInfo->BusTypeGuid = GUID_BUS_TYPE_SERENUM;
289 /* FIXME: real value should be PNPBus, but PNPBus seems to be
290 * the only value in INTERFACE_TYPE enum that doesn't work...
291 */
292 BusInfo->LegacyBusType = PNPISABus;
293 /* We're the only serial bus enumerator on the computer */
294 BusInfo->BusNumber = 0;
295 Information = (ULONG_PTR)BusInfo;
296 Status = STATUS_SUCCESS;
297 }
298 break;
299 }
300 default:
301 {
302 /* We can't forward request to the lower driver, because
303 * we are a Pdo, so we don't have lower driver... */
304 DPRINT1("Serenum: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
305 Information = Irp->IoStatus.Information;
306 Status = Irp->IoStatus.Status;
307 }
308 }
309
310 Irp->IoStatus.Information = Information;
311 Irp->IoStatus.Status = Status;
312 IoCompleteRequest(Irp, IO_NO_INCREMENT);
313 return Status;
314 }