[TASKMGR] Process page: Allow using "Open File Location" functionality without runnin...
[reactos.git] / drivers / bus / isapnp / pdo.c
1 /*
2 * PROJECT: ReactOS ISA PnP Bus driver
3 * FILE: pdo.c
4 * PURPOSE: PDO-specific code
5 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
6 * Hervé Poussineau
7 */
8
9 #include <isapnp.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 NTSTATUS
15 NTAPI
16 IsaPdoQueryDeviceRelations(
17 IN PISAPNP_PDO_EXTENSION PdoExt,
18 IN PIRP Irp,
19 IN PIO_STACK_LOCATION IrpSp)
20 {
21 PDEVICE_RELATIONS DeviceRelations;
22
23 if (IrpSp->Parameters.QueryDeviceRelations.Type == RemovalRelations &&
24 PdoExt->Common.Self == PdoExt->FdoExt->DataPortPdo)
25 {
26 return IsaPnpFillDeviceRelations(PdoExt->FdoExt, Irp, FALSE);
27 }
28
29 if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
30 return Irp->IoStatus.Status;
31
32 DeviceRelations = ExAllocatePool(PagedPool, sizeof(*DeviceRelations));
33 if (!DeviceRelations)
34 return STATUS_NO_MEMORY;
35
36 DeviceRelations->Count = 1;
37 DeviceRelations->Objects[0] = PdoExt->Common.Self;
38 ObReferenceObject(PdoExt->Common.Self);
39
40 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
41
42 return STATUS_SUCCESS;
43 }
44
45 NTSTATUS
46 NTAPI
47 IsaPdoQueryCapabilities(
48 IN PISAPNP_PDO_EXTENSION PdoExt,
49 IN PIRP Irp,
50 IN PIO_STACK_LOCATION IrpSp)
51 {
52 PDEVICE_CAPABILITIES DeviceCapabilities;
53 PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice;
54 ULONG i;
55
56 DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
57 if (DeviceCapabilities->Version != 1)
58 return STATUS_REVISION_MISMATCH;
59
60 if (LogDev)
61 {
62 DeviceCapabilities->UniqueID = TRUE;
63 DeviceCapabilities->Address = LogDev->CSN;
64 }
65 else
66 {
67 DeviceCapabilities->UniqueID = FALSE;
68 DeviceCapabilities->RawDeviceOK = TRUE;
69 DeviceCapabilities->SilentInstall = TRUE;
70 }
71
72 for (i = 0; i < POWER_SYSTEM_MAXIMUM; i++)
73 DeviceCapabilities->DeviceState[i] = PowerDeviceD3;
74 DeviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
75
76 return STATUS_SUCCESS;
77 }
78
79 NTSTATUS
80 NTAPI
81 IsaPdoQueryPnpDeviceState(
82 IN PISAPNP_PDO_EXTENSION PdoExt,
83 IN PIRP Irp,
84 IN PIO_STACK_LOCATION IrpSp)
85 {
86 Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
87 return STATUS_SUCCESS;
88 }
89
90 NTSTATUS
91 NTAPI
92 IsaPdoQueryId(
93 IN PISAPNP_PDO_EXTENSION PdoExt,
94 IN PIRP Irp,
95 IN PIO_STACK_LOCATION IrpSp)
96 {
97 PUNICODE_STRING Source;
98 PWCHAR Buffer;
99
100 switch (IrpSp->Parameters.QueryId.IdType)
101 {
102 case BusQueryDeviceID:
103 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
104 Source = &PdoExt->DeviceID;
105 break;
106
107 case BusQueryHardwareIDs:
108 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
109 Source = &PdoExt->HardwareIDs;
110 break;
111
112 case BusQueryCompatibleIDs:
113 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
114 Source = &PdoExt->CompatibleIDs;
115 break;
116
117 case BusQueryInstanceID:
118 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
119 Source = &PdoExt->InstanceID;
120 break;
121
122 default:
123 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n",
124 IrpSp->Parameters.QueryId.IdType);
125 return Irp->IoStatus.Status;
126 }
127
128 if (!Source->Buffer)
129 return Irp->IoStatus.Status;
130
131 Buffer = ExAllocatePool(PagedPool, Source->MaximumLength);
132 if (!Buffer)
133 return STATUS_NO_MEMORY;
134
135 RtlCopyMemory(Buffer, Source->Buffer, Source->MaximumLength);
136 Irp->IoStatus.Information = (ULONG_PTR)Buffer;
137 return STATUS_SUCCESS;
138 }
139
140 NTSTATUS
141 NTAPI
142 IsaPdoQueryResources(
143 IN PISAPNP_PDO_EXTENSION PdoExt,
144 IN PIRP Irp,
145 IN PIO_STACK_LOCATION IrpSp)
146 {
147 ULONG ListSize;
148 PCM_RESOURCE_LIST ResourceList;
149
150 if (!PdoExt->ResourceList)
151 return Irp->IoStatus.Status;
152
153 ListSize = PdoExt->ResourceListSize;
154 ResourceList = ExAllocatePool(PagedPool, ListSize);
155 if (!ResourceList)
156 return STATUS_NO_MEMORY;
157
158 RtlCopyMemory(ResourceList, PdoExt->ResourceList, ListSize);
159 Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
160 return STATUS_SUCCESS;
161 }
162
163 NTSTATUS
164 NTAPI
165 IsaPdoQueryResourceRequirements(
166 IN PISAPNP_PDO_EXTENSION PdoExt,
167 IN PIRP Irp,
168 IN PIO_STACK_LOCATION IrpSp)
169 {
170 ULONG ListSize;
171 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
172
173 if (!PdoExt->RequirementsList)
174 return Irp->IoStatus.Status;
175
176 ListSize = PdoExt->RequirementsList->ListSize;
177 RequirementsList = ExAllocatePool(PagedPool, ListSize);
178 if (!RequirementsList)
179 return STATUS_NO_MEMORY;
180
181 RtlCopyMemory(RequirementsList, PdoExt->RequirementsList, ListSize);
182 Irp->IoStatus.Information = (ULONG_PTR)RequirementsList;
183 return STATUS_SUCCESS;
184 }
185
186 static
187 NTSTATUS
188 NTAPI
189 IsaPdoStartReadPort(
190 IN PISAPNP_FDO_EXTENSION FdoExt,
191 IN PIO_STACK_LOCATION IrpSp)
192 {
193 PCM_RESOURCE_LIST ResourceList = IrpSp->Parameters.StartDevice.AllocatedResources;
194 NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
195 KIRQL OldIrql;
196 ULONG i;
197
198 if (!ResourceList || ResourceList->Count != 1)
199 {
200 DPRINT1("No resource list (%p) or bad count (%d)\n", ResourceList, ResourceList ? ResourceList->Count : 0);
201 return STATUS_INSUFFICIENT_RESOURCES;
202 }
203 if (ResourceList->List[0].PartialResourceList.Version != 1
204 || ResourceList->List[0].PartialResourceList.Revision != 1)
205 {
206 DPRINT1("Bad resource list version (%d.%d)\n", ResourceList->List[0].PartialResourceList.Version, ResourceList->List[0].PartialResourceList.Revision);
207 return STATUS_REVISION_MISMATCH;
208 }
209 for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++)
210 {
211 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
212 if (PartialDescriptor->Type == CmResourceTypePort && PartialDescriptor->u.Port.Length > 1 && !FdoExt->ReadDataPort)
213 {
214 PUCHAR ReadDataPort = ULongToPtr(PartialDescriptor->u.Port.Start.u.LowPart + 3);
215 if (NT_SUCCESS(IsaHwTryReadDataPort(ReadDataPort)))
216 {
217 /* we detected some ISAPNP cards */
218 FdoExt->ReadDataPort = ReadDataPort;
219 KeAcquireSpinLock(&FdoExt->Lock, &OldIrql);
220 Status = IsaHwFillDeviceList(FdoExt);
221 KeReleaseSpinLock(&FdoExt->Lock, OldIrql);
222 if (FdoExt->DeviceCount > 0)
223 {
224 IoInvalidateDeviceRelations(FdoExt->Pdo, BusRelations);
225 IoInvalidateDeviceRelations(FdoExt->DataPortPdo, RemovalRelations);
226 }
227 }
228 else
229 {
230 /* mark read data port as started, even if no card has been detected */
231 Status = STATUS_SUCCESS;
232 }
233 }
234 }
235 return Status;
236 }
237
238 static
239 NTSTATUS
240 NTAPI
241 IsaPdoOnRepeaterComplete(
242 IN PDEVICE_OBJECT Tdo,
243 IN PIRP SubIrp,
244 PVOID NeedsVote)
245 {
246 PIO_STACK_LOCATION SubStack = IoGetCurrentIrpStackLocation(SubIrp);
247 PIRP Irp = (PIRP)SubStack->Parameters.Others.Argument1;
248 ObDereferenceObject(Tdo);
249
250 if (SubIrp->IoStatus.Status == STATUS_NOT_SUPPORTED)
251 {
252 if (NeedsVote)
253 {
254 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
255 }
256 }
257 else
258 {
259 Irp->IoStatus = SubIrp->IoStatus;
260 }
261
262 IoFreeIrp(SubIrp);
263 IoCompleteRequest(Irp, IO_NO_INCREMENT);
264 return STATUS_MORE_PROCESSING_REQUIRED;
265 }
266
267 NTSTATUS
268 NTAPI
269 IsaPdoRepeatRequest(
270 IN PISAPNP_PDO_EXTENSION PdoExt,
271 IN PIRP Irp,
272 IN BOOLEAN NeedsVote)
273 {
274 PDEVICE_OBJECT Fdo = PdoExt->FdoExt->Common.Self;
275 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
276
277 PDEVICE_OBJECT Tdo = IoGetAttachedDeviceReference(Fdo);
278 PIRP SubIrp = IoAllocateIrp(Tdo->StackSize + 1, FALSE);
279 PIO_STACK_LOCATION SubStack = IoGetNextIrpStackLocation(SubIrp);
280
281 SubStack->DeviceObject = Tdo;
282 SubStack->Parameters.Others.Argument1 = (PVOID)Irp;
283
284 IoSetNextIrpStackLocation(SubIrp);
285 SubStack = IoGetNextIrpStackLocation(SubIrp);
286 RtlCopyMemory(SubStack, Stack, FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine));
287 SubStack->Control = 0;
288 IoSetCompletionRoutine(SubIrp, IsaPdoOnRepeaterComplete, (PVOID)(ULONG_PTR)NeedsVote, TRUE, TRUE, TRUE);
289
290 SubIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
291 IoMarkIrpPending(Irp);
292 IoCallDriver(Tdo, SubIrp);
293 return STATUS_PENDING;
294 }
295
296 NTSTATUS
297 NTAPI
298 IsaPdoPnp(
299 IN PISAPNP_PDO_EXTENSION PdoExt,
300 IN PIRP Irp,
301 IN PIO_STACK_LOCATION IrpSp)
302 {
303 NTSTATUS Status = Irp->IoStatus.Status;
304
305 switch (IrpSp->MinorFunction)
306 {
307 case IRP_MN_START_DEVICE:
308 if (PdoExt->IsaPnpDevice)
309 Status = IsaHwActivateDevice(PdoExt->IsaPnpDevice);
310 else
311 Status = IsaPdoStartReadPort(PdoExt->FdoExt, IrpSp);
312
313 if (NT_SUCCESS(Status))
314 PdoExt->Common.State = dsStarted;
315 break;
316
317 case IRP_MN_STOP_DEVICE:
318 if (PdoExt->IsaPnpDevice)
319 Status = IsaHwDeactivateDevice(PdoExt->IsaPnpDevice);
320 else
321 Status = STATUS_SUCCESS;
322
323 if (NT_SUCCESS(Status))
324 PdoExt->Common.State = dsStopped;
325 break;
326
327 case IRP_MN_QUERY_DEVICE_RELATIONS:
328 Status = IsaPdoQueryDeviceRelations(PdoExt, Irp, IrpSp);
329 break;
330
331 case IRP_MN_QUERY_CAPABILITIES:
332 Status = IsaPdoQueryCapabilities(PdoExt, Irp, IrpSp);
333 break;
334
335 case IRP_MN_QUERY_PNP_DEVICE_STATE:
336 if (PdoExt->Common.Self == PdoExt->FdoExt->DataPortPdo)
337 Status = IsaPdoQueryPnpDeviceState(PdoExt, Irp, IrpSp);
338 break;
339
340 case IRP_MN_QUERY_RESOURCES:
341 Status = IsaPdoQueryResources(PdoExt, Irp, IrpSp);
342 break;
343
344 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
345 Status = IsaPdoQueryResourceRequirements(PdoExt, Irp, IrpSp);
346 break;
347
348 case IRP_MN_QUERY_ID:
349 Status = IsaPdoQueryId(PdoExt, Irp, IrpSp);
350 break;
351
352 case IRP_MN_QUERY_REMOVE_DEVICE:
353 case IRP_MN_REMOVE_DEVICE:
354 case IRP_MN_CANCEL_REMOVE_DEVICE:
355 case IRP_MN_QUERY_STOP_DEVICE:
356 case IRP_MN_CANCEL_STOP_DEVICE:
357 case IRP_MN_QUERY_DEVICE_TEXT:
358 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
359 case IRP_MN_SURPRISE_REMOVAL:
360 Status = STATUS_SUCCESS;
361 break;
362
363 case IRP_MN_READ_CONFIG:
364 case IRP_MN_WRITE_CONFIG:
365 case IRP_MN_EJECT:
366 case IRP_MN_SET_LOCK:
367 case IRP_MN_QUERY_BUS_INFORMATION:
368 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
369 return IsaPdoRepeatRequest(PdoExt, Irp, TRUE);
370
371 default:
372 DPRINT1("Unknown PnP code: %x\n", IrpSp->MinorFunction);
373 break;
374 }
375
376 Irp->IoStatus.Status = Status;
377 IoCompleteRequest(Irp, IO_NO_INCREMENT);
378
379 return Status;
380 }