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