d92a882f3127608075a9823904fb36052c62a4b8
[reactos.git] / reactos / lib / msafd / misc / sndrcv.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver DLL
4 * FILE: misc/sndrcv.c
5 * PURPOSE: Send/receive routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Alex Ionescu (alex@relsoft.net)
8 * REVISIONS:
9 * CSH 01/09-2000 Created
10 * Alex 16/07/2004 - Complete Rewrite
11 */
12 #include <string.h>
13 #include <msafd.h>
14
15 INT
16 WSPAPI
17 WSPAsyncSelect(
18 IN SOCKET s,
19 IN HWND hWnd,
20 IN UINT wMsg,
21 IN LONG lEvent,
22 OUT LPINT lpErrno)
23 {
24 UNIMPLEMENTED
25
26 return 0;
27 }
28
29
30 int
31 WSPAPI
32 WSPRecv(
33 SOCKET Handle,
34 LPWSABUF lpBuffers,
35 DWORD dwBufferCount,
36 LPDWORD lpNumberOfBytesRead,
37 LPDWORD ReceiveFlags,
38 LPWSAOVERLAPPED lpOverlapped,
39 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
40 LPWSATHREADID lpThreadId,
41 LPINT lpErrno)
42 {
43 PIO_STATUS_BLOCK IOSB;
44 IO_STATUS_BLOCK DummyIOSB;
45 AFD_RECV_INFO RecvInfo;
46 NTSTATUS Status;
47 PVOID APCContext;
48 PVOID APCFunction;
49 HANDLE Event;
50 HANDLE SockEvent;
51 PSOCKET_INFORMATION Socket;
52
53
54 /* Get the Socket Structure associate to this Socket*/
55 Socket = GetSocketStructure(Handle);
56
57 Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE,
58 NULL, 1, FALSE );
59
60 if( !NT_SUCCESS(Status) ) return -1;
61
62 /* Set up the Receive Structure */
63 RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
64 RecvInfo.BufferCount = dwBufferCount;
65 RecvInfo.TdiFlags = 0;
66 RecvInfo.AfdFlags = Socket->SharedData.NonBlocking ? AFD_IMMEDIATE : 0;
67
68 /* Set the TDI Flags */
69 if (*ReceiveFlags == 0) {
70 RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
71
72 } else {
73
74 if (*ReceiveFlags & MSG_OOB) {
75 RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED;
76 } else {
77 RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
78 }
79
80 if (*ReceiveFlags & MSG_PEEK) {
81 RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
82 }
83
84 if (*ReceiveFlags & MSG_PARTIAL) {
85 RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
86 }
87 }
88
89 /* Verifiy if we should use APC */
90
91 if (lpOverlapped == NULL) {
92
93 /* Not using Overlapped structure, so use normal blocking on event */
94 APCContext = NULL;
95 APCFunction = NULL;
96 Event = SockEvent;
97 IOSB = &DummyIOSB;
98
99 } else {
100
101 if (lpCompletionRoutine == NULL) {
102
103 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
104 APCContext = lpOverlapped;
105 APCFunction = NULL;
106 Event = lpOverlapped->hEvent;
107
108 } else {
109
110 /* Using Overlapped Structure and a Completition Routine, so use an APC */
111 APCFunction = NULL; // should be a private io completition function inside us
112 APCContext = lpCompletionRoutine;
113 RecvInfo.AfdFlags = AFD_SKIP_FIO;
114 }
115
116 IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
117 RecvInfo.AfdFlags |= AFD_OVERLAPPED;
118 }
119
120 IOSB->Status = STATUS_PENDING;
121
122 /* Send IOCTL */
123 Status = NtDeviceIoControlFile((HANDLE)Handle,
124 SockEvent,
125 APCFunction,
126 APCContext,
127 IOSB,
128 IOCTL_AFD_RECV,
129 &RecvInfo,
130 sizeof(RecvInfo),
131 NULL,
132 0);
133
134 /* Wait for completition of not overlapped */
135 if (Status == STATUS_PENDING && lpOverlapped == NULL) {
136 WaitForSingleObject(SockEvent, 0); // BUGBUG, shouldn wait infintely for receive...
137 Status = IOSB->Status;
138 }
139
140 NtClose( SockEvent );
141
142 /* Return the Flags */
143 *ReceiveFlags = 0;
144 switch (Status) {
145 case STATUS_CANT_WAIT:
146 return WSAEWOULDBLOCK;
147
148 case STATUS_SUCCESS:
149 break;
150
151 case STATUS_PENDING :
152 return WSA_IO_PENDING;
153
154 case STATUS_BUFFER_OVERFLOW:
155 return WSAEMSGSIZE;
156
157 case STATUS_RECEIVE_EXPEDITED:
158 *ReceiveFlags = MSG_OOB;
159 break;
160
161 case STATUS_RECEIVE_PARTIAL_EXPEDITED :
162 *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
163 break;
164
165 case STATUS_RECEIVE_PARTIAL :
166 *ReceiveFlags = MSG_PARTIAL;
167 break;
168 }
169
170 /* Return Number of bytes Read */
171 *lpNumberOfBytesRead = (DWORD)IOSB->Information;
172
173 /* Success */
174 return STATUS_SUCCESS;
175 }
176
177 int
178 WSPAPI
179 WSPRecvFrom(
180 SOCKET Handle,
181 LPWSABUF lpBuffers,
182 DWORD dwBufferCount,
183 LPDWORD lpNumberOfBytesRead,
184 LPDWORD ReceiveFlags,
185 struct sockaddr *SocketAddress,
186 int *SocketAddressLength,
187 LPWSAOVERLAPPED lpOverlapped,
188 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
189 LPWSATHREADID lpThreadId,
190 LPINT lpErrno)
191 {
192 PIO_STATUS_BLOCK IOSB;
193 IO_STATUS_BLOCK DummyIOSB;
194 AFD_RECV_INFO_UDP RecvInfo;
195 NTSTATUS Status;
196 PVOID APCContext;
197 PVOID APCFunction;
198 HANDLE Event;
199 HANDLE SockEvent;
200 PSOCKET_INFORMATION Socket;
201
202 /* Get the Socket Structure associate to this Socket*/
203 Socket = GetSocketStructure(Handle);
204
205 Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE,
206 NULL, 1, FALSE );
207
208 if( !NT_SUCCESS(Status) ) return -1;
209
210 /* Set up the Receive Structure */
211 RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
212 RecvInfo.BufferCount = dwBufferCount;
213 RecvInfo.TdiFlags = 0;
214 RecvInfo.AfdFlags = Socket->SharedData.NonBlocking ? AFD_IMMEDIATE : 0;
215 RecvInfo.AddressLength = SocketAddressLength;
216 RecvInfo.Address = SocketAddress;
217
218 /* Set the TDI Flags */
219 if (*ReceiveFlags == 0) {
220 RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
221
222 } else {
223
224 if (*ReceiveFlags & MSG_OOB) {
225 RecvInfo.TdiFlags |= TDI_RECEIVE_EXPEDITED;
226 } else {
227 RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
228 }
229
230 if (*ReceiveFlags & MSG_PEEK) {
231 RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
232 }
233
234 if (*ReceiveFlags & MSG_PARTIAL) {
235 RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
236 }
237 }
238
239 /* Verifiy if we should use APC */
240
241 if (lpOverlapped == NULL) {
242
243 /* Not using Overlapped structure, so use normal blocking on event */
244 APCContext = NULL;
245 APCFunction = NULL;
246 Event = SockEvent;
247 IOSB = &DummyIOSB;
248
249 } else {
250
251 if (lpCompletionRoutine == NULL) {
252
253 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
254 APCContext = lpOverlapped;
255 APCFunction = NULL;
256 Event = lpOverlapped->hEvent;
257
258 } else {
259
260 /* Using Overlapped Structure and a Completition Routine, so use an APC */
261 APCFunction = NULL; // should be a private io completition function inside us
262 APCContext = lpCompletionRoutine;
263 RecvInfo.AfdFlags = AFD_SKIP_FIO;
264 }
265
266 IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
267 RecvInfo.AfdFlags |= AFD_OVERLAPPED;
268 }
269
270 IOSB->Status = STATUS_PENDING;
271
272 /* Send IOCTL */
273 Status = NtDeviceIoControlFile((HANDLE)Handle,
274 SockEvent,
275 APCFunction,
276 APCContext,
277 IOSB,
278 IOCTL_AFD_RECV_DATAGRAM,
279 &RecvInfo,
280 sizeof(RecvInfo),
281 NULL,
282 0);
283
284 /* Wait for completition of not overlapped */
285 if (Status == STATUS_PENDING && lpOverlapped == NULL) {
286 WaitForSingleObject(SockEvent, 0); // BUGBUG, shouldn wait infintely for receive...
287 Status = IOSB->Status;
288 }
289
290 NtClose( SockEvent );
291
292 /* Return the Flags */
293 *ReceiveFlags = 0;
294 switch (Status) {
295 case STATUS_CANT_WAIT:
296 return WSAEWOULDBLOCK;
297
298 case STATUS_SUCCESS:
299 break;
300
301 case STATUS_PENDING :
302 return WSA_IO_PENDING;
303
304 case STATUS_BUFFER_OVERFLOW:
305 return WSAEMSGSIZE;
306
307 case STATUS_RECEIVE_EXPEDITED:
308 *ReceiveFlags = MSG_OOB;
309 break;
310
311 case STATUS_RECEIVE_PARTIAL_EXPEDITED :
312 *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
313 break;
314
315 case STATUS_RECEIVE_PARTIAL :
316 *ReceiveFlags = MSG_PARTIAL;
317 break;
318 }
319
320 /* Return Number of bytes Read */
321 *lpNumberOfBytesRead = (DWORD)IOSB->Information;
322
323 /* Success */
324 return STATUS_SUCCESS;
325 }
326
327
328 int
329 WSPAPI
330 WSPSend(
331 SOCKET Handle,
332 LPWSABUF lpBuffers,
333 DWORD dwBufferCount,
334 LPDWORD lpNumberOfBytesSent,
335 DWORD iFlags,
336 LPWSAOVERLAPPED lpOverlapped,
337 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
338 LPWSATHREADID lpThreadId,
339 LPINT lpErrno)
340 {
341 PIO_STATUS_BLOCK IOSB;
342 IO_STATUS_BLOCK DummyIOSB;
343 AFD_SEND_INFO SendInfo;
344 NTSTATUS Status;
345 PVOID APCContext;
346 PVOID APCFunction;
347 HANDLE Event;
348 HANDLE SockEvent;
349 PSOCKET_INFORMATION Socket;
350
351 /* Get the Socket Structure associate to this Socket*/
352 Socket = GetSocketStructure(Handle);
353
354 Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE,
355 NULL, 1, FALSE );
356
357 if( !NT_SUCCESS(Status) ) return -1;
358
359 AFD_DbgPrint(MID_TRACE,("Called\n"));
360
361 /* Set up the Send Structure */
362 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
363 SendInfo.BufferCount = dwBufferCount;
364 SendInfo.TdiFlags = 0;
365 SendInfo.AfdFlags = Socket->SharedData.NonBlocking ? AFD_IMMEDIATE : 0;
366
367 /* Set the TDI Flags */
368 if (iFlags) {
369 if (iFlags & MSG_OOB) {
370 SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
371 }
372 if (iFlags & MSG_PARTIAL) {
373 SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
374 }
375 }
376
377 /* Verifiy if we should use APC */
378 if (lpOverlapped == NULL) {
379
380 /* Not using Overlapped structure, so use normal blocking on event */
381 APCContext = NULL;
382 APCFunction = NULL;
383 Event = SockEvent;
384 IOSB = &DummyIOSB;
385
386 } else {
387
388 if (lpCompletionRoutine == NULL) {
389
390 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
391 APCContext = lpOverlapped;
392 APCFunction = NULL;
393 Event = lpOverlapped->hEvent;
394
395 } else {
396
397 /* Using Overlapped Structure and a Completition Routine, so use an APC */
398 APCFunction = NULL; // should be a private io completition function inside us
399 APCContext = lpCompletionRoutine;
400 SendInfo.AfdFlags = AFD_SKIP_FIO;
401 }
402
403 IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
404 SendInfo.AfdFlags |= AFD_OVERLAPPED;
405 }
406
407 IOSB->Status = STATUS_PENDING;
408
409 /* Send IOCTL */
410 Status = NtDeviceIoControlFile((HANDLE)Handle,
411 SockEvent,
412 APCFunction,
413 APCContext,
414 IOSB,
415 IOCTL_AFD_SEND,
416 &SendInfo,
417 sizeof(SendInfo),
418 NULL,
419 0);
420
421 /* Wait for completition of not overlapped */
422 if (Status == STATUS_PENDING && lpOverlapped == NULL) {
423 WaitForSingleObject(SockEvent, 0); // BUGBUG, shouldn wait infintely for send...
424 Status = IOSB->Status;
425 }
426
427 NtClose( SockEvent );
428
429 if (Status == STATUS_PENDING) {
430 AFD_DbgPrint(MID_TRACE,("Leaving (Pending)\n"));
431 return WSA_IO_PENDING;
432 }
433
434 /* Return Number of bytes Sent */
435 *lpNumberOfBytesSent = (DWORD)IOSB->Information;
436
437 AFD_DbgPrint(MID_TRACE,("Leaving (Success, %d)\n", IOSB->Information));
438
439 /* Success */
440 return STATUS_SUCCESS;
441 }
442
443 int
444 WSPAPI
445 WSPSendTo(
446 SOCKET Handle,
447 LPWSABUF lpBuffers,
448 DWORD dwBufferCount,
449 LPDWORD lpNumberOfBytesSent,
450 DWORD iFlags,
451 struct sockaddr *SocketAddress,
452 int SocketAddressLength,
453 LPWSAOVERLAPPED lpOverlapped,
454 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
455 LPWSATHREADID lpThreadId,
456 LPINT lpErrno)
457 {
458 PIO_STATUS_BLOCK IOSB;
459 IO_STATUS_BLOCK DummyIOSB;
460 AFD_SEND_INFO_UDP SendInfo;
461 NTSTATUS Status;
462 PVOID APCContext;
463 PVOID APCFunction;
464 HANDLE Event;
465 PTRANSPORT_ADDRESS RemoteAddress;
466 UCHAR TdiBuffer[0x16];
467 PSOCKADDR BindAddress;
468 INT BindAddressLength;
469 HANDLE SockEvent;
470 PSOCKET_INFORMATION Socket;
471
472
473 /* Get the Socket Structure associate to this Socket*/
474 Socket = GetSocketStructure(Handle);
475
476 Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE,
477 NULL, 1, FALSE );
478
479 if( !NT_SUCCESS(Status) ) return -1;
480
481 /* Bind us First */
482 if (Socket->SharedData.State == SocketOpen) {
483
484 /* Get the Wildcard Address */
485 BindAddressLength = Socket->HelperData->MaxWSAddressLength;
486 BindAddress = HeapAlloc(GlobalHeap, 0, BindAddressLength);
487 Socket->HelperData->WSHGetWildcardSockaddr (Socket->HelperContext,
488 BindAddress,
489 &BindAddressLength);
490
491 /* Bind it */
492 WSPBind(Handle, BindAddress, BindAddressLength, NULL);
493 }
494
495 /* Set up Address in TDI Format */
496 RemoteAddress = (PTRANSPORT_ADDRESS)TdiBuffer;
497 RemoteAddress->TAAddressCount = 1;
498 RemoteAddress->Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
499 RtlCopyMemory(&RemoteAddress->Address[0].AddressType, SocketAddress, SocketAddressLength);
500
501 /* Set up Structure */
502 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
503 SendInfo.AfdFlags = Socket->SharedData.NonBlocking ? AFD_IMMEDIATE : 0;
504 SendInfo.BufferCount = dwBufferCount;
505 SendInfo.RemoteAddress = RemoteAddress;
506 SendInfo.SizeOfRemoteAddress = Socket->HelperData->MaxTDIAddressLength;
507
508 /* Verifiy if we should use APC */
509 if (lpOverlapped == NULL) {
510
511 /* Not using Overlapped structure, so use normal blocking on event */
512 APCContext = NULL;
513 APCFunction = NULL;
514 Event = SockEvent;
515 IOSB = &DummyIOSB;
516
517 } else {
518
519 if (lpCompletionRoutine == NULL) {
520
521 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
522 APCContext = lpOverlapped;
523 APCFunction = NULL;
524 Event = lpOverlapped->hEvent;
525
526 } else {
527
528 /* Using Overlapped Structure and a Completition Routine, so use an APC */
529 APCFunction = NULL; // should be a private io completition function inside us
530 APCContext = lpCompletionRoutine;
531 SendInfo.AfdFlags = AFD_SKIP_FIO;
532 }
533
534 IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
535 SendInfo.AfdFlags |= AFD_OVERLAPPED;
536 }
537
538 /* Send IOCTL */
539 Status = NtDeviceIoControlFile((HANDLE)Handle,
540 SockEvent,
541 APCFunction,
542 APCContext,
543 IOSB,
544 IOCTL_AFD_SEND_DATAGRAM,
545 &SendInfo,
546 sizeof(SendInfo),
547 NULL,
548 0);
549
550 /* Wait for completition of not overlapped */
551 if (Status == STATUS_PENDING && lpOverlapped == NULL) {
552 WaitForSingleObject(SockEvent, 0); // BUGBUG, shouldn wait infintely for send...
553 Status = IOSB->Status;
554 }
555
556 NtClose( SockEvent );
557
558 if (Status == STATUS_PENDING) {
559 return WSA_IO_PENDING;
560 }
561
562 /* Return Number of bytes Sent */
563 *lpNumberOfBytesSent = (DWORD)IOSB->Information;
564
565 /* Success */
566 return STATUS_SUCCESS;
567 }
568 INT
569 WSPAPI
570 WSPRecvDisconnect(
571 IN SOCKET s,
572 OUT LPWSABUF lpInboundDisconnectData,
573 OUT LPINT lpErrno)
574 {
575 UNIMPLEMENTED
576
577 return 0;
578 }
579
580
581
582 INT
583 WSPAPI
584 WSPSendDisconnect(
585 IN SOCKET s,
586 IN LPWSABUF lpOutboundDisconnectData,
587 OUT LPINT lpErrno)
588 {
589 UNIMPLEMENTED
590
591 return 0;
592 }
593
594 /* EOF */