2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS User I/O driver
5 * PURPOSE: IOCTL handling
6 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
15 CancelPacketRead(PIRP Irp
, PIO_STACK_LOCATION IrpSp
)
17 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= IrpSp
->FileObject
->FsContext
;
18 PNDISUIO_PACKET_ENTRY PacketEntry
;
21 /* Indicate a 0-byte packet on the queue so one read returns 0 */
22 PacketEntry
= ExAllocatePool(PagedPool
, sizeof(NDISUIO_PACKET_ENTRY
));
25 PacketEntry
->PacketLength
= 0;
27 ExInterlockedInsertTailList(&AdapterContext
->PacketList
,
28 &PacketEntry
->ListEntry
,
29 &AdapterContext
->Spinlock
);
31 KeSetEvent(&AdapterContext
->PacketReadEvent
, IO_NO_INCREMENT
, FALSE
);
33 Status
= STATUS_SUCCESS
;
37 Status
= STATUS_NO_MEMORY
;
40 Irp
->IoStatus
.Status
= Status
;
41 Irp
->IoStatus
.Information
= 0;
43 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
49 SetAdapterOid(PIRP Irp
, PIO_STACK_LOCATION IrpSp
)
51 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= IrpSp
->FileObject
->FsContext
;
52 PNDISUIO_SET_OID SetOidRequest
;
53 NDIS_REQUEST NdisRequest
;
57 Irp
->IoStatus
.Information
= 0;
59 SetOidRequest
= IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
60 RequestLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
61 if (QueryOidRequest
&& RequestLength
>= sizeof(NDIS_OID
))
63 /* Setup the NDIS request */
64 NdisRequest
.RequestType
= NdisRequestSetInformation
;
65 NdisRequest
.Oid
= SetOidRequest
->Oid
;
66 NdisRequest
.InformationBuffer
= SetOidRequest
->Data
;
67 NdisRequest
.InformationBufferLength
= RequestLength
- sizeof(NDIS_OID
);
69 /* Dispatch the request */
71 AdapterContext
->BindingHandle
,
74 /* Wait for the request */
75 if (Status
== NDIS_STATUS_PENDING
)
77 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
82 Status
= AdapterContext
->AsyncStatus
;
85 /* Return the bytes read */
86 if (NT_SUCCESS(Status
)) Irp
->IoStatus
.Information
= NdisRequest
.BytesRead
;
91 Status
= STATUS_INVALID_PARAMETER
;
94 Irp
->IoStatus
.Status
= Status
;
96 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
102 QueryAdapterOid(PIRP Irp
, PIO_STACK_LOCATION IrpSp
)
104 PNDISUIO_ADAPTER_CONTEXT AdapterContext
= IrpSp
->FileObject
->FsContext
;
105 PNDISUIO_QUERY_OID QueryOidRequest
;
106 NDIS_REQUEST NdisRequest
;
110 Irp
->IoStatus
.Information
= 0;
112 QueryOidRequest
= IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
113 RequestLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
114 if (QueryOidRequest
&& RequestLength
>= sizeof(NDIS_OID
))
116 /* Setup the NDIS request */
117 NdisRequest
.RequestType
= NdisRequestQueryInformation
;
118 NdisRequest
.Oid
= QueryOidRequest
->Oid
;
119 NdisRequest
.InformationBuffer
= QueryOidRequest
->Data
;
120 NdisRequest
.InformationBufferLength
= RequestLength
- sizeof(NDIS_OID
);
122 /* Dispatch the request */
124 AdapterContext
->BindingHandle
,
127 /* Wait for the request */
128 if (Status
== NDIS_STATUS_PENDING
)
130 KeWaitForSingleObject(&AdapterContext
->AsyncEvent
,
135 Status
= AdapterContext
->AsyncStatus
;
138 /* Return the bytes written */
139 if (NT_SUCCESS(Status
)) Irp
->IoStatus
.Information
= NdisRequest
.BytesWritten
;
144 Status
= STATUS_INVALID_PARAMETER
;
147 Irp
->IoStatus
.Status
= Status
;
149 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
155 OpenDeviceReadWrite(PIRP Irp
, PIO_STACK_LOCATION IrpSp
)
157 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
158 UNICODE_STRING DeviceName
;
161 PNDISUIO_ADAPTER_CONTEXT AdapterContext
;
162 PNDISUIO_OPEN_ENTRY OpenEntry
;
165 NameLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
168 DeviceName
.MaximumLength
= DeviceName
.Length
= NameLength
;
169 DeviceName
.Buffer
= IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
171 /* Check if this already has a context */
172 AdapterContext
= FindAdapterContextByName(&DeviceName
);
173 if (AdapterContext
!= NULL
)
175 /* Reference the adapter context */
176 KeAcquireSpinLock(&AdapterContext
->Spinlock
, &OldIrql
);
177 if (AdapterContext
->OpenCount
!= 0)
179 /* An open for read-write is exclusive,
180 * so we can't have any other open handles */
181 KeReleaseSpinLock(&AdapterContext
->Spinlock
, OldIrql
);
182 Status
= STATUS_INVALID_PARAMETER
;
186 /* Add a reference */
187 ReferenceAdapterContext(AdapterContext
);
188 Status
= STATUS_SUCCESS
;
193 /* Invalid device name */
194 Status
= STATUS_INVALID_PARAMETER
;
197 /* Check that the bind succeeded */
198 if (NT_SUCCESS(Status
))
200 OpenEntry
= ExAllocatePool(NonPagedPool
, sizeof(*OpenEntry
));
203 /* Set the file object pointer */
204 OpenEntry
->FileObject
= FileObject
;
206 /* Set the permissions */
207 OpenEntry
->WriteOnly
= FALSE
;
209 /* Associate this FO with the adapter */
210 FileObject
->FsContext
= AdapterContext
;
211 FileObject
->FsContext2
= OpenEntry
;
213 /* Add it to the adapter's list */
214 InsertTailList(&AdapterContext
->OpenEntryList
,
215 &OpenEntry
->ListEntry
);
218 KeReleaseSpinLock(&AdapterContext
->Spinlock
, OldIrql
);
219 Status
= STATUS_SUCCESS
;
223 /* Remove the reference we added */
224 KeReleaseSpinLock(&AdapterContext
->Spinlock
, OldIrql
);
225 DereferenceAdapterContext(AdapterContext
, NULL
);
226 Status
= STATUS_NO_MEMORY
;
232 /* Invalid device name */
233 Status
= STATUS_INVALID_PARAMETER
;
236 Irp
->IoStatus
.Status
= Status
;
237 Irp
->IoStatus
.Information
= 0;
239 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
245 OpenDeviceWrite(PIRP Irp
, PIO_STACK_LOCATION IrpSp
)
247 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
248 UNICODE_STRING DeviceName
;
251 PNDISUIO_ADAPTER_CONTEXT AdapterContext
;
252 PNDISUIO_OPEN_ENTRY OpenEntry
;
255 NameLength
= IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
258 DeviceName
.MaximumLength
= DeviceName
.Length
= NameLength
;
259 DeviceName
.Buffer
= IrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
261 /* Check if this already has a context */
262 AdapterContext
= FindAdapterContextByName(&DeviceName
);
263 if (AdapterContext
!= NULL
)
265 /* Reference the adapter context */
266 KeAcquireSpinLock(&AdapterContext
->Spinlock
, &OldIrql
);
267 ReferenceAdapterContext(AdapterContext
);
268 Status
= STATUS_SUCCESS
;
272 /* Invalid device name */
273 Status
= STATUS_INVALID_PARAMETER
;
276 /* Check that the bind succeeded */
277 if (NT_SUCCESS(Status
))
279 OpenEntry
= ExAllocatePool(NonPagedPool
, sizeof(*OpenEntry
));
282 /* Set the file object pointer */
283 OpenEntry
->FileObject
= FileObject
;
285 /* Associate this FO with the adapter */
286 FileObject
->FsContext
= AdapterContext
;
287 FileObject
->FsContext2
= OpenEntry
;
289 /* Set permissions */
290 OpenEntry
->WriteOnly
= TRUE
;
292 /* Add it to the adapter's list */
293 InsertTailList(&AdapterContext
->OpenEntryList
,
294 &OpenEntry
->ListEntry
);
297 KeReleaseSpinLock(&AdapterContext
->Spinlock
, OldIrql
);
298 Status
= STATUS_SUCCESS
;
302 /* Remove the reference we added */
303 KeReleaseSpinLock(&AdapterContext
->Spinlock
, OldIrql
);
304 DereferenceAdapterContext(AdapterContext
, NULL
);
305 Status
= STATUS_NO_MEMORY
;
311 /* Invalid device name */
312 Status
= STATUS_INVALID_PARAMETER
;
315 Irp
->IoStatus
.Status
= Status
;
316 Irp
->IoStatus
.Information
= 0;
318 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
325 NduDispatchDeviceControl(PDEVICE_OBJECT DeviceObject
,
328 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
329 PNDISUIO_OPEN_ENTRY OpenEntry
;
331 ASSERT(DeviceObject
== GlobalDeviceObject
);
333 /* Handle open IOCTLs first */
334 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
336 case IOCTL_NDISUIO_OPEN_DEVICE
:
337 return OpenDeviceReadWrite(Irp
, IrpSp
);
339 case IOCTL_NDISUIO_OPEN_WRITE_DEVICE
:
340 return OpenDeviceWrite(Irp
, IrpSp
);
343 /* Fail if this file object has no adapter associated */
344 if (IrpSp
->FileObject
->FsContext
== NULL
)
346 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
347 Irp
->IoStatus
.Information
= 0;
348 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
350 return STATUS_INVALID_PARAMETER
;
353 /* Now handle write IOCTLs */
354 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
356 case IOCTL_NDISUIO_SET_OID_VALUE
:
357 return SetAdapterOid(Irp
, IrpSp
);
360 /* Check that we have read permissions */
361 OpenEntry
= IrpSp
->FileObject
->FsContext2
;
362 if (OpenEntry
->WriteOnly
)
364 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
365 Irp
->IoStatus
.Information
= 0;
366 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
368 return STATUS_INVALID_PARAMETER
;
371 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
373 case IOCTL_CANCEL_READ
:
374 return CancelPacketRead(Irp
, IrpSp
);
376 case IOCTL_NDISUIO_QUERY_OID_VALUE
:
377 return QueryAdapterOid(Irp
, IrpSp
);
380 DPRINT1("Unimplemented\n");
381 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
382 Irp
->IoStatus
.Information
= 0;
383 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);