1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/net/afd/afd/info.c
5 * PURPOSE: Ancillary functions driver
6 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
7 * UPDATE HISTORY:
8 * 20040708 Created
9 */
10
11 #include "afd.h"
12
13 NTSTATUS NTAPI
AfdGetInfo(PDEVICE_OBJECT DeviceObject,PIRP Irp,PIO_STACK_LOCATION IrpSp)14 AfdGetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp,
15 PIO_STACK_LOCATION IrpSp ) {
16 NTSTATUS Status = STATUS_SUCCESS;
17 PAFD_INFO InfoReq = LockRequest(Irp, IrpSp, TRUE, NULL);
18 PFILE_OBJECT FileObject = IrpSp->FileObject;
19 PAFD_FCB FCB = FileObject->FsContext;
20 PLIST_ENTRY CurrentEntry;
21
22 UNREFERENCED_PARAMETER(DeviceObject);
23
24 AFD_DbgPrint(MID_TRACE,("Called %p %x\n", InfoReq,
25 InfoReq ? InfoReq->InformationClass : 0));
26
27 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
28
29 if (!InfoReq)
30 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
31
32 _SEH2_TRY {
33 switch( InfoReq->InformationClass ) {
34 case AFD_INFO_RECEIVE_WINDOW_SIZE:
35 InfoReq->Information.Ulong = FCB->Recv.Size;
36 break;
37
38 case AFD_INFO_SEND_WINDOW_SIZE:
39 InfoReq->Information.Ulong = FCB->Send.Size;
40 AFD_DbgPrint(MID_TRACE,("Send window size %u\n", FCB->Send.Size));
41 break;
42
43 case AFD_INFO_GROUP_ID_TYPE:
44 InfoReq->Information.LargeInteger.u.HighPart = FCB->GroupType;
45 InfoReq->Information.LargeInteger.u.LowPart = FCB->GroupID;
46 AFD_DbgPrint(MID_TRACE, ("Group ID: %u Group Type: %u\n", FCB->GroupID, FCB->GroupType));
47 break;
48
49 case AFD_INFO_BLOCKING_MODE:
50 InfoReq->Information.Boolean = FCB->NonBlocking;
51 break;
52
53 case AFD_INFO_INLINING_MODE:
54 InfoReq->Information.Boolean = FCB->OobInline;
55 break;
56
57 case AFD_INFO_RECEIVE_CONTENT_SIZE:
58 InfoReq->Information.Ulong = FCB->Recv.Content - FCB->Recv.BytesUsed;
59 break;
60
61 case AFD_INFO_SENDS_IN_PROGRESS:
62 InfoReq->Information.Ulong = 0;
63
64 /* Count the queued sends */
65 CurrentEntry = FCB->PendingIrpList[FUNCTION_SEND].Flink;
66 while (CurrentEntry != &FCB->PendingIrpList[FUNCTION_SEND])
67 {
68 InfoReq->Information.Ulong++;
69 CurrentEntry = CurrentEntry->Flink;
70 }
71
72 /* This needs to count too because when this is dispatched
73 * the user-mode IRP has already been completed and therefore
74 * will NOT be in our pending IRP list. We count this as one send
75 * outstanding although it could be multiple since we batch sends
76 * when waiting for the in flight request to return, so this number
77 * may not be accurate but it really doesn't matter that much since
78 * it's more or less a zero/non-zero comparison to determine whether
79 * we can shutdown the socket
80 */
81 if (FCB->SendIrp.InFlightRequest)
82 InfoReq->Information.Ulong++;
83 break;
84
85 default:
86 AFD_DbgPrint(MIN_TRACE,("Unknown info id %x\n",
87 InfoReq->InformationClass));
88 Status = STATUS_INVALID_PARAMETER;
89 break;
90 }
91 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
92 AFD_DbgPrint(MIN_TRACE,("Exception executing GetInfo\n"));
93 Status = STATUS_INVALID_PARAMETER;
94 } _SEH2_END;
95
96 AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
97
98 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
99 }
100
101 NTSTATUS NTAPI
AfdSetInfo(PDEVICE_OBJECT DeviceObject,PIRP Irp,PIO_STACK_LOCATION IrpSp)102 AfdSetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp,
103 PIO_STACK_LOCATION IrpSp ) {
104 NTSTATUS Status = STATUS_SUCCESS;
105 PAFD_INFO InfoReq = LockRequest(Irp, IrpSp, FALSE, NULL);
106 PFILE_OBJECT FileObject = IrpSp->FileObject;
107 PAFD_FCB FCB = FileObject->FsContext;
108 PCHAR NewBuffer;
109
110 UNREFERENCED_PARAMETER(DeviceObject);
111
112 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
113
114 if (!InfoReq)
115 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
116
117 _SEH2_TRY {
118 switch (InfoReq->InformationClass) {
119 case AFD_INFO_BLOCKING_MODE:
120 AFD_DbgPrint(MID_TRACE,("Blocking mode set to %u\n", InfoReq->Information.Boolean));
121 FCB->NonBlocking = InfoReq->Information.Boolean;
122 break;
123 case AFD_INFO_INLINING_MODE:
124 FCB->OobInline = InfoReq->Information.Boolean;
125 break;
126 case AFD_INFO_RECEIVE_WINDOW_SIZE:
127 if (FCB->State == SOCKET_STATE_CONNECTED ||
128 FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)
129 {
130 /* FIXME: likely not right, check tcpip.sys for TDI_QUERY_MAX_DATAGRAM_INFO */
131 if (InfoReq->Information.Ulong > 0 && InfoReq->Information.Ulong < 0xFFFF &&
132 InfoReq->Information.Ulong != FCB->Recv.Size)
133 {
134 NewBuffer = ExAllocatePoolWithTag(PagedPool,
135 InfoReq->Information.Ulong,
136 TAG_AFD_DATA_BUFFER);
137
138 if (NewBuffer)
139 {
140 if (FCB->Recv.Content > InfoReq->Information.Ulong)
141 FCB->Recv.Content = InfoReq->Information.Ulong;
142
143 if (FCB->Recv.Window)
144 {
145 RtlCopyMemory(NewBuffer,
146 FCB->Recv.Window,
147 FCB->Recv.Content);
148
149 ExFreePoolWithTag(FCB->Recv.Window, TAG_AFD_DATA_BUFFER);
150 }
151
152 FCB->Recv.Size = InfoReq->Information.Ulong;
153 FCB->Recv.Window = NewBuffer;
154
155 Status = STATUS_SUCCESS;
156 }
157 else
158 {
159 Status = STATUS_NO_MEMORY;
160 }
161 }
162 else
163 {
164 Status = STATUS_SUCCESS;
165 }
166 }
167 else
168 {
169 Status = STATUS_INVALID_PARAMETER;
170 }
171 break;
172 case AFD_INFO_SEND_WINDOW_SIZE:
173 if (FCB->State == SOCKET_STATE_CONNECTED ||
174 FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)
175 {
176 if (InfoReq->Information.Ulong > 0 && InfoReq->Information.Ulong < 0xFFFF &&
177 InfoReq->Information.Ulong != FCB->Send.Size)
178 {
179 NewBuffer = ExAllocatePoolWithTag(PagedPool,
180 InfoReq->Information.Ulong,
181 TAG_AFD_DATA_BUFFER);
182
183 if (NewBuffer)
184 {
185 if (FCB->Send.BytesUsed > InfoReq->Information.Ulong)
186 FCB->Send.BytesUsed = InfoReq->Information.Ulong;
187
188 if (FCB->Send.Window)
189 {
190 RtlCopyMemory(NewBuffer,
191 FCB->Send.Window,
192 FCB->Send.BytesUsed);
193
194 ExFreePoolWithTag(FCB->Send.Window, TAG_AFD_DATA_BUFFER);
195 }
196
197 FCB->Send.Size = InfoReq->Information.Ulong;
198 FCB->Send.Window = NewBuffer;
199
200 Status = STATUS_SUCCESS;
201 }
202 else
203 {
204 Status = STATUS_NO_MEMORY;
205 }
206 }
207 else
208 {
209 Status = STATUS_SUCCESS;
210 }
211 }
212 else
213 {
214 Status = STATUS_INVALID_PARAMETER;
215 }
216 break;
217 default:
218 AFD_DbgPrint(MIN_TRACE,("Unknown request %u\n", InfoReq->InformationClass));
219 break;
220 }
221 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
222 AFD_DbgPrint(MIN_TRACE,("Exception executing SetInfo\n"));
223 Status = STATUS_INVALID_PARAMETER;
224 } _SEH2_END;
225
226 AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
227
228 return UnlockAndMaybeComplete(FCB, Status, Irp, 0);
229 }
230
231 NTSTATUS NTAPI
AfdGetSockName(PDEVICE_OBJECT DeviceObject,PIRP Irp,PIO_STACK_LOCATION IrpSp)232 AfdGetSockName( PDEVICE_OBJECT DeviceObject, PIRP Irp,
233 PIO_STACK_LOCATION IrpSp ) {
234 NTSTATUS Status = STATUS_SUCCESS;
235 PFILE_OBJECT FileObject = IrpSp->FileObject;
236 PAFD_FCB FCB = FileObject->FsContext;
237 PMDL Mdl = NULL;
238
239 UNREFERENCED_PARAMETER(DeviceObject);
240 ASSERT(Irp->MdlAddress == NULL);
241
242 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
243
244 if( FCB->AddressFile.Object == NULL && FCB->Connection.Object == NULL ) {
245 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 );
246 }
247
248 Mdl = IoAllocateMdl( Irp->UserBuffer,
249 IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
250 FALSE,
251 FALSE,
252 NULL );
253
254 if( Mdl != NULL ) {
255 _SEH2_TRY {
256 MmProbeAndLockPages( Mdl, Irp->RequestorMode, IoModifyAccess );
257 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
258 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
259 Status = _SEH2_GetExceptionCode();
260 } _SEH2_END;
261
262 if( NT_SUCCESS(Status) ) {
263 Status = TdiQueryInformation( FCB->Connection.Object
264 ? FCB->Connection.Object
265 : FCB->AddressFile.Object,
266 TDI_QUERY_ADDRESS_INFO,
267 Mdl );
268 }
269
270 /* Check if MmProbeAndLockPages or TdiQueryInformation failed and
271 * clean up Mdl */
272 if (!NT_SUCCESS(Status) && Irp->MdlAddress != Mdl)
273 IoFreeMdl(Mdl);
274 } else
275 Status = STATUS_INSUFFICIENT_RESOURCES;
276
277 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
278 }
279
280 NTSTATUS NTAPI
AfdGetPeerName(PDEVICE_OBJECT DeviceObject,PIRP Irp,PIO_STACK_LOCATION IrpSp)281 AfdGetPeerName( PDEVICE_OBJECT DeviceObject, PIRP Irp,
282 PIO_STACK_LOCATION IrpSp ) {
283 NTSTATUS Status;
284 PFILE_OBJECT FileObject = IrpSp->FileObject;
285 PAFD_FCB FCB = FileObject->FsContext;
286
287 UNREFERENCED_PARAMETER(DeviceObject);
288
289 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
290
291 if (FCB->RemoteAddress == NULL) {
292 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
293 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 );
294 }
295
296 if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= TaLengthOfTransportAddress(FCB->RemoteAddress))
297 {
298 RtlCopyMemory(Irp->UserBuffer, FCB->RemoteAddress, TaLengthOfTransportAddress(FCB->RemoteAddress));
299 Status = STATUS_SUCCESS;
300 }
301 else
302 {
303 AFD_DbgPrint(MIN_TRACE,("Buffer too small\n"));
304 Status = STATUS_BUFFER_TOO_SMALL;
305 }
306
307 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
308 }
309