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 ReferenceAdapterContext(AdapterContext
);
178 Status
= STATUS_SUCCESS
;
182 /* Invalid device name */
183 Status
= STATUS_INVALID_PARAMETER
;
186 /* Check that the bind succeeded */
187 if (NT_SUCCESS(Status
))
189 OpenEntry
= ExAllocatePool(NonPagedPool
, sizeof(*OpenEntry
));
192 /* Set the file object pointer */
193 OpenEntry
->FileObject
= FileObject
;
195 /* Associate this FO with the adapter */
196 FileObject
->FsContext
= AdapterContext
;
197 FileObject
->FsContext2
= OpenEntry
;
199 /* Add it to the adapter's list */
200 InsertTailList(&AdapterContext
->OpenEntryList
,
201 &OpenEntry
->ListEntry
);
204 KeReleaseSpinLock(&AdapterContext
->Spinlock
, OldIrql
);
205 Status
= STATUS_SUCCESS
;
209 /* Remove the reference we added */
210 KeReleaseSpinLock(&AdapterContext
->Spinlock
, OldIrql
);
211 DereferenceAdapterContext(AdapterContext
, NULL
);
212 Status
= STATUS_NO_MEMORY
;
218 /* Invalid device name */
219 Status
= STATUS_INVALID_PARAMETER
;
222 Irp
->IoStatus
.Status
= Status
;
223 Irp
->IoStatus
.Information
= 0;
225 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
231 OpenDeviceWrite(PIRP Irp
, PIO_STACK_LOCATION IrpSp
)
233 /* FIXME: Handle this correctly */
234 return OpenDeviceReadWrite(Irp
, IrpSp
);
239 NduDispatchDeviceControl(PDEVICE_OBJECT DeviceObject
,
242 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
244 ASSERT(DeviceObject
== GlobalDeviceObject
);
246 /* Handle open IOCTLs first */
247 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
249 case IOCTL_NDISUIO_OPEN_DEVICE
:
250 return OpenDeviceReadWrite(Irp
, IrpSp
);
252 case IOCTL_NDISUIO_OPEN_WRITE_DEVICE
:
253 return OpenDeviceWrite(Irp
, IrpSp
);
256 /* Fail if this file object has no adapter associated */
257 if (IrpSp
->FileObject
->FsContext
== NULL
)
259 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
260 Irp
->IoStatus
.Information
= 0;
261 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
263 return STATUS_INVALID_PARAMETER
;
266 /* Now handle other IOCTLs */
267 switch (IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
)
269 case IOCTL_CANCEL_READ
:
270 return CancelPacketRead(Irp
, IrpSp
);
272 case IOCTL_NDISUIO_QUERY_OID_VALUE
:
273 return QueryAdapterOid(Irp
, IrpSp
);
275 case IOCTL_NDISUIO_SET_OID_VALUE
:
276 return SetAdapterOid(Irp
, IrpSp
);
279 DPRINT1("Unimplemented\n");
280 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
281 Irp
->IoStatus
.Information
= 0;
282 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);