ReactOS 0.4.15-dev-6068-g8061a6f
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 /* Wait for completion of not overlapped */
296 {
297 /* It's up to the protocol to time out recv. We must wait
298 * until the protocol decides it's had enough.
299 */
301 Status = IOSB->Status;
302 }
303
305
306 TRACE("Status %x Information %d\n", Status, IOSB->Information);
307
308 if (Status == STATUS_PENDING)
309 {
310 TRACE("Leaving (Pending)\n");
311 return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead);
312 }
313
314 /* Return the Flags */
315 *ReceiveFlags = 0;
316
317 switch (Status)
318 {
320 *ReceiveFlags = MSG_OOB;
321 break;
323 *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
324 break;
326 *ReceiveFlags = MSG_PARTIAL;
327 break;
328 }
329
330 /* Re-enable Async Event */
331 if (*ReceiveFlags & MSG_OOB)
332 {
334 }
335 else
336 {
338 }
339
340 if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
341 {
342 lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags);
343 HeapFree(GlobalHeap, 0, (PVOID)APCContext);
344 }
345
346 return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead );
347}
348
349int
350WSPAPI
352 LPWSABUF lpBuffers,
353 DWORD dwBufferCount,
354 LPDWORD lpNumberOfBytesRead,
355 LPDWORD ReceiveFlags,
356 struct sockaddr *SocketAddress,
357 int *SocketAddressLength,
359 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
360 LPWSATHREADID lpThreadId,
361 LPINT lpErrno )
362{
363 PIO_STATUS_BLOCK IOSB;
364 IO_STATUS_BLOCK DummyIOSB;
365 AFD_RECV_INFO_UDP RecvInfo;
367 PVOID APCContext;
368 PVOID APCFunction;
369 HANDLE Event = NULL;
371 PSOCKET_INFORMATION Socket;
372
373 /* Get the Socket Structure associate to this Socket*/
374 Socket = GetSocketStructure(Handle);
375 if (!Socket)
376 {
377 if (lpErrno)
378 *lpErrno = WSAENOTSOCK;
379 return SOCKET_ERROR;
380 }
381 if (!lpNumberOfBytesRead && !lpOverlapped)
382 {
383 if (lpErrno)
384 *lpErrno = WSAEFAULT;
385 return SOCKET_ERROR;
386 }
387 if (Socket->SharedData->OobInline && ReceiveFlags && (*ReceiveFlags & MSG_OOB) != 0)
388 {
389 if (lpErrno)
390 *lpErrno = WSAEINVAL;
391 return SOCKET_ERROR;
392 }
393
395 {
396 /* Call WSPRecv for a non-datagram socket */
397 return WSPRecv(Handle,
398 lpBuffers,
399 dwBufferCount,
400 lpNumberOfBytesRead,
401 ReceiveFlags,
403 lpCompletionRoutine,
404 lpThreadId,
405 lpErrno);
406 }
407
408 /* Bind us First */
409 if (Socket->SharedData->State == SocketOpen)
410 {
412 SocketAddress,
413 SocketAddressLength);
414 /* Bind it */
415 if (WSPBind(Handle, SocketAddress, *SocketAddressLength, lpErrno) == SOCKET_ERROR)
416 return SOCKET_ERROR;
417 }
418
421
422 if( !NT_SUCCESS(Status) )
423 return -1;
424
425 /* Set up the Receive Structure */
426 RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
427 RecvInfo.BufferCount = dwBufferCount;
428 RecvInfo.TdiFlags = 0;
429 RecvInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
430 RecvInfo.AddressLength = SocketAddressLength;
431 RecvInfo.Address = SocketAddress;
432
433 /* Set the TDI Flags */
434 if (*ReceiveFlags == 0)
435 {
436 RecvInfo.TdiFlags |= TDI_RECEIVE_NORMAL;
437 }
438 else
439 {
440 if (*ReceiveFlags & MSG_OOB)
441 {
443 }
444
445 if (*ReceiveFlags & MSG_PEEK)
446 {
447 RecvInfo.TdiFlags |= TDI_RECEIVE_PEEK;
448 }
449
450 if (*ReceiveFlags & MSG_PARTIAL)
451 {
452 RecvInfo.TdiFlags |= TDI_RECEIVE_PARTIAL;
453 }
454 }
455
456 /* Verify if we should use APC */
457
458 if (lpOverlapped == NULL)
459 {
460 /* Not using Overlapped structure, so use normal blocking on event */
461 APCContext = NULL;
462 APCFunction = NULL;
464 IOSB = &DummyIOSB;
465 }
466 else
467 {
468 /* Overlapped request for non overlapped opened socket */
469 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
470 {
471 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
472 return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesRead);
473 }
474 if (lpCompletionRoutine == NULL)
475 {
476 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
477 APCContext = lpOverlapped;
478 APCFunction = NULL;
479 Event = lpOverlapped->hEvent;
480 }
481 else
482 {
483 /* Using Overlapped Structure and a Completion Routine, so use an APC */
484 APCFunction = &AfdAPC; // should be a private io completion function inside us
485 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
486 if (!APCContext)
487 {
488 ERR("Not enough memory for APC Context\n");
489 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesRead);
490 }
491 ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
492 ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
493 ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
494 RecvInfo.AfdFlags |= AFD_SKIP_FIO;
495 }
496
497 IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
498 RecvInfo.AfdFlags |= AFD_OVERLAPPED;
499 }
500
501 IOSB->Status = STATUS_PENDING;
502
503 /* Send IOCTL */
505 Event,
506 APCFunction,
507 APCContext,
508 IOSB,
510 &RecvInfo,
511 sizeof(RecvInfo),
512 NULL,
513 0);
514
515 /* Wait for completion of not overlapped */
517 {
518 WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for receive...
519 Status = IOSB->Status;
520 }
521
523
524 if (Status == STATUS_PENDING)
525 {
526 TRACE("Leaving (Pending)\n");
527 return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesRead);
528 }
529
530 /* Return the Flags */
531 *ReceiveFlags = 0;
532
533 switch (Status)
534 {
536 *ReceiveFlags = MSG_OOB;
537 break;
539 *ReceiveFlags = MSG_PARTIAL | MSG_OOB;
540 break;
542 *ReceiveFlags = MSG_PARTIAL;
543 break;
544 }
545
546 /* Re-enable Async Event */
547 if (*ReceiveFlags & MSG_OOB)
548 {
550 }
551 else
552 {
554 }
555
556 if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
557 {
558 lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, *ReceiveFlags);
559 HeapFree(GlobalHeap, 0, (PVOID)APCContext);
560 }
561
562 return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead );
563}
564
565
566int
567WSPAPI
569 LPWSABUF lpBuffers,
570 DWORD dwBufferCount,
571 LPDWORD lpNumberOfBytesSent,
572 DWORD iFlags,
574 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
575 LPWSATHREADID lpThreadId,
576 LPINT lpErrno)
577{
578 PIO_STATUS_BLOCK IOSB;
579 IO_STATUS_BLOCK DummyIOSB;
580 AFD_SEND_INFO SendInfo;
582 PVOID APCContext;
583 PVOID APCFunction;
584 HANDLE Event = NULL;
586 PSOCKET_INFORMATION Socket;
587
588 /* Get the Socket Structure associate to this Socket*/
589 Socket = GetSocketStructure(Handle);
590 if (!Socket)
591 {
592 if (lpErrno)
593 *lpErrno = WSAENOTSOCK;
594 return SOCKET_ERROR;
595 }
596 if (!lpNumberOfBytesSent && !lpOverlapped)
597 {
598 if (lpErrno)
599 *lpErrno = WSAEFAULT;
600 return SOCKET_ERROR;
601 }
602
605
606 if( !NT_SUCCESS(Status) )
607 return -1;
608
609 TRACE("Called\n");
610
611 /* Set up the Send Structure */
612 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
613 SendInfo.BufferCount = dwBufferCount;
614 SendInfo.TdiFlags = 0;
615 SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
616
617 /* Set the TDI Flags */
618 if (iFlags)
619 {
620 if (iFlags & MSG_OOB)
621 {
622 SendInfo.TdiFlags |= TDI_SEND_EXPEDITED;
623 }
624 if (iFlags & MSG_PARTIAL)
625 {
626 SendInfo.TdiFlags |= TDI_SEND_PARTIAL;
627 }
628 }
629
630 /* Verify if we should use APC */
631 if (lpOverlapped == NULL)
632 {
633 /* Not using Overlapped structure, so use normal blocking on event */
634 APCContext = NULL;
635 APCFunction = NULL;
637 IOSB = &DummyIOSB;
638 }
639 else
640 {
641 /* Overlapped request for non overlapped opened socket */
642 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
643 {
644 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
645 return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent);
646 }
647 if (lpCompletionRoutine == NULL)
648 {
649 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
650 APCContext = lpOverlapped;
651 APCFunction = NULL;
652 Event = lpOverlapped->hEvent;
653 }
654 else
655 {
656 /* Using Overlapped Structure and a Completion Routine, so use an APC */
657 APCFunction = &AfdAPC; // should be a private io completion function inside us
658 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
659 if (!APCContext)
660 {
661 ERR("Not enough memory for APC Context\n");
662 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
663 }
664 ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
665 ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
666 ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
667 SendInfo.AfdFlags |= AFD_SKIP_FIO;
668 }
669
670 IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
671 SendInfo.AfdFlags |= AFD_OVERLAPPED;
672 }
673
674 IOSB->Status = STATUS_PENDING;
675
676 /* Send IOCTL */
678 Event,
679 APCFunction,
680 APCContext,
681 IOSB,
683 &SendInfo,
684 sizeof(SendInfo),
685 NULL,
686 0);
687
688 /* Wait for completion of not overlapped */
690 {
691 WaitForSingleObject(SockEvent, INFINITE); // BUGBUG, shouldn wait infinitely for send...
692 Status = IOSB->Status;
693 }
694
696
697 if (Status == STATUS_PENDING)
698 {
699 TRACE("Leaving (Pending)\n");
700 return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
701 }
702
703 /* Re-enable Async Event */
705
706 TRACE("Leaving (Success, %d)\n", IOSB->Information);
707
708 if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
709 {
710 lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0);
711 HeapFree(GlobalHeap, 0, (PVOID)APCContext);
712 }
713
714 return MsafdReturnWithErrno( Status, lpErrno, IOSB->Information, lpNumberOfBytesSent );
715}
716
717int
718WSPAPI
720 LPWSABUF lpBuffers,
721 DWORD dwBufferCount,
722 LPDWORD lpNumberOfBytesSent,
723 DWORD iFlags,
724 const struct sockaddr *SocketAddress,
725 int SocketAddressLength,
727 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
728 LPWSATHREADID lpThreadId,
729 LPINT lpErrno)
730{
731 PIO_STATUS_BLOCK IOSB;
732 IO_STATUS_BLOCK DummyIOSB;
733 AFD_SEND_INFO_UDP SendInfo;
735 PVOID APCContext;
736 PVOID APCFunction;
737 HANDLE Event = NULL;
739 PSOCKADDR BindAddress = NULL;
740 INT BindAddressLength;
742 PSOCKET_INFORMATION Socket;
743
744 /* Get the Socket Structure associate to this Socket */
745 Socket = GetSocketStructure(Handle);
746 if (!Socket)
747 {
748 if (lpErrno)
749 *lpErrno = WSAENOTSOCK;
750 return SOCKET_ERROR;
751 }
752 if (!lpNumberOfBytesSent && !lpOverlapped)
753 {
754 if (lpErrno)
755 *lpErrno = WSAEFAULT;
756 return SOCKET_ERROR;
757 }
758
760 {
761 /* Use WSPSend for connection-oriented sockets */
762 return WSPSend(Handle,
763 lpBuffers,
764 dwBufferCount,
765 lpNumberOfBytesSent,
766 iFlags,
768 lpCompletionRoutine,
769 lpThreadId,
770 lpErrno);
771 }
772
773 /* Bind us First */
774 if (Socket->SharedData->State == SocketOpen)
775 {
776 /* Get the Wildcard Address */
777 BindAddressLength = Socket->HelperData->MaxWSAddressLength;
778 BindAddress = HeapAlloc(GlobalHeap, 0, BindAddressLength);
779 if (!BindAddress)
780 {
782 return INVALID_SOCKET;
783 }
784
786 BindAddress,
787 &BindAddressLength);
788 /* Bind it */
789 if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR)
790 return SOCKET_ERROR;
791 }
792
793 RemoteAddress = HeapAlloc(GlobalHeap, 0, 0x6 + SocketAddressLength);
794 if (!RemoteAddress)
795 {
796 if (BindAddress != NULL)
797 {
798 HeapFree(GlobalHeap, 0, BindAddress);
799 }
801 }
802
806
807 if (!NT_SUCCESS(Status))
808 {
810 if (BindAddress != NULL)
811 {
812 HeapFree(GlobalHeap, 0, BindAddress);
813 }
814 return SOCKET_ERROR;
815 }
816
817 /* Set up Address in TDI Format */
818 RemoteAddress->TAAddressCount = 1;
819 RemoteAddress->Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
820 RtlCopyMemory(&RemoteAddress->Address[0].AddressType, SocketAddress, SocketAddressLength);
821
822 /* Set up Structure */
823 SendInfo.BufferArray = (PAFD_WSABUF)lpBuffers;
824 SendInfo.AfdFlags = Socket->SharedData->NonBlocking ? AFD_IMMEDIATE : 0;
825 SendInfo.BufferCount = dwBufferCount;
828
829 /* Verify if we should use APC */
830 if (lpOverlapped == NULL)
831 {
832 /* Not using Overlapped structure, so use normal blocking on event */
833 APCContext = NULL;
834 APCFunction = NULL;
836 IOSB = &DummyIOSB;
837 }
838 else
839 {
840 /* Overlapped request for non overlapped opened socket */
841 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
842 {
843 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
844 return MsafdReturnWithErrno(0, lpErrno, 0, lpNumberOfBytesSent);
845 }
846 if (lpCompletionRoutine == NULL)
847 {
848 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
849 APCContext = lpOverlapped;
850 APCFunction = NULL;
851 Event = lpOverlapped->hEvent;
852 }
853 else
854 {
855 /* Using Overlapped Structure and a Completion Routine, so use an APC */
856 APCFunction = &AfdAPC; // should be a private io completion function inside us
857 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
858 if (!APCContext)
859 {
860 ERR("Not enough memory for APC Context\n");
861 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, lpNumberOfBytesSent);
862 }
863 ((PAFDAPCCONTEXT)APCContext)->lpCompletionRoutine = lpCompletionRoutine;
864 ((PAFDAPCCONTEXT)APCContext)->lpOverlapped = lpOverlapped;
865 ((PAFDAPCCONTEXT)APCContext)->lpSocket = Socket;
866 SendInfo.AfdFlags |= AFD_SKIP_FIO;
867 }
868
869 IOSB = (PIO_STATUS_BLOCK)&lpOverlapped->Internal;
870 SendInfo.AfdFlags |= AFD_OVERLAPPED;
871 }
872
873 /* Send IOCTL */
875 Event,
876 APCFunction,
877 APCContext,
878 IOSB,
880 &SendInfo,
881 sizeof(SendInfo),
882 NULL,
883 0);
884
885 /* Wait for completion of not overlapped */
887 {
888 /* BUGBUG, shouldn't wait infinitely for send... */
890 Status = IOSB->Status;
891 }
892
895 if (BindAddress != NULL)
896 {
897 HeapFree(GlobalHeap, 0, BindAddress);
898 }
899
900 if (Status == STATUS_PENDING)
901 {
902 TRACE("Leaving (Pending)\n");
903 return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
904 }
905
907
908 if (Status == STATUS_SUCCESS && lpOverlapped && lpCompletionRoutine)
909 {
910 lpCompletionRoutine(Status, IOSB->Information, lpOverlapped, 0);
911 HeapFree(GlobalHeap, 0, (PVOID)APCContext);
912 }
913
914 return MsafdReturnWithErrno(Status, lpErrno, IOSB->Information, lpNumberOfBytesSent);
915}
916
917INT
918WSPAPI
920 OUT LPWSABUF lpInboundDisconnectData,
921 OUT LPINT lpErrno)
922{
924 return 0;
925}
926
927
928
929INT
930WSPAPI
932 IN LPWSABUF lpOutboundDisconnectData,
933 OUT LPINT lpErrno)
934{
936 return 0;
937}
938
939/* 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:3589
PSOCKET_INFORMATION GetSocketStructure(SOCKET Handle)
Definition: dllmain.c:3516
HANDLE GlobalHeap
Definition: dllmain.c:19
VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
Definition: dllmain.c:3958
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:3393
VOID SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket, IN ULONG Event)
Definition: dllmain.c:3992
BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
Definition: dllmain.c:3684
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:931
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:351
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:719
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:568
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:919
#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 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