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