91665eb395108d18ec75692c60a5ade478365de1
[reactos.git] / drivers / network / ndisuio / ioctl.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS User I/O driver
4 * FILE: ioctl.c
5 * PURPOSE: IOCTL handling
6 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
7 */
8
9 #include "ndisuio.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 NTSTATUS
15 SetAdapterOid(PIRP Irp, PIO_STACK_LOCATION IrpSp)
16 {
17 PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
18 PNDISUIO_SET_OID SetOidRequest;
19 NDIS_REQUEST NdisRequest;
20 ULONG RequestLength;
21 NDIS_STATUS Status;
22
23 Irp->IoStatus.Information = 0;
24
25 SetOidRequest = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
26 RequestLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
27 if (QueryOidRequest && RequestLength >= sizeof(NDIS_OID))
28 {
29 /* Setup the NDIS request */
30 NdisRequest.RequestType = NdisRequestSetInformation;
31 NdisRequest.Oid = SetOidRequest->Oid;
32 NdisRequest.InformationBuffer = SetOidRequest->Data;
33 NdisRequest.InformationBufferLength = RequestLength - sizeof(NDIS_OID);
34
35 /* Dispatch the request */
36 NdisRequest(&Status,
37 AdapterContext->BindingHandle,
38 &NdisRequest);
39
40 /* Wait for the request */
41 if (Status == NDIS_STATUS_PENDING)
42 {
43 KeWaitForSingleObject(&AdapterContext->AsyncEvent,
44 Executive,
45 KernelMode,
46 FALSE,
47 NULL);
48 Status = AdapterContext->AsyncStatus;
49 }
50
51 /* Return the bytes read */
52 if (NT_SUCCESS(Status)) Irp->IoStatus.Information = NdisRequest.BytesRead;
53 }
54 else
55 {
56 /* Bad parameters */
57 Status = STATUS_INVALID_PARAMETER;
58 }
59
60 Irp->IoStatus.Status = Status;
61
62 IoCompleteRequest(Irp, IO_NO_INCREMENT);
63
64 return Status;
65 }
66
67 NTSTATUS
68 QueryAdapterOid(PIRP Irp, PIO_STACK_LOCATION IrpSp)
69 {
70 PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
71 PNDISUIO_QUERY_OID QueryOidRequest;
72 NDIS_REQUEST NdisRequest;
73 ULONG RequestLength;
74 NDIS_STATUS Status;
75
76 Irp->IoStatus.Information = 0;
77
78 QueryOidRequest = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
79 RequestLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
80 if (QueryOidRequest && RequestLength >= sizeof(NDIS_OID))
81 {
82 /* Setup the NDIS request */
83 NdisRequest.RequestType = NdisRequestQueryInformation;
84 NdisRequest.Oid = QueryOidRequest->Oid;
85 NdisRequest.InformationBuffer = QueryOidRequest->Data;
86 NdisRequest.InformationBufferLength = RequestLength - sizeof(NDIS_OID);
87
88 /* Dispatch the request */
89 NdisRequest(&Status,
90 AdapterContext->BindingHandle,
91 &NdisRequest);
92
93 /* Wait for the request */
94 if (Status == NDIS_STATUS_PENDING)
95 {
96 KeWaitForSingleObject(&AdapterContext->AsyncEvent,
97 Executive,
98 KernelMode,
99 FALSE,
100 NULL);
101 Status = AdapterContext->AsyncStatus;
102 }
103
104 /* Return the bytes written */
105 if (NT_SUCCESS(Status)) Irp->IoStatus.Information = NdisRequest.BytesWritten;
106 }
107 else
108 {
109 /* Bad parameters */
110 Status = STATUS_INVALID_PARAMETER;
111 }
112
113 Irp->IoStatus.Status = Status;
114
115 IoCompleteRequest(Irp, IO_NO_INCREMENT);
116
117 return Status;
118 }
119
120 NTSTATUS
121 OpenDeviceReadWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp)
122 {
123 PFILE_OBJECT FileObject = IrpSp->FileObject;
124 UNICODE_STRING DeviceName;
125 ULONG NameLength;
126 NTSTATUS Status;
127 PNDISUIO_ADAPTER_CONTEXT AdapterContext;
128 PNDISUIO_OPEN_ENTRY OpenEntry;
129 KIRQL OldIrql;
130
131 NameLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
132 if (NameLength != 0)
133 {
134 DeviceName.MaximumLength = DeviceName.Length = NameLength;
135 DeviceName.Buffer = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
136
137 /* Check if this already has a context */
138 AdapterContext = FindAdapterContextByName(&DeviceName);
139 if (AdapterContext != NULL)
140 {
141 /* Reference the adapter context */
142 KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
143 ReferenceAdapterContext(AdapterContext);
144 Status = STATUS_SUCCESS;
145 }
146 else
147 {
148 /* Invalid device name */
149 Status = STATUS_INVALID_PARAMETER;
150 }
151
152 /* Check that the bind succeeded */
153 if (NT_SUCCESS(Status))
154 {
155 OpenEntry = ExAllocatePool(NonPagedPool, sizeof(*OpenEntry));
156 if (OpenEntry)
157 {
158 /* Set the file object pointer */
159 OpenEntry->FileObject = FileObject;
160
161 /* Associate this FO with the adapter */
162 FileObject->FsContext = AdapterContext;
163 FileObject->FsContext2 = OpenEntry;
164
165 /* Add it to the adapter's list */
166 InsertTailList(&AdapterContext->OpenEntryList,
167 &OpenEntry->ListEntry);
168
169 /* Success */
170 KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
171 Status = STATUS_SUCCESS;
172 }
173 else
174 {
175 /* Remove the reference we added */
176 KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
177 DereferenceAdapterContext(AdapterContext, NULL);
178 Status = STATUS_NO_MEMORY;
179 }
180 }
181 }
182 else
183 {
184 /* Invalid device name */
185 Status = STATUS_INVALID_PARAMETER;
186 }
187
188 Irp->IoStatus.Status = Status;
189 Irp->IoStatus.Information = 0;
190
191 IoCompleteRequest(Irp, IO_NO_INCREMENT);
192
193 return Status;
194 }
195
196 NTSTATUS
197 OpenDeviceWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp)
198 {
199 /* FIXME: Handle this correctly */
200 return OpenDeviceReadWrite(Irp, IrpSp);
201 }
202
203 NTSTATUS
204 NTAPI
205 NduDispatchDeviceControl(PDEVICE_OBJECT DeviceObject,
206 PIRP Irp)
207 {
208 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
209
210 ASSERT(DeviceObject == GlobalDeviceObject);
211
212 /* Handle open IOCTLs first */
213 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
214 {
215 case IOCTL_NDISUIO_OPEN_DEVICE:
216 return OpenDeviceReadWrite(Irp, IrpSp);
217
218 case IOCTL_NDISUIO_OPEN_WRITE_DEVICE:
219 return OpenDeviceWrite(Irp, IrpSp);
220
221 default:
222 /* Fail if this file object has no adapter associated */
223 if (IrpSp->FileObject->FsContext == NULL)
224 {
225 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
226 Irp->IoStatus.Information = 0;
227 IoCompleteRequest(Irp, IO_NO_INCREMENT);
228
229 return STATUS_INVALID_PARAMETER;
230 }
231
232 /* Now handle other IOCTLs */
233 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
234 {
235 case IOCTL_NDISUIO_QUERY_OID_VALUE:
236 return QueryAdapterOid(Irp, IrpSp);
237
238 case IOCTL_NDISUIO_SET_OID_VALUE:
239 return SetAdapterOid(Irp, IrpSp);
240
241 default:
242 DPRINT1("Unimplemented\n");
243 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
244 Irp->IoStatus.Information = 0;
245 IoCompleteRequest(Irp, IO_NO_INCREMENT);
246 break;
247 }
248 break;
249 }
250 }