ReactOS 0.4.16-dev-2206-gc56950d
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;
106 BOOL Ret;
107
108 TRACE("Called (%x)\n", Handle);
109
110 /* Get the Socket Structure associate to this Socket*/
111 Socket = GetSocketStructure(Handle);
112 if (!Socket)
113 {
114 if(lpErrno)
115 *lpErrno = WSAENOTSOCK;
116 return FALSE;
117 }
118 if (!lpOverlapped || !lpdwBytes || !lpdwFlags)
119 {
120 if (lpErrno)
121 *lpErrno = WSAEFAULT;
122 return FALSE;
123 }
124
126 Ret = GetOverlappedResult((HANDLE)Handle, lpOverlapped, lpdwBytes, fWait);
127
128 /* HACK: Allow APC to be processed */
129 SleepEx(0, TRUE);
130
131 if (!fWait && IoStatusBlock->Status == STATUS_PENDING)
132 {
133 if (lpErrno)
134 *lpErrno = WSA_IO_INCOMPLETE;
135 return FALSE;
136 }
137
138 if (Ret)
139 {
140
141 /* Re-enable Async Event */
145 }
146
147 switch (IoStatusBlock->Status)
148 {
150 *lpdwFlags = MSG_OOB;
151 break;
153 *lpdwFlags = MSG_PARTIAL | MSG_OOB;
154 break;
156 *lpdwFlags = MSG_PARTIAL;
157 break;
158 default:
159 *lpdwFlags = 0;
160 if (lpErrno)
162 break;
163 }
164
165 return Ret;
166}
167
168static
169VOID
170NTAPI
175{
177
178 TRACE("MsafdRecvAPC(%p %lx %lx)\n", ApcContext, IoStatusBlock->Status, IoStatusBlock->Information);
179
180 /* Re-enable Async Event */
183 {
185 }
186 else
187 {
189 }
190
191 if (Context->lpCompletionRoutine)
193
195}
196
197static
198VOID
199NTAPI
204{
206
207 TRACE("MsafdSendAPC(%p %lx %lx)\n", ApcContext, IoStatusBlock->Status, IoStatusBlock->Information);
208
209 /* Re-enable Async Event */
211
212 if (Context->lpCompletionRoutine)
214
215 /* Free IOCTL buffers */
217}
218
219int
220WSPAPI
222 LPWSABUF lpBuffers,
223 DWORD dwBufferCount,
224 LPDWORD lpNumberOfBytesRead,
225 LPDWORD ReceiveFlags,
227 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
228 LPWSATHREADID lpThreadId,
229 LPINT lpErrno)
230{
231 PIO_STATUS_BLOCK IOSB;
232 IO_STATUS_BLOCK DummyIOSB;
233 AFD_RECV_INFO RecvInfo;
235 PMSAFD_RECV_APC_CONTEXT APCContext;
236 PIO_APC_ROUTINE APCFunction = NULL;
237 HANDLE Event = NULL;
239 PSOCKET_INFORMATION Socket;
240 DWORD NumberOfBytesRead;
241
242 TRACE("WSPRecv(%x)\n", Handle);
243
244 /* Get the Socket Structure associate to this Socket*/
245 Socket = GetSocketStructure(Handle);
246 if (!Socket)
247 {
248 if (lpErrno)
249 *lpErrno = WSAENOTSOCK;
250 return SOCKET_ERROR;
251 }
252 if (!lpNumberOfBytesRead && !lpOverlapped)
253 {
254 if (lpErrno)
255 *lpErrno = WSAEFAULT;
256 return SOCKET_ERROR;
257 }
258 if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0)
259 {
260 if (lpErrno)
261 *lpErrno = WSAEINVAL;
262 return SOCKET_ERROR;
263 }
264
265 memset(&RecvInfo, 0, sizeof(RecvInfo));
266
269
270 if (!NT_SUCCESS(Status))
271 {
272 return SOCKET_ERROR;
273 }
274
275 /* Set up the Receive Structure */
276 RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
277 RecvInfo.BufferCount = dwBufferCount;
278 RecvInfo.TdiFlags = 0;
279 RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
280
281 /* Set the TDI Flags */
282 if (!ReceiveFlags || *ReceiveFlags == 0)
283 {
284 RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
285 }
286 else
287 {
288 if (*ReceiveFlags & MSG_OOB)
289 {
291 }
292
293 if (*ReceiveFlags & MSG_PEEK)
294 {
295 RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
296 }
297
298 if (*ReceiveFlags & MSG_PARTIAL)
299 {
300 RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL;
301 }
302 }
303
304 /* Verify if we should use APC */
305 if (!lpOverlapped)
306 {
307 /* Not using Overlapped structure, so use normal blocking on event */
308 APCContext = NULL;
309 APCFunction = NULL;
311 IOSB = &DummyIOSB;
312 }
313 else
314 {
315 /* Overlapped request for non overlapped opened socket */
316 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
317 {
318 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
320 return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesRead);
321 }
322
324 if (lpCompletionRoutine)
325 {
326 RecvInfo.AfdFlags |= AFD_SKIP_FIO;
327 APCFunction = &MsafdRecvAPC;
328 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(*APCContext));
329 if (!APCContext)
330 {
331 ERR("Not enough memory for APC Context\n");
333 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead);
334 }
335 APCContext->lpCompletionRoutine = lpCompletionRoutine;
336 APCContext->lpOverlapped = lpOverlapped;
337 APCContext->lpSocket = Socket;
338 Event = NULL;
339 }
340 else
341 {
342 // .NET expects APCContext to be a pointer to lpOverlapped, because it adds some additional metadata past OVERLAPPED structure
343 // Do not use APC when there is no completion context
344 Event = lpOverlapped->hEvent;
345
346 APCFunction = NULL;
347 if (Event)
348 {
349 APCContext = NULL;
350 }
351 else
352 {
354 }
355 }
356
357 RecvInfo.AfdFlags |= AFD_OVERLAPPED;
358 }
359
360 IOSB->Information = 0;
361 IOSB->Status = STATUS_PENDING;
362
363 /* Send IOCTL */
365 Event,
366 APCFunction,
367 APCContext,
368 IOSB,
370 &RecvInfo,
371 sizeof(RecvInfo),
372 NULL,
373 0);
374
375 /* Wait for completion if not overlapped */
377 {
378 /* It's up to the protocol to time out recv. We must wait
379 * until the protocol decides it's had enough. */
381 Status = IOSB->Status;
382 }
383
385
386 if (Status == STATUS_PENDING)
387 {
388 TRACE("Leaving (Pending)\n");
389 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
390 }
391
392 NumberOfBytesRead = (DWORD)IOSB->Information;
393
394 /* Return the Flags */
395 if (ReceiveFlags)
396 {
397 switch (Status)
398 {
400 *ReceiveFlags = MSG_OOB;
401 break;
403 *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
404 break;
406 *ReceiveFlags = MSG_PARTIAL;
407 break;
408 default:
409 *ReceiveFlags = 0;
410 break;
411 }
412 }
413
414 /* Re-enable Async Event */
415 if (ReceiveFlags && (*ReceiveFlags & MSG_OOB))
416 {
418 }
419 else
420 {
422 }
423
424 TRACE("Leaving (%lx %ld)\n", Status, NumberOfBytesRead);
425 return MsafdReturnWithErrno(Status, lpErrno, NumberOfBytesRead, lpNumberOfBytesRead);
426}
427
428int
429WSPAPI
431 LPWSABUF lpBuffers,
432 DWORD dwBufferCount,
433 LPDWORD lpNumberOfBytesRead,
434 LPDWORD ReceiveFlags,
435 struct sockaddr *SocketAddress,
436 int *SocketAddressLength,
438 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
439 LPWSATHREADID lpThreadId,
440 LPINT lpErrno )
441{
442 PIO_STATUS_BLOCK IOSB;
443 IO_STATUS_BLOCK DummyIOSB;
444 AFD_RECV_INFO_UDP RecvInfo;
446 PMSAFD_RECV_APC_CONTEXT APCContext;
447 PIO_APC_ROUTINE APCFunction = NULL;
448 HANDLE Event = NULL;
450 PSOCKET_INFORMATION Socket;
451 DWORD NumberOfBytesRead;
452
453 TRACE("WSPRecvFrom(%x)\n", Handle);
454
455 /* Get the Socket Structure associate to this Socket*/
456 Socket = GetSocketStructure(Handle);
457 if (!Socket)
458 {
459 if (lpErrno)
460 *lpErrno = WSAENOTSOCK;
461 return SOCKET_ERROR;
462 }
463 if (!lpNumberOfBytesRead && !lpOverlapped)
464 {
465 if (lpErrno)
466 *lpErrno = WSAEFAULT;
467 return SOCKET_ERROR;
468 }
469 if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0)
470 {
471 if (lpErrno)
472 *lpErrno = WSAEINVAL;
473 return SOCKET_ERROR;
474 }
475
477 {
478 /* Call WSPRecv for a non-datagram socket */
479 return WSPRecv(Handle,
480 lpBuffers,
481 dwBufferCount,
482 lpNumberOfBytesRead,
483 ReceiveFlags,
485 lpCompletionRoutine,
486 lpThreadId,
487 lpErrno);
488 }
489
490 /* Bind us First */
491 if (Socket->SharedData->State == SocketOpen)
492 {
494 SocketAddress,
495 SocketAddressLength);
496 /* Bind it */
497 if (WSPBind(Handle, SocketAddress, *SocketAddressLength, lpErrno) == SOCKET_ERROR)
498 return SOCKET_ERROR;
499 }
500 memset(&RecvInfo, 0, sizeof(RecvInfo));
501
504
505 if( !NT_SUCCESS(Status) )
506 {
507 return SOCKET_ERROR;
508 }
509
510 /* Set up the Receive Structure */
511 RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
512 RecvInfo.BufferCount = dwBufferCount;
513 RecvInfo.TdiFlags = 0;
514 RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
515 RecvInfo.AddressLength = SocketAddressLength;
516 RecvInfo.Address = SocketAddress;
517
518 /* Set the TDI Flags */
519 if (!ReceiveFlags || *ReceiveFlags == 0)
520 {
521 RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
522 }
523 else
524 {
525 if (*ReceiveFlags & MSG_OOB)
526 {
528 }
529
530 if (*ReceiveFlags & MSG_PEEK)
531 {
532 RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
533 }
534
535 if (*ReceiveFlags & MSG_PARTIAL)
536 {
537 RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL;
538 }
539 }
540
541 /* Verify if we should use APC */
542 if (!lpOverlapped)
543 {
544 /* Not using Overlapped structure, so use normal blocking on event */
545 APCContext = NULL;
546 APCFunction = NULL;
548 IOSB = &DummyIOSB;
549 }
550 else
551 {
552 /* Overlapped request for non overlapped opened socket */
553 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
554 {
555 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
557 return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesRead);
558 }
559
561 if (lpCompletionRoutine)
562 {
563 RecvInfo.AfdFlags |= AFD_SKIP_FIO;
564 APCFunction = &MsafdRecvAPC;
565 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(*APCContext));
566 if (!APCContext)
567 {
568 ERR("Not enough memory for APC Context\n");
570 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead);
571 }
572 APCContext->lpCompletionRoutine = lpCompletionRoutine;
573 APCContext->lpOverlapped = lpOverlapped;
574 APCContext->lpSocket = Socket;
575 Event = NULL;
576 }
577 else
578 {
579 // .NET expects APCContext to be a pointer to lpOverlapped, because it adds some additional metadata past OVERLAPPED structure
580 // Do not use APC when there is no completion context
581 Event = lpOverlapped->hEvent;
582
583 APCFunction = NULL;
584 if (Event)
585 {
586 APCContext = NULL;
587 }
588 else
589 {
591 }
592 }
593
594 RecvInfo.AfdFlags |= AFD_OVERLAPPED;
595 }
596
597 IOSB->Information = 0;
598 IOSB->Status = STATUS_PENDING;
599
600 /* Send IOCTL */
602 Event,
603 APCFunction,
604 APCContext,
605 IOSB,
607 &RecvInfo,
608 sizeof(RecvInfo),
609 NULL,
610 0);
611
612 /* Wait for completion if not overlapped */
614 {
615 /* FIXME: Shouldn't wait infinitely for receive... */
617 Status = IOSB->Status;
618 }
619
620 /* Return the Flags */
621 if (ReceiveFlags)
622 {
623 switch (Status)
624 {
626 *ReceiveFlags = MSG_OOB;
627 break;
629 *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
630 break;
632 *ReceiveFlags = MSG_PARTIAL;
633 break;
634 default:
635 *ReceiveFlags = 0;
636 break;
637 }
638 }
639
641
642 if (Status == STATUS_PENDING)
643 {
644 TRACE("Leaving (Pending)\n");
645 *lpErrno = WSA_IO_PENDING;
646 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
647 }
648
649 NumberOfBytesRead = (DWORD)IOSB->Information;
650
651 /* Re-enable Async Event */
652 if (ReceiveFlags && (*ReceiveFlags & MSG_OOB))
653 {
655 }
656 else
657 {
659 }
660
661 TRACE("Leaving (%lx %ld)\n", Status, NumberOfBytesRead);
662 return MsafdReturnWithErrno(Status, lpErrno, NumberOfBytesRead, lpNumberOfBytesRead);
663}
664
665
666int
667WSPAPI
669 LPWSABUF lpBuffers,
670 DWORD dwBufferCount,
671 LPDWORD lpNumberOfBytesSent,
672 DWORD iFlags,
674 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
675 LPWSATHREADID lpThreadId,
676 LPINT lpErrno)
677{
678 PIO_STATUS_BLOCK IOSB;
679 IO_STATUS_BLOCK DummyIOSB;
680 AFD_SEND_INFO SendInfo;
682 PMSAFD_SEND_APC_CONTEXT APCContext;
683 PIO_APC_ROUTINE APCFunction = NULL;
684 HANDLE Event = NULL;
686 PSOCKET_INFORMATION Socket;
687 DWORD NumberOfBytesSent;
688
689 TRACE("WSPSend(%x)\n", Handle);
690
691 /* Get the Socket Structure associate to this Socket*/
692 Socket = GetSocketStructure(Handle);
693 if (!Socket)
694 {
695 if (lpErrno)
696 *lpErrno = WSAENOTSOCK;
697 return SOCKET_ERROR;
698 }
699 if (!lpNumberOfBytesSent && !lpOverlapped)
700 {
701 if (lpErrno)
702 *lpErrno = WSAEFAULT;
703 return SOCKET_ERROR;
704 }
705
706 memset(&SendInfo, 0, sizeof(SendInfo));
707
710
711 if( !NT_SUCCESS(Status) )
712 {
713 return SOCKET_ERROR;
714 }
715
716 /* Set up the Send Structure */
717 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
718 SendInfo.BufferCount = dwBufferCount;
719 SendInfo.TdiFlags = 0;
720 SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
721
722 /* Set the TDI Flags */
723 if (iFlags)
724 {
725 if (iFlags & MSG_OOB)
726 {
727 SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
728 }
729 if (iFlags & MSG_PARTIAL)
730 {
731 SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
732 }
733 }
734
735 /* Verify if we should use APC */
736 if (!lpOverlapped)
737 {
738 /* Not using Overlapped structure, so use normal blocking on event */
739 APCContext = NULL;
740 APCFunction = NULL;
742 IOSB = &DummyIOSB;
743 }
744 else
745 {
746 /* Overlapped request for non overlapped opened socket */
747 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
748 {
749 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
751 return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesSent);
752 }
753
755 if (lpCompletionRoutine)
756 {
757 SendInfo.AfdFlags |= AFD_SKIP_FIO;
758 APCFunction = &MsafdSendAPC;
759 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(*APCContext));
760 if (!APCContext)
761 {
762 ERR("Not enough memory for APC Context\n");
764 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
765 }
766 APCContext->lpCompletionRoutine = lpCompletionRoutine;
767 APCContext->lpOverlapped = lpOverlapped;
768 APCContext->lpSocket = Socket;
769 APCContext->lpRemoteAddress = NULL;
770 Event = NULL;
771 }
772 else
773 {
774 // .NET expects APCContext to be a pointer to lpOverlapped, because it adds some additional metadata past OVERLAPPED structure
775 // Do not use APC when there is no completion context
776 Event = lpOverlapped->hEvent;
777
778 APCFunction = NULL;
779 if (Event)
780 {
781 APCContext = NULL;
782 }
783 else
784 {
786 }
787 }
788
789 Event = lpOverlapped->hEvent;
790 // APCContext is unsupported when using event
791 if (Event)
792 {
793 if (lpCompletionRoutine)
794 HeapFree(GetProcessHeap(), 0, APCContext);
795 APCContext = NULL;
796 }
797
798 SendInfo.AfdFlags |= AFD_OVERLAPPED;
799 }
800
801 IOSB->Information = 0;
802 IOSB->Status = STATUS_PENDING;
803
804 /* Send IOCTL */
806 Event,
807 APCFunction,
808 APCContext,
809 IOSB,
811 &SendInfo,
812 sizeof(SendInfo),
813 NULL,
814 0);
815
816 /* Wait for completion if not overlapped */
818 {
819 /* FIXME: Shouldn't wait infinitely for send... */
821 Status = IOSB->Status;
822 }
823
825
826 if (Status == STATUS_PENDING)
827 {
828 TRACE("Leaving (Pending)\n");
829 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
830 }
831
832 NumberOfBytesSent = (DWORD)IOSB->Information;
833
834 /* Re-enable Async Event */
836
837 TRACE("Leaving (%lx %ld)\n", Status, NumberOfBytesSent);
838 return MsafdReturnWithErrno(Status, lpErrno, NumberOfBytesSent, lpNumberOfBytesSent);
839}
840
841int
842WSPAPI
844 LPWSABUF lpBuffers,
845 DWORD dwBufferCount,
846 LPDWORD lpNumberOfBytesSent,
847 DWORD iFlags,
848 const struct sockaddr *SocketAddress,
849 int SocketAddressLength,
851 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
852 LPWSATHREADID lpThreadId,
853 LPINT lpErrno)
854{
855 PIO_STATUS_BLOCK IOSB;
856 IO_STATUS_BLOCK DummyIOSB;
857 AFD_SEND_INFO_UDP SendInfo;
859 PMSAFD_SEND_APC_CONTEXT APCContext;
860 PIO_APC_ROUTINE APCFunction = NULL;
861 HANDLE Event = NULL;
864 PSOCKET_INFORMATION Socket;
865 DWORD NumberOfBytesSent;
866 UCHAR Buffer[128];
867
868 TRACE("WSPSendTo(%x)\n", Handle);
869
870 /* Get the Socket Structure associate to this Socket */
871 Socket = GetSocketStructure(Handle);
872 if (!Socket)
873 {
874 if (lpErrno)
875 *lpErrno = WSAENOTSOCK;
876 return SOCKET_ERROR;
877 }
878 if (!lpNumberOfBytesSent && !lpOverlapped)
879 {
880 if (lpErrno)
881 *lpErrno = WSAEFAULT;
882 return SOCKET_ERROR;
883 }
884
886 {
887 /* Use WSPSend for connection-oriented sockets */
888 return WSPSend(Handle,
889 lpBuffers,
890 dwBufferCount,
891 lpNumberOfBytesSent,
892 iFlags,
894 lpCompletionRoutine,
895 lpThreadId,
896 lpErrno);
897 }
898
899 /* Bind us First */
900 if (Socket->SharedData->State == SocketOpen)
901 {
902 INT BindAddressLength;
903 PSOCKADDR BindAddress;
904 INT BindError;
905
906 /* Get the Wildcard Address */
907 BindAddressLength = Socket->HelperData->MaxWSAddressLength;
908 BindAddress = HeapAlloc(GlobalHeap, 0, BindAddressLength);
909 if (!BindAddress)
910 {
912 return INVALID_SOCKET;
913 }
914
916 BindAddress,
917 &BindAddressLength);
918 /* Bind it */
919 BindError = WSPBind(Handle, BindAddress, BindAddressLength, lpErrno);
920 HeapFree(GlobalHeap, 0, BindAddress);
921 if (BindError == SOCKET_ERROR)
922 return SOCKET_ERROR;
923 }
924
928
929 if (!NT_SUCCESS(Status))
930 {
931 return SOCKET_ERROR;
932 }
933
935
936 if (SocketAddressLength > 128 - sizeof(TRANSPORT_ADDRESS)) {
937 *lpErrno = WSAEFAULT;
938 return SOCKET_ERROR;
939 }
940
941 /* Fill TDI address */
942 RemoteAddress->TAAddressCount = 1;
943 RemoteAddress->Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
944 RtlCopyMemory(&RemoteAddress->Address[0].AddressType, SocketAddress, SocketAddressLength);
945
946 /* Set up Structure */
947 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
948 SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
949 SendInfo.BufferCount = dwBufferCount;
952
953 /* Verify if we should use APC */
954 if (!lpOverlapped)
955 {
956 /* Not using Overlapped structure, so use normal blocking on event */
957 APCContext = NULL;
958 APCFunction = NULL;
960 IOSB = &DummyIOSB;
961 }
962 else
963 {
964 /* Overlapped request for non overlapped opened socket */
965 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
966 {
967 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
969 return MsafdReturnWithErrno(STATUS_SUCCESS, lpErrno, 0, lpNumberOfBytesSent);
970 }
971
973 if (lpCompletionRoutine)
974 {
975 SendInfo.AfdFlags |= AFD_SKIP_FIO;
976 APCFunction = &MsafdSendAPC;
977 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(*APCContext));
978 if (!APCContext)
979 {
980 ERR("Not enough memory for APC Context\n");
982 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
983 }
984 APCContext->lpCompletionRoutine = lpCompletionRoutine;
985 APCContext->lpOverlapped = lpOverlapped;
986 APCContext->lpSocket = Socket;
987 APCContext->lpRemoteAddress = RemoteAddress;
988 Event = NULL;
989 }
990 else
991 {
992 // .NET expects APCContext to be a pointer to lpOverlapped, because it adds some additional metadata past OVERLAPPED structure
993 // Do not use APC when there is no completion context
994 Event = lpOverlapped->hEvent;
995
996 APCFunction = NULL;
997 if (Event)
998 {
999 APCContext = NULL;
1000 }
1001 else
1002 {
1004 }
1005 }
1006
1007 SendInfo.AfdFlags |= AFD_OVERLAPPED;
1008 }
1009
1010 IOSB->Information = 0;
1011 IOSB->Status = STATUS_PENDING;
1012
1013 /* Send IOCTL */
1015 Event,
1016 APCFunction,
1017 APCContext,
1018 IOSB,
1020 &SendInfo,
1021 sizeof(SendInfo),
1022 NULL,
1023 0);
1024
1025 /* Wait for completion if not overlapped */
1027 {
1028 /* FIXME: Shouldn't wait infinitely for send... */
1030 Status = IOSB->Status;
1031 }
1032
1034
1035 if (Status == STATUS_PENDING)
1036 {
1037 TRACE("Leaving (Pending)\n");
1038 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
1039 }
1040
1041 NumberOfBytesSent = (DWORD)IOSB->Information;
1042
1043 /* Re-enable Async Event */
1045
1046 TRACE("Leaving (%lx %ld)\n", Status, NumberOfBytesSent);
1047 return MsafdReturnWithErrno(Status, lpErrno, NumberOfBytesSent, lpNumberOfBytesSent);
1048}
1049
1050INT
1051WSPAPI
1053 OUT LPWSABUF lpInboundDisconnectData,
1054 OUT LPINT lpErrno)
1055{
1057 return 0;
1058}
1059
1060
1061
1062INT
1063WSPAPI
1065 IN LPWSABUF lpOutboundDisconnectData,
1066 OUT LPINT lpErrno)
1067{
1069 return 0;
1070}
1071
1072/* EOF */
unsigned char BOOLEAN
HWND hWnd
Definition: settings.c:17
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: precomp.h:57
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
Definition: bufpool.h:45
#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:33
#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:860
BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
Definition: dllmain.c:3702
VOID MsafdWaitForAlert(_In_ HANDLE hObject)
Definition: dllmain.c:614
PSOCKET_INFORMATION GetSocketStructure(SOCKET Handle)
Definition: dllmain.c:3629
HANDLE GlobalHeap
Definition: dllmain.c:19
VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
Definition: dllmain.c:4071
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:3507
INT TranslateNtStatusError(NTSTATUS Status)
Definition: dllmain.c:537
VOID SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, IN ULONG Event)
Definition: dllmain.c:4105
BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
Definition: dllmain.c:3797
int WSPAPI WSPEventSelect(IN SOCKET Handle, IN WSAEVENT hEventObject, IN long lNetworkEvents, OUT LPINT lpErrno)
Definition: event.c:17
FORCEINLINE DWORD MsafdReturnWithErrno(_In_ NTSTATUS Status, _Out_opt_ LPINT Errno, _In_ DWORD Received, _Out_opt_ LPDWORD ReturnedBytes)
Definition: msafd.h:568
struct _MSAFD_RECV_APC_CONTEXT * PMSAFD_RECV_APC_CONTEXT
HANDLE SockEvent
struct _MSAFD_SEND_APC_CONTEXT * PMSAFD_SEND_APC_CONTEXT
@ SocketOpen
Definition: msafd.h:46
#define SO_SYNCHRONOUS_NONALERT
Definition: ws2_32.h:41
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
if(dx< 0)
Definition: linetemp.h:194
int * LPINT
Definition: minwindef.h:151
_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
#define _In_
Definition: no_sal2.h:158
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
#define DWORD
Definition: nt_native.h:44
VOID(* PIO_APC_ROUTINE)(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved)
Definition: nt_native.h:880
@ SynchronizationEvent
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
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:205
#define STATUS_RECEIVE_PARTIAL
Definition: ntstatus.h:204
#define STATUS_RECEIVE_PARTIAL_EXPEDITED
Definition: ntstatus.h:206
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 memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
INT WSPAPI WSPSendDisconnect(IN SOCKET s, IN LPWSABUF lpOutboundDisconnectData, OUT LPINT lpErrno)
Definition: sndrcv.c:1064
static VOID NTAPI MsafdSendAPC(_In_ PVOID ApcContext, _In_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG Reserved)
Definition: sndrcv.c:200
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:430
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:843
static VOID NTAPI MsafdRecvAPC(_In_ PVOID ApcContext, _In_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG Reserved)
Definition: sndrcv.c:171
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:668
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:221
INT WSPAPI WSPRecvDisconnect(IN SOCKET s, OUT LPWSABUF lpInboundDisconnectData, OUT LPINT lpErrno)
Definition: sndrcv.c:1052
#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
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
Definition: msafd.h:154
LPWSAOVERLAPPED lpOverlapped
Definition: msafd.h:153
PSOCKET_INFORMATION lpSocket
Definition: msafd.h:155
LPWSAOVERLAPPED lpOverlapped
Definition: msafd.h:145
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
Definition: msafd.h:146
PSOCKET_INFORMATION lpSocket
Definition: msafd.h:147
PTRANSPORT_ADDRESS lpRemoteAddress
Definition: msafd.h:148
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:211
DWORD WINAPI SleepEx(IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:802
#define TDI_SEND_EXPEDITED
Definition: tdi.h:135
#define TDI_RECEIVE_PARTIAL
Definition: tdi.h:121
#define TDI_RECEIVE_EXPEDITED
Definition: tdi.h:123
struct _TRANSPORT_ADDRESS * PTRANSPORT_ADDRESS
#define TDI_RECEIVE_PEEK
Definition: tdi.h:124
#define TDI_RECEIVE_NORMAL
Definition: tdi.h:122
#define TDI_SEND_PARTIAL
Definition: tdi.h:136
#define STATUS_PENDING
Definition: telnetd.h:14
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
#define WSAEINVAL
Definition: winerror.h:2845
#define WSAENOTSOCK
Definition: winerror.h:2854
#define WSAEFAULT
Definition: winerror.h:2844
#define XP1_CONNECTIONLESS
Definition: winsock2.h:430
#define WSA_IO_PENDING
Definition: winsock2.h:610
#define WSA_IO_INCOMPLETE
Definition: winsock2.h:611
void(CALLBACK * LPWSAOVERLAPPED_COMPLETION_ROUTINE)(IN DWORD dwError, IN DWORD cbTransferred, IN LPWSAOVERLAPPED lpOverlapped, IN DWORD dwFlags)
Definition: winsock2.h:716
#define FD_READ
Definition: winsock.h:399
#define FD_WRITE
Definition: winsock.h:400
#define INVALID_SOCKET
Definition: winsock.h:326
UINT_PTR SOCKET
Definition: winsock.h:41
#define MSG_PEEK
Definition: winsock.h:216
#define SOCKET_ERROR
Definition: winsock.h:327
#define MSG_OOB
Definition: winsock.h:215
#define MSG_PARTIAL
Definition: winsock.h:396
#define FD_OOB
Definition: winsock.h:401
#define WSPAPI
Definition: ws2spi.h:39
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR RemoteAddress
Definition: wsk.h:172
unsigned char UCHAR
Definition: xmlstorage.h:181