Sync up with trunk r61578.
[reactos.git] / drivers / network / afd / afd / event.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver
4 * FILE: afd/event.c
5 * PURPOSE: TDI event handlers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/09-2000 Created
9 */
10 #include <afd.h>
11
12 NTSTATUS AfdEventError(
13 IN PVOID TdiEventContext,
14 IN NTSTATUS Status)
15 {
16 AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
17
18 return STATUS_SUCCESS;
19 }
20
21
22 NTSTATUS AfdEventDisconnect(
23 IN PVOID TdiEventContext,
24 IN CONNECTION_CONTEXT ConnectionContext,
25 IN LONG DisconnectDataLength,
26 IN PVOID DisconnectData,
27 IN LONG DisconnectInformationLength,
28 IN PVOID DisconnectInformation,
29 IN ULONG DisconnectFlags)
30 {
31 AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
32
33 return STATUS_SUCCESS;
34 }
35
36
37 NTSTATUS AfdEventReceive(
38 IN PVOID TdiEventContext,
39 IN CONNECTION_CONTEXT ConnectionContext,
40 IN ULONG ReceiveFlags,
41 IN ULONG BytesIndicated,
42 IN ULONG BytesAvailable,
43 OUT ULONG *BytesTaken,
44 IN PVOID Tsdu,
45 OUT PIRP *IoRequestPacket)
46 {
47 PAFDFCB FCB = (PAFDFCB)TdiEventContext;
48 PVOID ReceiveBuffer;
49 PAFD_BUFFER Buffer;
50 KIRQL OldIrql;
51
52 AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
53
54 AFD_DbgPrint(MID_TRACE, ("Receiving (%d) bytes on socket\n",
55 BytesAvailable));
56
57 ReceiveBuffer = ExAllocatePool(NonPagedPool, BytesAvailable);
58 if (!ReceiveBuffer)
59 return STATUS_INSUFFICIENT_RESOURCES;
60
61 /*Buffer = (PAFD_BUFFER)ExAllocateFromNPagedLookasideList(
62 &BufferLookasideList);*/
63 Buffer = (PAFD_BUFFER)ExAllocatePool(NonPagedPool, sizeof(AFD_BUFFER));
64 if (!Buffer) {
65 ExFreePool(ReceiveBuffer);
66 return STATUS_INSUFFICIENT_RESOURCES;
67 }
68
69 /* Copy the data to a local buffer */
70 RtlCopyMemory(ReceiveBuffer, Tsdu, BytesAvailable);
71
72 Buffer->Buffer.len = BytesAvailable;
73 Buffer->Buffer.buf = ReceiveBuffer;
74 Buffer->Offset = 0;
75
76 KeAcquireSpinLock(&FCB->ReceiveQueueLock, &OldIrql);
77
78 InsertTailList( &FCB->ReceiveQueue, &Buffer->ListEntry );
79
80 TryToSatisfyRecvRequest( FCB, TRUE );
81
82 KeReleaseSpinLock(&FCB->ReceiveQueueLock, OldIrql);
83
84 *BytesTaken = BytesAvailable;
85
86 AFD_DbgPrint(MAX_TRACE, ("Leaving.\n"));
87
88 return STATUS_SUCCESS;
89 }
90
91
92 TDI_STATUS ClientEventReceiveExpedited(
93 IN PVOID TdiEventContext,
94 IN CONNECTION_CONTEXT ConnectionContext,
95 IN ULONG ReceiveFlags,
96 IN ULONG BytesIndicated,
97 IN ULONG BytesAvailable,
98 OUT ULONG *BytesTaken,
99 IN PVOID Tsdu,
100 OUT PIRP *IoRequestPacket)
101 {
102 AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
103
104 return STATUS_SUCCESS;
105 }
106
107
108 NTSTATUS ClientEventChainedReceive(
109 IN PVOID TdiEventContext,
110 IN CONNECTION_CONTEXT ConnectionContext,
111 IN ULONG ReceiveFlags,
112 IN ULONG ReceiveLength,
113 IN ULONG StartingOffset,
114 IN PMDL Tsdu,
115 IN PVOID TsduDescriptor)
116 {
117 AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
118
119 return STATUS_SUCCESS;
120 }
121
122
123 NTSTATUS AfdEventReceiveDatagramHandler(
124 IN PVOID TdiEventContext,
125 IN LONG SourceAddressLength,
126 IN PVOID SourceAddress,
127 IN LONG OptionsLength,
128 IN PVOID Options,
129 IN ULONG ReceiveDatagramFlags,
130 IN ULONG BytesIndicated,
131 IN ULONG BytesAvailable,
132 OUT ULONG *BytesTaken,
133 IN PVOID Tsdu,
134 OUT PIRP *IoRequestPacket)
135 {
136 PAFDFCB FCB = (PAFDFCB)TdiEventContext;
137 PAFD_READ_REQUEST ReadRequest;
138 PVOID ReceiveBuffer;
139 PAFD_BUFFER Buffer;
140 PLIST_ENTRY Entry;
141 NTSTATUS Status;
142 KIRQL OldIrql;
143 ULONG Count;
144 BOOLEAN CompleteIrp;
145
146 AFD_DbgPrint(MAX_TRACE, ("Called.\n"));
147
148 AFD_DbgPrint(MID_TRACE, ("Receiving (%d) bytes from (0x%X).\n",
149 BytesAvailable, *(PULONG)SourceAddress));
150
151 ReceiveBuffer = ExAllocatePool(NonPagedPool, BytesAvailable);
152 if (!ReceiveBuffer)
153 return STATUS_INSUFFICIENT_RESOURCES;
154
155 /*Buffer = (PAFD_BUFFER)ExAllocateFromNPagedLookasideList(
156 &BufferLookasideList);*/
157 Buffer = (PAFD_BUFFER)ExAllocatePool(NonPagedPool, sizeof(AFD_BUFFER));
158 if (!Buffer) {
159 ExFreePool(ReceiveBuffer);
160 return STATUS_INSUFFICIENT_RESOURCES;
161 }
162
163 /* Copy the data to a local buffer */
164 RtlCopyMemory(ReceiveBuffer, Tsdu, BytesAvailable);
165
166 Buffer->Buffer.len = BytesAvailable;
167 Buffer->Buffer.buf = ReceiveBuffer;
168 Buffer->Offset = 0;
169
170 ExInterlockedInsertTailList(&FCB->ReceiveQueue,
171 &Buffer->ListEntry,
172 &FCB->ReceiveQueueLock);
173
174 KeAcquireSpinLock(&FCB->ReceiveQueueLock, &OldIrql);
175
176 if (CompleteIrp = !IsListEmpty(&FCB->ReadRequestQueue)) {
177 AFD_DbgPrint(MAX_TRACE, ("Satisfying read request.\n"));
178
179 Entry = RemoveHeadList(&FCB->ReceiveQueue);
180 ReadRequest = CONTAINING_RECORD(Entry, AFD_READ_REQUEST, ListEntry);
181
182 Status = FillWSABuffers(FCB,
183 ReadRequest->RecvFromRequest->Buffers,
184 ReadRequest->RecvFromRequest->BufferCount,
185 &Count,
186 FALSE); /* Packet oriented */
187 ReadRequest->RecvFromReply->NumberOfBytesRecvd = Count;
188 ReadRequest->RecvFromReply->Status = NO_ERROR;
189
190 ReadRequest->Irp->IoStatus.Information = 0;
191 ReadRequest->Irp->IoStatus.Status = Status;
192 }
193
194 KeReleaseSpinLock(&FCB->ReceiveQueueLock, OldIrql);
195
196 if (CompleteIrp) {
197 AFD_DbgPrint(MAX_TRACE, ("Completing IRP at (0x%X).\n", ReadRequest->Irp));
198 IoCompleteRequest(ReadRequest->Irp, IO_NETWORK_INCREMENT);
199 *BytesTaken = BytesAvailable;
200 }
201
202 AFD_DbgPrint(MAX_TRACE, ("Leaving.\n"));
203
204 return STATUS_SUCCESS;
205 }
206
207
208 NTSTATUS AfdRegisterEventHandlers(
209 PAFDFCB FCB)
210 {
211 NTSTATUS Status;
212
213 assert(FCB->TdiAddressObject);
214
215 /* Report errors for all types of sockets */
216 Status = TdiSetEventHandler(FCB->TdiAddressObject,
217 TDI_EVENT_ERROR,
218 (PVOID)AfdEventError,
219 (PVOID)FCB);
220 if (!NT_SUCCESS(Status)) { return Status; }
221
222 switch (FCB->SocketType) {
223 case SOCK_STREAM:
224 Status = TdiSetEventHandler(FCB->TdiAddressObject,
225 TDI_EVENT_DISCONNECT,
226 (PVOID)AfdEventDisconnect,
227 (PVOID)FCB);
228 if (!NT_SUCCESS(Status)) { return Status; }
229
230 Status = TdiSetEventHandler(FCB->TdiAddressObject,
231 TDI_EVENT_RECEIVE,
232 (PVOID)AfdEventReceive,
233 (PVOID)FCB);
234 if (!NT_SUCCESS(Status)) { return Status; }
235
236 Status = TdiSetEventHandler(FCB->TdiAddressObject,
237 TDI_EVENT_RECEIVE_EXPEDITED,
238 (PVOID)ClientEventReceiveExpedited,
239 (PVOID)FCB);
240 if (!NT_SUCCESS(Status)) { return Status; }
241
242 Status = TdiSetEventHandler(FCB->TdiAddressObject,
243 TDI_EVENT_CHAINED_RECEIVE,
244 (PVOID)ClientEventChainedReceive,
245 (PVOID)FCB);
246 if (!NT_SUCCESS(Status)) { return Status; }
247 break;
248
249 case SOCK_DGRAM:
250 case SOCK_RAW:
251 Status = TdiSetEventHandler(FCB->TdiAddressObject,
252 TDI_EVENT_RECEIVE_DATAGRAM,
253 (PVOID)AfdEventReceiveDatagramHandler,
254 (PVOID)FCB);
255 if (!NT_SUCCESS(Status)) { return Status; }
256 }
257 return STATUS_SUCCESS;
258 }
259
260
261 NTSTATUS AfdDeregisterEventHandlers(
262 PAFDFCB FCB)
263 {
264 NTSTATUS Status;
265
266 Status = TdiSetEventHandler(FCB->TdiAddressObject,
267 TDI_EVENT_ERROR,
268 NULL,
269 NULL);
270 if (!NT_SUCCESS(Status)) { return Status; }
271
272 switch (FCB->SocketType) {
273 case SOCK_STREAM:
274 Status = TdiSetEventHandler(FCB->TdiAddressObject,
275 TDI_EVENT_DISCONNECT,
276 NULL,
277 NULL);
278 if (!NT_SUCCESS(Status)) { return Status; }
279
280 Status = TdiSetEventHandler(FCB->TdiAddressObject,
281 TDI_EVENT_RECEIVE,
282 NULL,
283 NULL);
284 if (!NT_SUCCESS(Status)) { return Status; }
285
286 Status = TdiSetEventHandler(FCB->TdiAddressObject,
287 TDI_EVENT_RECEIVE_EXPEDITED,
288 NULL,
289 NULL);
290 if (!NT_SUCCESS(Status)) { return Status; }
291
292 Status = TdiSetEventHandler(FCB->TdiAddressObject,
293 TDI_EVENT_CHAINED_RECEIVE,
294 NULL,
295 NULL);
296 if (!NT_SUCCESS(Status)) { return Status; }
297 break;
298
299 case SOCK_DGRAM:
300 case SOCK_RAW:
301 Status = TdiSetEventHandler(FCB->TdiAddressObject,
302 TDI_EVENT_RECEIVE_DATAGRAM,
303 NULL,
304 NULL);
305 if (!NT_SUCCESS(Status)) { return Status; }
306 }
307 return STATUS_SUCCESS;
308 }
309
310
311 /* EOF */