ReactOS 0.4.15-dev-7693-gd0e2924
sndrcv.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver DLL
4 * FILE: dll/win32/msafd/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
13#include <msafd.h>
14
15INT
18 IN HWND hWnd,
19 IN UINT wMsg,
21 OUT LPINT lpErrno)
22{
24 PASYNC_DATA AsyncData;
25 BOOLEAN BlockMode;
26
27 /* Get the Socket Structure associated to this Socket */
28 Socket = GetSocketStructure(Handle);
29 if (!Socket)
30 {
31 *lpErrno = WSAENOTSOCK;
32 return SOCKET_ERROR;
33 }
34
35 /* Allocate the Async Data Structure to pass on to the Thread later */
36 AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(*AsyncData));
37 if (!AsyncData)
38 {
40 return INVALID_SOCKET;
41 }
42
43 /* Change the Socket to Non Blocking */
44 BlockMode = TRUE;
46 Socket->SharedData->NonBlocking = TRUE;
47
48 /* Deactivate WSPEventSelect */
49 if (Socket->SharedData->AsyncEvents)
50 {
51 if (WSPEventSelect(Handle, NULL, 0, lpErrno) == SOCKET_ERROR)
52 {
53 HeapFree(GetProcessHeap(), 0, AsyncData);
54 return SOCKET_ERROR;
55 }
56 }
57
58 /* Create the Asynch Thread if Needed */
60
61 /* Open a Handle to AFD's Async Helper */
63
64 /* Store Socket Data */
65 Socket->SharedData->hWnd = hWnd;
66 Socket->SharedData->wMsg = wMsg;
67 Socket->SharedData->AsyncEvents = lEvent;
69 Socket->SharedData->SequenceNumber++;
70
71 /* Return if there are no more Events */
72 if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) == 0)
73 {
74 HeapFree(GetProcessHeap(), 0, AsyncData);
75 return 0;
76 }
77
78 /* Set up the Async Data */
79 AsyncData->ParentSocket = Socket;
80 AsyncData->SequenceNumber = Socket->SharedData->SequenceNumber;
81
82 /* Begin Async Select by using I/O Completion */
85 AsyncData,
86 0,
87 0);
88
89 /* Return */
90 return ERROR_SUCCESS;
91}
92
93
94BOOL
99 OUT LPDWORD lpdwBytes,
100 IN BOOL fWait,
101 OUT LPDWORD lpdwFlags,
102 OUT LPINT lpErrno)
103{
104 PSOCKET_INFORMATION Socket;
105 BOOL Ret;
106
107 TRACE("Called (%x)\n", Handle);
108
109 /* Get the Socket Structure associate to this Socket*/
110 Socket = GetSocketStructure(Handle);
111 if (!Socket)
112 {
113 if(lpErrno)
114 *lpErrno = WSAENOTSOCK;
115 return FALSE;
116 }
117 if (!lpOverlapped || !lpdwBytes || !lpdwFlags)
118 {
119 if (lpErrno)
120 *lpErrno = WSAEFAULT;
121 return FALSE;
122 }
123 Ret = GetOverlappedResult((HANDLE)Handle, lpOverlapped, lpdwBytes, fWait);
124
125 if (Ret)
126 {
127 *lpdwFlags = 0;
128
129 /* Re-enable Async Event */
133 }
134
135 return Ret;
136}
137
138VOID
139NTAPI
143{
145
146 /* Re-enable Async Event */
150
151 Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0);
153}
154
155int
156WSPAPI
158 LPWSABUF lpBuffers,
159 DWORD dwBufferCount,
160 LPDWORD lpNumberOfBytesRead,
161 LPDWORD ReceiveFlags,
163 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
164 LPWSATHREADID lpThreadId,
165 LPINT lpErrno)
166{
167 PIO_STATUS_BLOCK IOSB;
168 IO_STATUS_BLOCK DummyIOSB;
169 AFD_RECV_INFO RecvInfo;
171 PVOID APCContext;
172 PIO_APC_ROUTINE APCFunction;
173 HANDLE Event = NULL;
175 PSOCKET_INFORMATION Socket;
176
177 TRACE("Called (%x)\n", Handle);
178
179 /* Get the Socket Structure associate to this Socket*/
180 Socket = GetSocketStructure(Handle);
181 if (!Socket)
182 {
183 if (lpErrno)
184 *lpErrno = WSAENOTSOCK;
185 return SOCKET_ERROR;
186 }
187 if (!lpNumberOfBytesRead && !lpOverlapped)
188 {
189 if (lpErrno)
190 *lpErrno = WSAEFAULT;
191 return SOCKET_ERROR;
192 }
193 if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0)
194 {
195 if (lpErrno)
196 *lpErrno = WSAEINVAL;
197 return SOCKET_ERROR;
198 }
199
202
203 if( !NT_SUCCESS(Status) )
204 return -1;
205
206 /* Set up the Receive Structure */
207 RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
208 RecvInfo.BufferCount = dwBufferCount;
209 RecvInfo.TdiFlags = 0;
210 RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
211
212 /* Set the TDI Flags */
213 if (*ReceiveFlags == 0)
214 {
215 RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
216 }
217 else
218 {
219 if (*ReceiveFlags & MSG_OOB)
220 {
222 }
223
224 if (*ReceiveFlags & MSG_PEEK)
225 {
226 RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
227 }
228
229 if (*ReceiveFlags & MSG_PARTIAL)
230 {
231 RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL;
232 }
233 }
234
235 /* Verify if we should use APC */
236
237 if (lpOverlapped == NULL)
238 {
239 /* Not using Overlapped structure, so use normal blocking on event */
240 APCContext = NULL;
241 APCFunction = NULL;
243 IOSB = &DummyIOSB;
244 }
245 else
246 {
247 /* Overlapped request for non overlapped opened socket */
248 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
249 {
250 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
251 return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead);
252 }
253 if (lpCompletionRoutine == NULL)
254 {
255 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
256 APCContext = lpOverlapped;
257 APCFunction = NULL;
258 Event = lpOverlapped->hEvent;
259 }
260 else
261 {
262 /* Using Overlapped Structure and a Completion Routine, so use an APC */
263 APCFunction = &AfdAPC; // should be a private io completion function inside us
264 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
265 if (!APCContext)
266 {
267 ERR("Not enough memory for APC Context\n");
268 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead);
269 }
270 ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
271 ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
272 ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
273 RecvInfo.AfdFlags |= AFD_SKIP_FIO;
274 }
275
276 IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
277 RecvInfo.AfdFlags |= AFD_OVERLAPPED;
278 }
279
280 IOSB->Status = STATUS_PENDING;
281
282 /* Send IOCTL */
284 Event,
285 APCFunction,
286 APCContext,
287 IOSB,
289 &RecvInfo,
290 sizeof(RecvInfo),
291 NULL,
292 0);
293
294 /* Non-blocking sockets must wait until data is available */
295 if (Status == STATUS_PENDING && Socket->SharedData->NonBlocking)
296 {
297 if (lpErrno) *lpErrno = WSAEWOULDBLOCK;
298 return SOCKET_ERROR;
299 }
300
301 /* Wait for completion of not overlapped */
303 {
304 /* It's up to the protocol to time out recv. We must wait
305 * until the protocol decides it's had enough.
306 */
308 Status = IOSB->Status;
309 }
310
312
313 TRACE("Status %x Information %d\n", Status, IOSB->Information);
314
315 if (Status == STATUS_PENDING)
316 {
317 TRACE("Leaving (Pending)\n");
318 return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead);
319 }
320
321 /* Return the Flags */
322 *ReceiveFlags = 0;
323
324 switch (Status)
325 {
327 *ReceiveFlags = MSG_OOB;
328 break;
330 *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
331 break;
333 *ReceiveFlags = MSG_PARTIAL;
334 break;
335 }
336
337 /* Re-enable Async Event */
338 if (*ReceiveFlags & MSG_OOB)
339 {
341 }
342 else
343 {
345 }
346
347 if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
348 {
349 lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags);
350 HeapFree(GlobalHeap, 0, (PVOID)APCContext);
351 }
352
353 return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead );
354}
355
356int
357WSPAPI
359 LPWSABUF lpBuffers,
360 DWORD dwBufferCount,
361 LPDWORD lpNumberOfBytesRead,
362 LPDWORD ReceiveFlags,
363 struct sockaddr *SocketAddress,
364 int *SocketAddressLength,
366 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
367 LPWSATHREADID lpThreadId,
368 LPINT lpErrno )
369{
370 PIO_STATUS_BLOCK IOSB;
371 IO_STATUS_BLOCK DummyIOSB;
372 AFD_RECV_INFO_UDP RecvInfo;
374 PVOID APCContext;
375 PVOID APCFunction;
376 HANDLE Event = NULL;
378 PSOCKET_INFORMATION Socket;
379
380 /* Get the Socket Structure associate to this Socket*/
381 Socket = GetSocketStructure(Handle);
382 if (!Socket)
383 {
384 if (lpErrno)
385 *lpErrno = WSAENOTSOCK;
386 return SOCKET_ERROR;
387 }
388 if (!lpNumberOfBytesRead && !lpOverlapped)
389 {
390 if (lpErrno)
391 *lpErrno = WSAEFAULT;
392 return SOCKET_ERROR;
393 }
394 if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0)
395 {
396 if (lpErrno)
397 *lpErrno = WSAEINVAL;
398 return SOCKET_ERROR;
399 }
400
402 {
403 /* Call WSPRecv for a non-datagram socket */
404 return WSPRecv(Handle,
405 lpBuffers,
406 dwBufferCount,
407 lpNumberOfBytesRead,
408 ReceiveFlags,
410 lpCompletionRoutine,
411 lpThreadId,
412 lpErrno);
413 }
414
415 /* Bind us First */
416 if (Socket->SharedData->State == SocketOpen)
417 {
419 SocketAddress,
420 SocketAddressLength);
421 /* Bind it */
422 if (WSPBind(Handle, SocketAddress, *SocketAddressLength, lpErrno) == SOCKET_ERROR)
423 return SOCKET_ERROR;
424 }
425
428
429 if( !NT_SUCCESS(Status) )
430 return -1;
431
432 /* Set up the Receive Structure */
433 RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
434 RecvInfo.BufferCount = dwBufferCount;
435 RecvInfo.TdiFlags = 0;
436 RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
437 RecvInfo.AddressLength = SocketAddressLength;
438 RecvInfo.Address = SocketAddress;
439
440 /* Set the TDI Flags */
441 if (*ReceiveFlags == 0)
442 {
443 RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
444 }
445 else
446 {
447 if (*ReceiveFlags & MSG_OOB)
448 {
450 }
451
452 if (*ReceiveFlags & MSG_PEEK)
453 {
454 RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
455 }
456
457 if (*ReceiveFlags & MSG_PARTIAL)
458 {
459 RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL;
460 }
461 }
462
463 /* Verify if we should use APC */
464
465 if (lpOverlapped == NULL)
466 {
467 /* Not using Overlapped structure, so use normal blocking on event */
468 APCContext = NULL;
469 APCFunction = NULL;
471 IOSB = &DummyIOSB;
472 }
473 else
474 {
475 /* Overlapped request for non overlapped opened socket */
476 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
477 {
478 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
479 return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead);
480 }
481 if (lpCompletionRoutine == NULL)
482 {
483 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
484 APCContext = lpOverlapped;
485 APCFunction = NULL;
486 Event = lpOverlapped->hEvent;
487 }
488 else
489 {
490 /* Using Overlapped Structure and a Completion Routine, so use an APC */
491 APCFunction = &AfdAPC; // should be a private io completion function inside us
492 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
493 if (!APCContext)
494 {
495 ERR("Not enough memory for APC Context\n");
496 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead);
497 }
498 ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
499 ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
500 ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
501 RecvInfo.AfdFlags |= AFD_SKIP_FIO;
502 }
503
504 IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
505 RecvInfo.AfdFlags |= AFD_OVERLAPPED;
506 }
507
508 IOSB->Status = STATUS_PENDING;
509
510 /* Send IOCTL */
512 Event,
513 APCFunction,
514 APCContext,
515 IOSB,
517 &RecvInfo,
518 sizeof(RecvInfo),
519 NULL,
520 0);
521
522 /* Wait for completion of not overlapped */
524 {
525 WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for receive...
526 Status = IOSB->Status;
527 }
528
530
531 if (Status == STATUS_PENDING)
532 {
533 TRACE("Leaving (Pending)\n");
534 return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead);
535 }
536
537 /* Return the Flags */
538 *ReceiveFlags = 0;
539
540 switch (Status)
541 {
543 *ReceiveFlags = MSG_OOB;
544 break;
546 *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
547 break;
549 *ReceiveFlags = MSG_PARTIAL;
550 break;
551 }
552
553 /* Re-enable Async Event */
554 if (*ReceiveFlags & MSG_OOB)
555 {
557 }
558 else
559 {
561 }
562
563 if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
564 {
565 lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags);
566 HeapFree(GlobalHeap, 0, (PVOID)APCContext);
567 }
568
569 return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead );
570}
571
572
573int
574WSPAPI
576 LPWSABUF lpBuffers,
577 DWORD dwBufferCount,
578 LPDWORD lpNumberOfBytesSent,
579 DWORD iFlags,
581 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
582 LPWSATHREADID lpThreadId,
583 LPINT lpErrno)
584{
585 PIO_STATUS_BLOCK IOSB;
586 IO_STATUS_BLOCK DummyIOSB;
587 AFD_SEND_INFO SendInfo;
589 PVOID APCContext;
590 PVOID APCFunction;
591 HANDLE Event = NULL;
593 PSOCKET_INFORMATION Socket;
594
595 /* Get the Socket Structure associate to this Socket*/
596 Socket = GetSocketStructure(Handle);
597 if (!Socket)
598 {
599 if (lpErrno)
600 *lpErrno = WSAENOTSOCK;
601 return SOCKET_ERROR;
602 }
603 if (!lpNumberOfBytesSent && !lpOverlapped)
604 {
605 if (lpErrno)
606 *lpErrno = WSAEFAULT;
607 return SOCKET_ERROR;
608 }
609
612
613 if( !NT_SUCCESS(Status) )
614 return -1;
615
616 TRACE("Called\n");
617
618 /* Set up the Send Structure */
619 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
620 SendInfo.BufferCount = dwBufferCount;
621 SendInfo.TdiFlags = 0;
622 SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
623
624 /* Set the TDI Flags */
625 if (iFlags)
626 {
627 if (iFlags & MSG_OOB)
628 {
629 SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
630 }
631 if (iFlags & MSG_PARTIAL)
632 {
633 SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
634 }
635 }
636
637 /* Verify if we should use APC */
638 if (lpOverlapped == NULL)
639 {
640 /* Not using Overlapped structure, so use normal blocking on event */
641 APCContext = NULL;
642 APCFunction = NULL;
644 IOSB = &DummyIOSB;
645 }
646 else
647 {
648 /* Overlapped request for non overlapped opened socket */
649 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
650 {
651 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
652 return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent);
653 }
654 if (lpCompletionRoutine == NULL)
655 {
656 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
657 APCContext = lpOverlapped;
658 APCFunction = NULL;
659 Event = lpOverlapped->hEvent;
660 }
661 else
662 {
663 /* Using Overlapped Structure and a Completion Routine, so use an APC */
664 APCFunction = &AfdAPC; // should be a private io completion function inside us
665 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
666 if (!APCContext)
667 {
668 ERR("Not enough memory for APC Context\n");
669 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
670 }
671 ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
672 ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
673 ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
674 SendInfo.AfdFlags |= AFD_SKIP_FIO;
675 }
676
677 IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
678 SendInfo.AfdFlags |= AFD_OVERLAPPED;
679 }
680
681 IOSB->Status = STATUS_PENDING;
682
683 /* Send IOCTL */
685 Event,
686 APCFunction,
687 APCContext,
688 IOSB,
690 &SendInfo,
691 sizeof(SendInfo),
692 NULL,
693 0);
694
695 /* Wait for completion of not overlapped */
697 {
698 WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for send...
699 Status = IOSB->Status;
700 }
701
703
704 if (Status == STATUS_PENDING)
705 {
706 TRACE("Leaving (Pending)\n");
707 return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
708 }
709
710 /* Re-enable Async Event */
712
713 TRACE("Leaving (Success, %d)\n", IOSB->Information);
714
715 if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
716 {
717 lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0);
718 HeapFree(GlobalHeap, 0, (PVOID)APCContext);
719 }
720
721 return MsafdReturnWithErrno( Status, lpErrno, IOSB->Information, lpNumberOfBytesSent );
722}
723
724int
725WSPAPI
727 LPWSABUF lpBuffers,
728 DWORD dwBufferCount,
729 LPDWORD lpNumberOfBytesSent,
730 DWORD iFlags,
731 const struct sockaddr *SocketAddress,
732 int SocketAddressLength,
734 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
735 LPWSATHREADID lpThreadId,
736 LPINT lpErrno)
737{
738 PIO_STATUS_BLOCK IOSB;
739 IO_STATUS_BLOCK DummyIOSB;
740 AFD_SEND_INFO_UDP SendInfo;
742 PVOID APCContext;
743 PVOID APCFunction;
744 HANDLE Event = NULL;
746 PSOCKADDR BindAddress = NULL;
747 INT BindAddressLength;
749 PSOCKET_INFORMATION Socket;
750
751 /* Get the Socket Structure associate to this Socket */
752 Socket = GetSocketStructure(Handle);
753 if (!Socket)
754 {
755 if (lpErrno)
756 *lpErrno = WSAENOTSOCK;
757 return SOCKET_ERROR;
758 }
759 if (!lpNumberOfBytesSent && !lpOverlapped)
760 {
761 if (lpErrno)
762 *lpErrno = WSAEFAULT;
763 return SOCKET_ERROR;
764 }
765
767 {
768 /* Use WSPSend for connection-oriented sockets */
769 return WSPSend(Handle,
770 lpBuffers,
771 dwBufferCount,
772 lpNumberOfBytesSent,
773 iFlags,
775 lpCompletionRoutine,
776 lpThreadId,
777 lpErrno);
778 }
779
780 /* Bind us First */
781 if (Socket->SharedData->State == SocketOpen)
782 {
783 /* Get the Wildcard Address */
784 BindAddressLength = Socket->HelperData->MaxWSAddressLength;
785 BindAddress = HeapAlloc(GlobalHeap, 0, BindAddressLength);
786 if (!BindAddress)
787 {
789 return INVALID_SOCKET;
790 }
791
793 BindAddress,
794 &BindAddressLength);
795 /* Bind it */
796 if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR)
797 return SOCKET_ERROR;
798 }
799
800 RemoteAddress = HeapAlloc(GlobalHeap, 0, 0x6 + SocketAddressLength);
801 if (!RemoteAddress)
802 {
803 if (BindAddress != NULL)
804 {
805 HeapFree(GlobalHeap, 0, BindAddress);
806 }
808 }
809
813
814 if (!NT_SUCCESS(Status))
815 {
817 if (BindAddress != NULL)
818 {
819 HeapFree(GlobalHeap, 0, BindAddress);
820 }
821 return SOCKET_ERROR;
822 }
823
824 /* Set up Address in TDI Format */
825 RemoteAddress->TAAddressCount = 1;
826 RemoteAddress->Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
827 RtlCopyMemory(&RemoteAddress->Address[0].AddressType, SocketAddress, SocketAddressLength);
828
829 /* Set up Structure */
830 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
831 SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
832 SendInfo.BufferCount = dwBufferCount;
835
836 /* Verify if we should use APC */
837 if (lpOverlapped == NULL)
838 {
839 /* Not using Overlapped structure, so use normal blocking on event */
840 APCContext = NULL;
841 APCFunction = NULL;
843 IOSB = &DummyIOSB;
844 }
845 else
846 {
847 /* Overlapped request for non overlapped opened socket */
848 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
849 {
850 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
851 return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent);
852 }
853 if (lpCompletionRoutine == NULL)
854 {
855 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
856 APCContext = lpOverlapped;
857 APCFunction = NULL;
858 Event = lpOverlapped->hEvent;
859 }
860 else
861 {
862 /* Using Overlapped Structure and a Completion Routine, so use an APC */
863 APCFunction = &AfdAPC; // should be a private io completion function inside us
864 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
865 if (!APCContext)
866 {
867 ERR("Not enough memory for APC Context\n");
868 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
869 }
870 ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
871 ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
872 ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
873 SendInfo.AfdFlags |= AFD_SKIP_FIO;
874 }
875
876 IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
877 SendInfo.AfdFlags |= AFD_OVERLAPPED;
878 }
879
880 /* Send IOCTL */
882 Event,
883 APCFunction,
884 APCContext,
885 IOSB,
887 &SendInfo,
888 sizeof(SendInfo),
889 NULL,
890 0);
891
892 /* Wait for completion of not overlapped */
894 {
895 /* BUGBUG, shouldn't wait infinitely for send... */
897 Status = IOSB->Status;
898 }
899
902 if (BindAddress != NULL)
903 {
904 HeapFree(GlobalHeap, 0, BindAddress);
905 }
906
907 if (Status == STATUS_PENDING)
908 {
909 TRACE("Leaving (Pending)\n");
910 return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
911 }
912
914
915 if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
916 {
917 lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0);
918 HeapFree(GlobalHeap, 0, (PVOID)APCContext);
919 }
920
921 return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
922}
923
924INT
925WSPAPI
927 OUT LPWSABUF lpInboundDisconnectData,
928 OUT LPINT lpErrno)
929{
931 return 0;
932}
933
934
935
936INT
937WSPAPI
939 IN LPWSABUF lpOutboundDisconnectData,
940 OUT LPINT lpErrno)
941{
943 return 0;
944}
945
946/* EOF */
unsigned char BOOLEAN
HWND hWnd
Definition: settings.c:17
LONG NTSTATUS
Definition: precomp.h:26
#define UNIMPLEMENTED
Definition: debug.h:115
#define ERR(fmt,...)
Definition: debug.h:110
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
HANDLE SockAsyncCompletionPort
Definition: dllmain.c:28
INT WSPAPI WSPBind(SOCKET Handle, const struct sockaddr *SocketAddress, int SocketAddressLength, LPINT lpErrno)
Definition: dllmain.c:846
BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
Definition: dllmain.c:3593
PSOCKET_INFORMATION GetSocketStructure(SOCKET Handle)
Definition: dllmain.c:3520
HANDLE GlobalHeap
Definition: dllmain.c:19
VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
Definition: dllmain.c:3962
int SetSocketInformation(PSOCKET_INFORMATION Socket, ULONG AfdInformationClass, PBOOLEAN Boolean OPTIONAL, PULONG Ulong OPTIONAL, PLARGE_INTEGER LargeInteger OPTIONAL, LPWSAOVERLAPPED Overlapped OPTIONAL, LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine OPTIONAL)
Definition: dllmain.c:3397
VOID SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, IN ULONG Event)
Definition: dllmain.c:3996
BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
Definition: dllmain.c:3688
int WSPAPI WSPEventSelect(IN SOCKET Handle, IN WSAEVENT hEventObject, IN long lNetworkEvents, OUT LPINT lpErrno)
Definition: event.c:17
FORCEINLINE DWORD MsafdReturnWithErrno(NTSTATUS Status, LPINT Errno, DWORD Received, LPDWORD ReturnedBytes)
Definition: msafd.h:546
struct _AFDAPCCONTEXT * PAFDAPCCONTEXT
HANDLE SockEvent
@ SocketOpen
Definition: msafd.h:46
#define SO_SYNCHRONOUS_NONALERT
Definition: ws2_32.h:41
#define INFINITE
Definition: serial.h:102
struct _IO_STATUS_BLOCK * PIO_STATUS_BLOCK
Definition: change.c:34
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLdouble s
Definition: gl.h:2039
NTSTATUS NTAPI NtSetIoCompletion(IN HANDLE IoCompletionPortHandle, IN PVOID CompletionKey, IN PVOID CompletionContext, IN NTSTATUS CompletionStatus, IN ULONG CompletionInformation)
Definition: iocomp.c:569
BOOL WINAPI GetOverlappedResult(IN HANDLE hFile, IN LPOVERLAPPED lpOverlapped, OUT LPDWORD lpNumberOfBytesTransferred, IN BOOL bWait)
Definition: iocompl.c:221
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED lpOverlapped
Definition: mswsock.h:93
unsigned int UINT
Definition: ndis.h:50
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE _In_opt_ PVOID ApcContext
Definition: iofuncs.h:727
NTSYSAPI NTSTATUS NTAPI NtDeviceIoControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
VOID(* PIO_APC_ROUTINE)(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved)
Definition: nt_native.h:877
@ SynchronizationEvent
NTSTATUS NTAPI NtCreateEvent(OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN EVENT_TYPE EventType, IN BOOLEAN InitialState)
Definition: event.c:96
#define STATUS_RECEIVE_EXPEDITED
Definition: ntstatus.h:130
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_RECEIVE_PARTIAL
Definition: ntstatus.h:129
#define STATUS_RECEIVE_PARTIAL_EXPEDITED
Definition: ntstatus.h:131
long LONG
Definition: pedump.c:60
#define AFD_IMMEDIATE
Definition: shared.h:220
#define AFD_OVERLAPPED
Definition: shared.h:219
#define AFD_INFO_BLOCKING_MODE
Definition: shared.h:183
#define IOCTL_AFD_RECV
Definition: shared.h:277
#define AFD_SKIP_FIO
Definition: shared.h:218
#define IOCTL_AFD_SEND_DATAGRAM
Definition: shared.h:283
struct _AFD_WSABUF * PAFD_WSABUF
#define IOCTL_AFD_RECV_DATAGRAM
Definition: shared.h:279
#define IOCTL_AFD_SEND
Definition: shared.h:281
#define STATUS_SUCCESS
Definition: shellext.h:65
VOID NTAPI AfdAPC(PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG Reserved)
Definition: sndrcv.c:140
INT WSPAPI WSPSendDisconnect(IN SOCKET s, IN LPWSABUF lpOutboundDisconnectData, OUT LPINT lpErrno)
Definition: sndrcv.c:938
int WSPAPI WSPRecvFrom(SOCKET Handle, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRead, LPDWORD ReceiveFlags, struct sockaddr *SocketAddress, int *SocketAddressLength, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno)
Definition: sndrcv.c:358
BOOL WSPAPI WSPGetOverlappedResult(IN SOCKET Handle, IN LPWSAOVERLAPPED lpOverlapped, OUT LPDWORD lpdwBytes, IN BOOL fWait, OUT LPDWORD lpdwFlags, OUT LPINT lpErrno)
Definition: sndrcv.c:96
INT WSPAPI WSPAsyncSelect(IN SOCKET Handle, IN HWND hWnd, IN UINT wMsg, IN LONG lEvent, OUT LPINT lpErrno)
Definition: sndrcv.c:17
int WSPAPI WSPSendTo(SOCKET Handle, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD iFlags, const struct sockaddr *SocketAddress, int SocketAddressLength, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno)
Definition: sndrcv.c:726
int WSPAPI WSPSend(SOCKET Handle, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD iFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno)
Definition: sndrcv.c:575
int WSPAPI WSPRecv(SOCKET Handle, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesRead, LPDWORD ReceiveFlags, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno)
Definition: sndrcv.c:157
INT WSPAPI WSPRecvDisconnect(IN SOCKET s, OUT LPWSABUF lpInboundDisconnectData, OUT LPINT lpErrno)
Definition: sndrcv.c:926
#define TRACE(s)
Definition: solgame.cpp:4
ULONG AfdFlags
Definition: shared.h:94
PINT AddressLength
Definition: shared.h:97
ULONG BufferCount
Definition: shared.h:93
ULONG TdiFlags
Definition: shared.h:95
PAFD_WSABUF BufferArray
Definition: shared.h:92
ULONG BufferCount
Definition: shared.h:86
ULONG TdiFlags
Definition: shared.h:88
ULONG AfdFlags
Definition: shared.h:87
PAFD_WSABUF BufferArray
Definition: shared.h:85
ULONG BufferCount
Definition: shared.h:109
TDI_CONNECTION_INFORMATION TdiConnection
Definition: shared.h:112
PAFD_WSABUF BufferArray
Definition: shared.h:108
ULONG BufferCount
Definition: shared.h:102
PAFD_WSABUF BufferArray
Definition: shared.h:101
ULONG TdiFlags
Definition: shared.h:104
ULONG AfdFlags
Definition: shared.h:103
DWORD SequenceNumber
Definition: msafd.h:131
PSOCKET_INFORMATION ParentSocket
Definition: msafd.h:130
INT MaxTDIAddressLength
Definition: helpers.h:19
INT MaxWSAddressLength
Definition: helpers.h:17
PWSH_GET_WILDCARD_SOCKADDR WSHGetWildcardSockaddr
Definition: helpers.h:29
PVOID HelperContext
Definition: msafd.h:104
PSOCK_SHARED_INFO SharedData
Definition: msafd.h:100
PHELPER_DATA HelperData
Definition: msafd.h:103
LONG AsyncDisabledEvents
Definition: msafd.h:93
BOOLEAN OobInline
Definition: msafd.h:71
SOCKET_STATE State
Definition: msafd.h:54
BOOLEAN NonBlocking
Definition: msafd.h:74
LONG AsyncEvents
Definition: msafd.h:92
DWORD SequenceNumber
Definition: msafd.h:90
DWORD ServiceFlags1
Definition: msafd.h:82
DWORD CreateFlags
Definition: msafd.h:81
u_short sa_family
Definition: winsock.h:217
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define TDI_SEND_EXPEDITED
Definition: tdi.h:135
#define TDI_RECEIVE_PARTIAL
Definition: tdi.h:121
#define TDI_RECEIVE_EXPEDITED
Definition: tdi.h:123
#define TDI_RECEIVE_PEEK
Definition: tdi.h:124
#define TDI_RECEIVE_NORMAL
Definition: tdi.h:122
#define TDI_SEND_PARTIAL
Definition: tdi.h:136
HANDLE lEvent
Definition: tftpd.cpp:56
#define NTAPI
Definition: typedefs.h:36
uint32_t * LPDWORD
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Reserved_ PVOID Reserved
Definition: winddi.h:3974
int * LPINT
Definition: windef.h:178
#define WSAEWOULDBLOCK
Definition: winerror.h:1948
#define WSAEINVAL
Definition: winerror.h:1946
#define WSAENOTSOCK
Definition: winerror.h:1951
#define WSAEFAULT
Definition: winerror.h:1945
#define XP1_CONNECTIONLESS
Definition: winsock2.h:436
void(CALLBACK * LPWSAOVERLAPPED_COMPLETION_ROUTINE)(IN DWORD dwError, IN DWORD cbTransferred, IN LPWSAOVERLAPPED lpOverlapped, IN DWORD dwFlags)
Definition: winsock2.h:722
#define FD_READ
Definition: winsock.h:405
#define FD_WRITE
Definition: winsock.h:406
#define INVALID_SOCKET
Definition: winsock.h:332
UINT_PTR SOCKET
Definition: winsock.h:47
#define MSG_PEEK
Definition: winsock.h:222
#define SOCKET_ERROR
Definition: winsock.h:333
#define MSG_OOB
Definition: winsock.h:221
#define MSG_PARTIAL
Definition: winsock.h:402
#define FD_OOB
Definition: winsock.h:407
#define WSPAPI
Definition: ws2spi.h:39
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR RemoteAddress
Definition: wsk.h:172