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)
9 * CSH 01/09-2000 Created
10 * Alex 16/07/2004 - Complete Rewrite
17 WSPAsyncSelect(IN SOCKET Handle
,
23 PSOCKET_INFORMATION Socket
= NULL
;
24 PASYNC_DATA AsyncData
;
27 /* Get the Socket Structure associated to this Socket */
28 Socket
= GetSocketStructure(Handle
);
31 *lpErrno
= WSAENOTSOCK
;
35 /* Allocate the Async Data Structure to pass on to the Thread later */
36 AsyncData
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AsyncData
));
39 MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, NULL
);
40 return INVALID_SOCKET
;
43 /* Change the Socket to Non Blocking */
45 SetSocketInformation(Socket
, AFD_INFO_BLOCKING_MODE
, &BlockMode
, NULL
, NULL
, NULL
, NULL
);
46 Socket
->SharedData
->NonBlocking
= TRUE
;
48 /* Deactivate WSPEventSelect */
49 if (Socket
->SharedData
->AsyncEvents
)
51 if (WSPEventSelect(Handle
, NULL
, 0, lpErrno
) == SOCKET_ERROR
)
53 HeapFree(GetProcessHeap(), 0, AsyncData
);
58 /* Create the Asynch Thread if Needed */
59 SockCreateOrReferenceAsyncThread();
61 /* Open a Handle to AFD's Async Helper */
62 SockGetAsyncSelectHelperAfdHandle();
64 /* Store Socket Data */
65 Socket
->SharedData
->hWnd
= hWnd
;
66 Socket
->SharedData
->wMsg
= wMsg
;
67 Socket
->SharedData
->AsyncEvents
= lEvent
;
68 Socket
->SharedData
->AsyncDisabledEvents
= 0;
69 Socket
->SharedData
->SequenceNumber
++;
71 /* Return if there are no more Events */
72 if ((Socket
->SharedData
->AsyncEvents
& (~Socket
->SharedData
->AsyncDisabledEvents
)) == 0)
74 HeapFree(GetProcessHeap(), 0, AsyncData
);
78 /* Set up the Async Data */
79 AsyncData
->ParentSocket
= Socket
;
80 AsyncData
->SequenceNumber
= Socket
->SharedData
->SequenceNumber
;
82 /* Begin Async Select by using I/O Completion */
83 NtSetIoCompletion(SockAsyncCompletionPort
,
84 (PVOID
)&SockProcessQueuedAsyncSelect
,
96 WSPGetOverlappedResult(
98 IN LPWSAOVERLAPPED lpOverlapped
,
99 OUT LPDWORD lpdwBytes
,
101 OUT LPDWORD lpdwFlags
,
104 PSOCKET_INFORMATION Socket
;
107 TRACE("Called (%x)\n", Handle
);
109 /* Get the Socket Structure associate to this Socket*/
110 Socket
= GetSocketStructure(Handle
);
114 *lpErrno
= WSAENOTSOCK
;
117 if (!lpOverlapped
|| !lpdwBytes
|| !lpdwFlags
)
120 *lpErrno
= WSAEFAULT
;
123 Ret
= GetOverlappedResult((HANDLE
)Handle
, lpOverlapped
, lpdwBytes
, fWait
);
129 /* Re-enable Async Event */
130 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
131 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
132 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
140 AfdAPC(PVOID ApcContext
,
141 PIO_STATUS_BLOCK IoStatusBlock
,
144 PAFDAPCCONTEXT Context
= ApcContext
;
146 /* Re-enable Async Event */
147 SockReenableAsyncSelectEvent(Context
->lpSocket
, FD_OOB
);
148 SockReenableAsyncSelectEvent(Context
->lpSocket
, FD_READ
);
149 SockReenableAsyncSelectEvent(Context
->lpSocket
, FD_WRITE
);
151 Context
->lpCompletionRoutine(IoStatusBlock
->Status
, IoStatusBlock
->Information
, Context
->lpOverlapped
, 0);
152 HeapFree(GlobalHeap
, 0, ApcContext
);
157 WSPRecv(SOCKET Handle
,
160 LPDWORD lpNumberOfBytesRead
,
161 LPDWORD ReceiveFlags
,
162 LPWSAOVERLAPPED lpOverlapped
,
163 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
164 LPWSATHREADID lpThreadId
,
167 PIO_STATUS_BLOCK IOSB
;
168 IO_STATUS_BLOCK DummyIOSB
;
169 AFD_RECV_INFO RecvInfo
;
172 PIO_APC_ROUTINE APCFunction
;
175 PSOCKET_INFORMATION Socket
;
177 TRACE("Called (%x)\n", Handle
);
179 /* Get the Socket Structure associate to this Socket*/
180 Socket
= GetSocketStructure(Handle
);
184 *lpErrno
= WSAENOTSOCK
;
187 if (!lpNumberOfBytesRead
&& !lpOverlapped
)
190 *lpErrno
= WSAEFAULT
;
193 if (Socket
->SharedData
->OobInline
&& ReceiveFlags
&& (*ReceiveFlags
& MSG_OOB
) != 0)
196 *lpErrno
= WSAEINVAL
;
200 Status
= NtCreateEvent( &SockEvent
, EVENT_ALL_ACCESS
,
203 if( !NT_SUCCESS(Status
) )
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;
212 /* Set the TDI Flags */
213 if (*ReceiveFlags
== 0)
215 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
219 if (*ReceiveFlags
& MSG_OOB
)
221 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
224 if (*ReceiveFlags
& MSG_PEEK
)
226 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
229 if (*ReceiveFlags
& MSG_PARTIAL
)
231 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
235 /* Verify if we should use APC */
237 if (lpOverlapped
== NULL
)
239 /* Not using Overlapped structure, so use normal blocking on event */
247 /* Overlapped request for non overlapped opened socket */
248 if ((Socket
->SharedData
->CreateFlags
& SO_SYNCHRONOUS_NONALERT
) != 0)
250 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
251 return MsafdReturnWithErrno(0, lpErrno
, 0, lpNumberOfBytesRead
);
253 if (lpCompletionRoutine
== NULL
)
255 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
256 APCContext
= lpOverlapped
;
258 Event
= lpOverlapped
->hEvent
;
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
));
267 ERR("Not enough memory for APC Context\n");
268 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, lpNumberOfBytesRead
);
270 ((PAFDAPCCONTEXT
)APCContext
)->lpCompletionRoutine
= lpCompletionRoutine
;
271 ((PAFDAPCCONTEXT
)APCContext
)->lpOverlapped
= lpOverlapped
;
272 ((PAFDAPCCONTEXT
)APCContext
)->lpSocket
= Socket
;
273 RecvInfo
.AfdFlags
|= AFD_SKIP_FIO
;
276 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
277 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
280 IOSB
->Status
= STATUS_PENDING
;
283 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
294 /* Wait for completion of not overlapped */
295 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
297 /* It's up to the protocol to time out recv. We must wait
298 * until the protocol decides it's had enough.
300 WaitForSingleObject(SockEvent
, INFINITE
);
301 Status
= IOSB
->Status
;
304 NtClose( SockEvent
);
306 TRACE("Status %x Information %d\n", Status
, IOSB
->Information
);
308 if (Status
== STATUS_PENDING
)
310 TRACE("Leaving (Pending)\n");
311 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
314 /* Return the Flags */
319 case STATUS_RECEIVE_EXPEDITED
:
320 *ReceiveFlags
= MSG_OOB
;
322 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
323 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
325 case STATUS_RECEIVE_PARTIAL
:
326 *ReceiveFlags
= MSG_PARTIAL
;
330 /* Re-enable Async Event */
331 if (*ReceiveFlags
& MSG_OOB
)
333 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
337 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
340 if (Status
== STATUS_SUCCESS
&& lpOverlapped
&& lpCompletionRoutine
)
342 lpCompletionRoutine(Status
, IOSB
->Information
, lpOverlapped
, *ReceiveFlags
);
343 HeapFree(GlobalHeap
, 0, (PVOID
)APCContext
);
346 return MsafdReturnWithErrno ( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
351 WSPRecvFrom(SOCKET Handle
,
354 LPDWORD lpNumberOfBytesRead
,
355 LPDWORD ReceiveFlags
,
356 struct sockaddr
*SocketAddress
,
357 int *SocketAddressLength
,
358 LPWSAOVERLAPPED lpOverlapped
,
359 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
360 LPWSATHREADID lpThreadId
,
363 PIO_STATUS_BLOCK IOSB
;
364 IO_STATUS_BLOCK DummyIOSB
;
365 AFD_RECV_INFO_UDP RecvInfo
;
371 PSOCKET_INFORMATION Socket
;
373 /* Get the Socket Structure associate to this Socket*/
374 Socket
= GetSocketStructure(Handle
);
378 *lpErrno
= WSAENOTSOCK
;
381 if (!lpNumberOfBytesRead
&& !lpOverlapped
)
384 *lpErrno
= WSAEFAULT
;
387 if (Socket
->SharedData
->OobInline
&& ReceiveFlags
&& (*ReceiveFlags
& MSG_OOB
) != 0)
390 *lpErrno
= WSAEINVAL
;
394 if (!(Socket
->SharedData
->ServiceFlags1
& XP1_CONNECTIONLESS
))
396 /* Call WSPRecv for a non-datagram socket */
397 return WSPRecv(Handle
,
409 if (Socket
->SharedData
->State
== SocketOpen
)
411 Socket
->HelperData
->WSHGetWildcardSockaddr(Socket
->HelperContext
,
413 SocketAddressLength
);
415 if (WSPBind(Handle
, SocketAddress
, *SocketAddressLength
, lpErrno
) == SOCKET_ERROR
)
419 Status
= NtCreateEvent( &SockEvent
, EVENT_ALL_ACCESS
,
422 if( !NT_SUCCESS(Status
) )
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
;
433 /* Set the TDI Flags */
434 if (*ReceiveFlags
== 0)
436 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
440 if (*ReceiveFlags
& MSG_OOB
)
442 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
445 if (*ReceiveFlags
& MSG_PEEK
)
447 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
450 if (*ReceiveFlags
& MSG_PARTIAL
)
452 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
456 /* Verify if we should use APC */
458 if (lpOverlapped
== NULL
)
460 /* Not using Overlapped structure, so use normal blocking on event */
468 /* Overlapped request for non overlapped opened socket */
469 if ((Socket
->SharedData
->CreateFlags
& SO_SYNCHRONOUS_NONALERT
) != 0)
471 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
472 return MsafdReturnWithErrno(0, lpErrno
, 0, lpNumberOfBytesRead
);
474 if (lpCompletionRoutine
== NULL
)
476 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
477 APCContext
= lpOverlapped
;
479 Event
= lpOverlapped
->hEvent
;
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
));
488 ERR("Not enough memory for APC Context\n");
489 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, lpNumberOfBytesRead
);
491 ((PAFDAPCCONTEXT
)APCContext
)->lpCompletionRoutine
= lpCompletionRoutine
;
492 ((PAFDAPCCONTEXT
)APCContext
)->lpOverlapped
= lpOverlapped
;
493 ((PAFDAPCCONTEXT
)APCContext
)->lpSocket
= Socket
;
494 RecvInfo
.AfdFlags
|= AFD_SKIP_FIO
;
497 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
498 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
501 IOSB
->Status
= STATUS_PENDING
;
504 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
509 IOCTL_AFD_RECV_DATAGRAM
,
515 /* Wait for completion of not overlapped */
516 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
518 WaitForSingleObject(SockEvent
, INFINITE
); // BUGBUG, shouldn wait infinitely for receive...
519 Status
= IOSB
->Status
;
522 NtClose( SockEvent
);
524 if (Status
== STATUS_PENDING
)
526 TRACE("Leaving (Pending)\n");
527 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
530 /* Return the Flags */
535 case STATUS_RECEIVE_EXPEDITED
:
536 *ReceiveFlags
= MSG_OOB
;
538 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
539 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
541 case STATUS_RECEIVE_PARTIAL
:
542 *ReceiveFlags
= MSG_PARTIAL
;
546 /* Re-enable Async Event */
547 if (*ReceiveFlags
& MSG_OOB
)
549 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
553 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
556 if (Status
== STATUS_SUCCESS
&& lpOverlapped
&& lpCompletionRoutine
)
558 lpCompletionRoutine(Status
, IOSB
->Information
, lpOverlapped
, *ReceiveFlags
);
559 HeapFree(GlobalHeap
, 0, (PVOID
)APCContext
);
562 return MsafdReturnWithErrno ( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
568 WSPSend(SOCKET Handle
,
571 LPDWORD lpNumberOfBytesSent
,
573 LPWSAOVERLAPPED lpOverlapped
,
574 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
575 LPWSATHREADID lpThreadId
,
578 PIO_STATUS_BLOCK IOSB
;
579 IO_STATUS_BLOCK DummyIOSB
;
580 AFD_SEND_INFO SendInfo
;
586 PSOCKET_INFORMATION Socket
;
588 /* Get the Socket Structure associate to this Socket*/
589 Socket
= GetSocketStructure(Handle
);
593 *lpErrno
= WSAENOTSOCK
;
596 if (!lpNumberOfBytesSent
&& !lpOverlapped
)
599 *lpErrno
= WSAEFAULT
;
603 Status
= NtCreateEvent( &SockEvent
, EVENT_ALL_ACCESS
,
606 if( !NT_SUCCESS(Status
) )
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;
617 /* Set the TDI Flags */
620 if (iFlags
& MSG_OOB
)
622 SendInfo
.TdiFlags
|= TDI_SEND_EXPEDITED
;
624 if (iFlags
& MSG_PARTIAL
)
626 SendInfo
.TdiFlags
|= TDI_SEND_PARTIAL
;
630 /* Verify if we should use APC */
631 if (lpOverlapped
== NULL
)
633 /* Not using Overlapped structure, so use normal blocking on event */
641 /* Overlapped request for non overlapped opened socket */
642 if ((Socket
->SharedData
->CreateFlags
& SO_SYNCHRONOUS_NONALERT
) != 0)
644 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
645 return MsafdReturnWithErrno(0, lpErrno
, 0, lpNumberOfBytesSent
);
647 if (lpCompletionRoutine
== NULL
)
649 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
650 APCContext
= lpOverlapped
;
652 Event
= lpOverlapped
->hEvent
;
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
));
661 ERR("Not enough memory for APC Context\n");
662 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, lpNumberOfBytesSent
);
664 ((PAFDAPCCONTEXT
)APCContext
)->lpCompletionRoutine
= lpCompletionRoutine
;
665 ((PAFDAPCCONTEXT
)APCContext
)->lpOverlapped
= lpOverlapped
;
666 ((PAFDAPCCONTEXT
)APCContext
)->lpSocket
= Socket
;
667 SendInfo
.AfdFlags
|= AFD_SKIP_FIO
;
670 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
671 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
674 IOSB
->Status
= STATUS_PENDING
;
677 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
688 /* Wait for completion of not overlapped */
689 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
691 WaitForSingleObject(SockEvent
, INFINITE
); // BUGBUG, shouldn wait infinitely for send...
692 Status
= IOSB
->Status
;
695 NtClose( SockEvent
);
697 if (Status
== STATUS_PENDING
)
699 TRACE("Leaving (Pending)\n");
700 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
703 /* Re-enable Async Event */
704 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
706 TRACE("Leaving (Success, %d)\n", IOSB
->Information
);
708 if (Status
== STATUS_SUCCESS
&& lpOverlapped
&& lpCompletionRoutine
)
710 lpCompletionRoutine(Status
, IOSB
->Information
, lpOverlapped
, 0);
711 HeapFree(GlobalHeap
, 0, (PVOID
)APCContext
);
714 return MsafdReturnWithErrno( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
719 WSPSendTo(SOCKET Handle
,
722 LPDWORD lpNumberOfBytesSent
,
724 const struct sockaddr
*SocketAddress
,
725 int SocketAddressLength
,
726 LPWSAOVERLAPPED lpOverlapped
,
727 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
728 LPWSATHREADID lpThreadId
,
731 PIO_STATUS_BLOCK IOSB
;
732 IO_STATUS_BLOCK DummyIOSB
;
733 AFD_SEND_INFO_UDP SendInfo
;
738 PTRANSPORT_ADDRESS RemoteAddress
;
739 PSOCKADDR BindAddress
= NULL
;
740 INT BindAddressLength
;
742 PSOCKET_INFORMATION Socket
;
744 /* Get the Socket Structure associate to this Socket */
745 Socket
= GetSocketStructure(Handle
);
749 *lpErrno
= WSAENOTSOCK
;
752 if (!lpNumberOfBytesSent
&& !lpOverlapped
)
755 *lpErrno
= WSAEFAULT
;
759 if (!(Socket
->SharedData
->ServiceFlags1
& XP1_CONNECTIONLESS
))
761 /* Use WSPSend for connection-oriented sockets */
762 return WSPSend(Handle
,
774 if (Socket
->SharedData
->State
== SocketOpen
)
776 /* Get the Wildcard Address */
777 BindAddressLength
= Socket
->HelperData
->MaxWSAddressLength
;
778 BindAddress
= HeapAlloc(GlobalHeap
, 0, BindAddressLength
);
781 MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, NULL
);
782 return INVALID_SOCKET
;
785 Socket
->HelperData
->WSHGetWildcardSockaddr(Socket
->HelperContext
,
789 if (WSPBind(Handle
, BindAddress
, BindAddressLength
, lpErrno
) == SOCKET_ERROR
)
793 RemoteAddress
= HeapAlloc(GlobalHeap
, 0, 0x6 + SocketAddressLength
);
796 if (BindAddress
!= NULL
)
798 HeapFree(GlobalHeap
, 0, BindAddress
);
800 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, NULL
);
803 Status
= NtCreateEvent(&SockEvent
,
807 if (!NT_SUCCESS(Status
))
809 HeapFree(GlobalHeap
, 0, RemoteAddress
);
810 if (BindAddress
!= NULL
)
812 HeapFree(GlobalHeap
, 0, BindAddress
);
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
);
822 /* Set up Structure */
823 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
824 SendInfo
.AfdFlags
= Socket
->SharedData
->NonBlocking
? AFD_IMMEDIATE
: 0;
825 SendInfo
.BufferCount
= dwBufferCount
;
826 SendInfo
.TdiConnection
.RemoteAddress
= RemoteAddress
;
827 SendInfo
.TdiConnection
.RemoteAddressLength
= Socket
->HelperData
->MaxTDIAddressLength
;
829 /* Verify if we should use APC */
830 if (lpOverlapped
== NULL
)
832 /* Not using Overlapped structure, so use normal blocking on event */
840 /* Overlapped request for non overlapped opened socket */
841 if ((Socket
->SharedData
->CreateFlags
& SO_SYNCHRONOUS_NONALERT
) != 0)
843 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
844 return MsafdReturnWithErrno(0, lpErrno
, 0, lpNumberOfBytesSent
);
846 if (lpCompletionRoutine
== NULL
)
848 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
849 APCContext
= lpOverlapped
;
851 Event
= lpOverlapped
->hEvent
;
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
));
860 ERR("Not enough memory for APC Context\n");
861 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, lpNumberOfBytesSent
);
863 ((PAFDAPCCONTEXT
)APCContext
)->lpCompletionRoutine
= lpCompletionRoutine
;
864 ((PAFDAPCCONTEXT
)APCContext
)->lpOverlapped
= lpOverlapped
;
865 ((PAFDAPCCONTEXT
)APCContext
)->lpSocket
= Socket
;
866 SendInfo
.AfdFlags
|= AFD_SKIP_FIO
;
869 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
870 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
874 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
879 IOCTL_AFD_SEND_DATAGRAM
,
885 /* Wait for completion of not overlapped */
886 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
888 /* BUGBUG, shouldn't wait infinitely for send... */
889 WaitForSingleObject(SockEvent
, INFINITE
);
890 Status
= IOSB
->Status
;
894 HeapFree(GlobalHeap
, 0, RemoteAddress
);
895 if (BindAddress
!= NULL
)
897 HeapFree(GlobalHeap
, 0, BindAddress
);
900 if (Status
== STATUS_PENDING
)
902 TRACE("Leaving (Pending)\n");
903 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
906 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
908 if (Status
== STATUS_SUCCESS
&& lpOverlapped
&& lpCompletionRoutine
)
910 lpCompletionRoutine(Status
, IOSB
->Information
, lpOverlapped
, 0);
911 HeapFree(GlobalHeap
, 0, (PVOID
)APCContext
);
914 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
919 WSPRecvDisconnect(IN SOCKET s
,
920 OUT LPWSABUF lpInboundDisconnectData
,
931 WSPSendDisconnect(IN SOCKET s
,
932 IN LPWSABUF lpOutboundDisconnectData
,