xref: /reactos/drivers/network/afd/afd/info.c (revision 4e07b3b9)
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