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
15 #include <wine/debug.h>
16 WINE_DEFAULT_DEBUG_CHANNEL(msafd
);
20 WSPAsyncSelect(IN SOCKET Handle
,
26 PSOCKET_INFORMATION Socket
= NULL
;
27 PASYNC_DATA AsyncData
;
30 /* Get the Socket Structure associated to this Socket */
31 Socket
= GetSocketStructure(Handle
);
34 *lpErrno
= WSAENOTSOCK
;
38 /* Allocate the Async Data Structure to pass on to the Thread later */
39 AsyncData
= HeapAlloc(GetProcessHeap(), 0, sizeof(*AsyncData
));
42 MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, NULL
);
43 return INVALID_SOCKET
;
46 /* Change the Socket to Non Blocking */
48 SetSocketInformation(Socket
, AFD_INFO_BLOCKING_MODE
, &BlockMode
, NULL
, NULL
, NULL
, NULL
);
49 Socket
->SharedData
->NonBlocking
= TRUE
;
51 /* Deactivate WSPEventSelect */
52 if (Socket
->SharedData
->AsyncEvents
)
54 if (WSPEventSelect(Handle
, NULL
, 0, lpErrno
) == SOCKET_ERROR
)
56 HeapFree(GetProcessHeap(), 0, AsyncData
);
61 /* Create the Asynch Thread if Needed */
62 SockCreateOrReferenceAsyncThread();
64 /* Open a Handle to AFD's Async Helper */
65 SockGetAsyncSelectHelperAfdHandle();
67 /* Store Socket Data */
68 Socket
->SharedData
->hWnd
= hWnd
;
69 Socket
->SharedData
->wMsg
= wMsg
;
70 Socket
->SharedData
->AsyncEvents
= lEvent
;
71 Socket
->SharedData
->AsyncDisabledEvents
= 0;
72 Socket
->SharedData
->SequenceNumber
++;
74 /* Return if there are no more Events */
75 if ((Socket
->SharedData
->AsyncEvents
& (~Socket
->SharedData
->AsyncDisabledEvents
)) == 0)
77 HeapFree(GetProcessHeap(), 0, AsyncData
);
81 /* Set up the Async Data */
82 AsyncData
->ParentSocket
= Socket
;
83 AsyncData
->SequenceNumber
= Socket
->SharedData
->SequenceNumber
;
85 /* Begin Async Select by using I/O Completion */
86 NtSetIoCompletion(SockAsyncCompletionPort
,
87 (PVOID
)&SockProcessQueuedAsyncSelect
,
99 WSPGetOverlappedResult(
101 IN LPWSAOVERLAPPED lpOverlapped
,
102 OUT LPDWORD lpdwBytes
,
104 OUT LPDWORD lpdwFlags
,
107 PSOCKET_INFORMATION Socket
;
110 TRACE("Called (%x)\n", Handle
);
112 /* Get the Socket Structure associate to this Socket*/
113 Socket
= GetSocketStructure(Handle
);
117 *lpErrno
= WSAENOTSOCK
;
120 if (!lpOverlapped
|| !lpdwBytes
|| !lpdwFlags
)
123 *lpErrno
= WSAEFAULT
;
126 Ret
= GetOverlappedResult((HANDLE
)Handle
, lpOverlapped
, lpdwBytes
, fWait
);
132 /* Re-enable Async Event */
133 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
134 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
135 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
143 AfdAPC(PVOID ApcContext
,
144 PIO_STATUS_BLOCK IoStatusBlock
,
147 PAFDAPCCONTEXT Context
= ApcContext
;
149 /* Re-enable Async Event */
150 SockReenableAsyncSelectEvent(Context
->lpSocket
, FD_OOB
);
151 SockReenableAsyncSelectEvent(Context
->lpSocket
, FD_READ
);
152 SockReenableAsyncSelectEvent(Context
->lpSocket
, FD_WRITE
);
154 Context
->lpCompletionRoutine(IoStatusBlock
->Status
, IoStatusBlock
->Information
, Context
->lpOverlapped
, 0);
155 HeapFree(GlobalHeap
, 0, ApcContext
);
160 WSPRecv(SOCKET Handle
,
163 LPDWORD lpNumberOfBytesRead
,
164 LPDWORD ReceiveFlags
,
165 LPWSAOVERLAPPED lpOverlapped
,
166 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
167 LPWSATHREADID lpThreadId
,
170 PIO_STATUS_BLOCK IOSB
;
171 IO_STATUS_BLOCK DummyIOSB
;
172 AFD_RECV_INFO RecvInfo
;
175 PIO_APC_ROUTINE APCFunction
;
178 PSOCKET_INFORMATION Socket
;
180 TRACE("Called (%x)\n", Handle
);
182 /* Get the Socket Structure associate to this Socket*/
183 Socket
= GetSocketStructure(Handle
);
187 *lpErrno
= WSAENOTSOCK
;
190 if (!lpNumberOfBytesRead
&& !lpOverlapped
)
193 *lpErrno
= WSAEFAULT
;
196 if (Socket
->SharedData
->OobInline
&& ReceiveFlags
&& (*ReceiveFlags
& MSG_OOB
) != 0)
199 *lpErrno
= WSAEINVAL
;
203 Status
= NtCreateEvent( &SockEvent
, EVENT_ALL_ACCESS
,
206 if( !NT_SUCCESS(Status
) )
209 /* Set up the Receive Structure */
210 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
211 RecvInfo
.BufferCount
= dwBufferCount
;
212 RecvInfo
.TdiFlags
= 0;
213 RecvInfo
.AfdFlags
= Socket
->SharedData
->NonBlocking
? AFD_IMMEDIATE
: 0;
215 /* Set the TDI Flags */
216 if (*ReceiveFlags
== 0)
218 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
222 if (*ReceiveFlags
& MSG_OOB
)
224 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
227 if (*ReceiveFlags
& MSG_PEEK
)
229 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
232 if (*ReceiveFlags
& MSG_PARTIAL
)
234 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
238 /* Verify if we should use APC */
240 if (lpOverlapped
== NULL
)
242 /* Not using Overlapped structure, so use normal blocking on event */
250 /* Overlapped request for non overlapped opened socket */
251 if ((Socket
->SharedData
->CreateFlags
& SO_SYNCHRONOUS_NONALERT
) != 0)
253 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
254 return MsafdReturnWithErrno(0, lpErrno
, 0, lpNumberOfBytesRead
);
256 if (lpCompletionRoutine
== NULL
)
258 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
259 APCContext
= lpOverlapped
;
261 Event
= lpOverlapped
->hEvent
;
265 /* Using Overlapped Structure and a Completion Routine, so use an APC */
266 APCFunction
= &AfdAPC
; // should be a private io completion function inside us
267 APCContext
= HeapAlloc(GlobalHeap
, 0, sizeof(AFDAPCCONTEXT
));
270 ERR("Not enough memory for APC Context\n");
271 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, lpNumberOfBytesRead
);
273 ((PAFDAPCCONTEXT
)APCContext
)->lpCompletionRoutine
= lpCompletionRoutine
;
274 ((PAFDAPCCONTEXT
)APCContext
)->lpOverlapped
= lpOverlapped
;
275 ((PAFDAPCCONTEXT
)APCContext
)->lpSocket
= Socket
;
276 RecvInfo
.AfdFlags
|= AFD_SKIP_FIO
;
279 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
280 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
283 IOSB
->Status
= STATUS_PENDING
;
286 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
297 /* Wait for completion of not overlapped */
298 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
300 /* It's up to the protocol to time out recv. We must wait
301 * until the protocol decides it's had enough.
303 WaitForSingleObject(SockEvent
, INFINITE
);
304 Status
= IOSB
->Status
;
307 NtClose( SockEvent
);
309 TRACE("Status %x Information %d\n", Status
, IOSB
->Information
);
311 if (Status
== STATUS_PENDING
)
313 TRACE("Leaving (Pending)\n");
314 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
317 /* Return the Flags */
322 case STATUS_RECEIVE_EXPEDITED
:
323 *ReceiveFlags
= MSG_OOB
;
325 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
326 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
328 case STATUS_RECEIVE_PARTIAL
:
329 *ReceiveFlags
= MSG_PARTIAL
;
333 /* Re-enable Async Event */
334 if (*ReceiveFlags
& MSG_OOB
)
336 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
340 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
343 if (Status
== STATUS_SUCCESS
&& lpOverlapped
&& lpCompletionRoutine
)
345 lpCompletionRoutine(Status
, IOSB
->Information
, lpOverlapped
, *ReceiveFlags
);
346 HeapFree(GlobalHeap
, 0, (PVOID
)APCContext
);
349 return MsafdReturnWithErrno ( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
354 WSPRecvFrom(SOCKET Handle
,
357 LPDWORD lpNumberOfBytesRead
,
358 LPDWORD ReceiveFlags
,
359 struct sockaddr
*SocketAddress
,
360 int *SocketAddressLength
,
361 LPWSAOVERLAPPED lpOverlapped
,
362 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
363 LPWSATHREADID lpThreadId
,
366 PIO_STATUS_BLOCK IOSB
;
367 IO_STATUS_BLOCK DummyIOSB
;
368 AFD_RECV_INFO_UDP RecvInfo
;
374 PSOCKET_INFORMATION Socket
;
376 /* Get the Socket Structure associate to this Socket*/
377 Socket
= GetSocketStructure(Handle
);
381 *lpErrno
= WSAENOTSOCK
;
384 if (!lpNumberOfBytesRead
&& !lpOverlapped
)
387 *lpErrno
= WSAEFAULT
;
390 if (Socket
->SharedData
->OobInline
&& ReceiveFlags
&& (*ReceiveFlags
& MSG_OOB
) != 0)
393 *lpErrno
= WSAEINVAL
;
397 if (!(Socket
->SharedData
->ServiceFlags1
& XP1_CONNECTIONLESS
))
399 /* Call WSPRecv for a non-datagram socket */
400 return WSPRecv(Handle
,
412 if (Socket
->SharedData
->State
== SocketOpen
)
414 Socket
->HelperData
->WSHGetWildcardSockaddr(Socket
->HelperContext
,
416 SocketAddressLength
);
418 if (WSPBind(Handle
, SocketAddress
, *SocketAddressLength
, lpErrno
) == SOCKET_ERROR
)
422 Status
= NtCreateEvent( &SockEvent
, EVENT_ALL_ACCESS
,
425 if( !NT_SUCCESS(Status
) )
428 /* Set up the Receive Structure */
429 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
430 RecvInfo
.BufferCount
= dwBufferCount
;
431 RecvInfo
.TdiFlags
= 0;
432 RecvInfo
.AfdFlags
= Socket
->SharedData
->NonBlocking
? AFD_IMMEDIATE
: 0;
433 RecvInfo
.AddressLength
= SocketAddressLength
;
434 RecvInfo
.Address
= SocketAddress
;
436 /* Set the TDI Flags */
437 if (*ReceiveFlags
== 0)
439 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
443 if (*ReceiveFlags
& MSG_OOB
)
445 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
448 if (*ReceiveFlags
& MSG_PEEK
)
450 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
453 if (*ReceiveFlags
& MSG_PARTIAL
)
455 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
459 /* Verify if we should use APC */
461 if (lpOverlapped
== NULL
)
463 /* Not using Overlapped structure, so use normal blocking on event */
471 /* Overlapped request for non overlapped opened socket */
472 if ((Socket
->SharedData
->CreateFlags
& SO_SYNCHRONOUS_NONALERT
) != 0)
474 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
475 return MsafdReturnWithErrno(0, lpErrno
, 0, lpNumberOfBytesRead
);
477 if (lpCompletionRoutine
== NULL
)
479 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
480 APCContext
= lpOverlapped
;
482 Event
= lpOverlapped
->hEvent
;
486 /* Using Overlapped Structure and a Completion Routine, so use an APC */
487 APCFunction
= &AfdAPC
; // should be a private io completion function inside us
488 APCContext
= HeapAlloc(GlobalHeap
, 0, sizeof(AFDAPCCONTEXT
));
491 ERR("Not enough memory for APC Context\n");
492 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, lpNumberOfBytesRead
);
494 ((PAFDAPCCONTEXT
)APCContext
)->lpCompletionRoutine
= lpCompletionRoutine
;
495 ((PAFDAPCCONTEXT
)APCContext
)->lpOverlapped
= lpOverlapped
;
496 ((PAFDAPCCONTEXT
)APCContext
)->lpSocket
= Socket
;
497 RecvInfo
.AfdFlags
|= AFD_SKIP_FIO
;
500 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
501 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
504 IOSB
->Status
= STATUS_PENDING
;
507 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
512 IOCTL_AFD_RECV_DATAGRAM
,
518 /* Wait for completion of not overlapped */
519 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
521 WaitForSingleObject(SockEvent
, INFINITE
); // BUGBUG, shouldn wait infinitely for receive...
522 Status
= IOSB
->Status
;
525 NtClose( SockEvent
);
527 if (Status
== STATUS_PENDING
)
529 TRACE("Leaving (Pending)\n");
530 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
533 /* Return the Flags */
538 case STATUS_RECEIVE_EXPEDITED
:
539 *ReceiveFlags
= MSG_OOB
;
541 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
542 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
544 case STATUS_RECEIVE_PARTIAL
:
545 *ReceiveFlags
= MSG_PARTIAL
;
549 /* Re-enable Async Event */
550 if (*ReceiveFlags
& MSG_OOB
)
552 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
556 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
559 if (Status
== STATUS_SUCCESS
&& lpOverlapped
&& lpCompletionRoutine
)
561 lpCompletionRoutine(Status
, IOSB
->Information
, lpOverlapped
, *ReceiveFlags
);
562 HeapFree(GlobalHeap
, 0, (PVOID
)APCContext
);
565 return MsafdReturnWithErrno ( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
571 WSPSend(SOCKET Handle
,
574 LPDWORD lpNumberOfBytesSent
,
576 LPWSAOVERLAPPED lpOverlapped
,
577 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
578 LPWSATHREADID lpThreadId
,
581 PIO_STATUS_BLOCK IOSB
;
582 IO_STATUS_BLOCK DummyIOSB
;
583 AFD_SEND_INFO SendInfo
;
589 PSOCKET_INFORMATION Socket
;
591 /* Get the Socket Structure associate to this Socket*/
592 Socket
= GetSocketStructure(Handle
);
596 *lpErrno
= WSAENOTSOCK
;
599 if (!lpNumberOfBytesSent
&& !lpOverlapped
)
602 *lpErrno
= WSAEFAULT
;
606 Status
= NtCreateEvent( &SockEvent
, EVENT_ALL_ACCESS
,
609 if( !NT_SUCCESS(Status
) )
614 /* Set up the Send Structure */
615 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
616 SendInfo
.BufferCount
= dwBufferCount
;
617 SendInfo
.TdiFlags
= 0;
618 SendInfo
.AfdFlags
= Socket
->SharedData
->NonBlocking
? AFD_IMMEDIATE
: 0;
620 /* Set the TDI Flags */
623 if (iFlags
& MSG_OOB
)
625 SendInfo
.TdiFlags
|= TDI_SEND_EXPEDITED
;
627 if (iFlags
& MSG_PARTIAL
)
629 SendInfo
.TdiFlags
|= TDI_SEND_PARTIAL
;
633 /* Verify if we should use APC */
634 if (lpOverlapped
== NULL
)
636 /* Not using Overlapped structure, so use normal blocking on event */
644 /* Overlapped request for non overlapped opened socket */
645 if ((Socket
->SharedData
->CreateFlags
& SO_SYNCHRONOUS_NONALERT
) != 0)
647 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
648 return MsafdReturnWithErrno(0, lpErrno
, 0, lpNumberOfBytesSent
);
650 if (lpCompletionRoutine
== NULL
)
652 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
653 APCContext
= lpOverlapped
;
655 Event
= lpOverlapped
->hEvent
;
659 /* Using Overlapped Structure and a Completion Routine, so use an APC */
660 APCFunction
= &AfdAPC
; // should be a private io completion function inside us
661 APCContext
= HeapAlloc(GlobalHeap
, 0, sizeof(AFDAPCCONTEXT
));
664 ERR("Not enough memory for APC Context\n");
665 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, lpNumberOfBytesSent
);
667 ((PAFDAPCCONTEXT
)APCContext
)->lpCompletionRoutine
= lpCompletionRoutine
;
668 ((PAFDAPCCONTEXT
)APCContext
)->lpOverlapped
= lpOverlapped
;
669 ((PAFDAPCCONTEXT
)APCContext
)->lpSocket
= Socket
;
670 SendInfo
.AfdFlags
|= AFD_SKIP_FIO
;
673 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
674 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
677 IOSB
->Status
= STATUS_PENDING
;
680 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
691 /* Wait for completion of not overlapped */
692 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
694 WaitForSingleObject(SockEvent
, INFINITE
); // BUGBUG, shouldn wait infinitely for send...
695 Status
= IOSB
->Status
;
698 NtClose( SockEvent
);
700 if (Status
== STATUS_PENDING
)
702 TRACE("Leaving (Pending)\n");
703 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
706 /* Re-enable Async Event */
707 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
709 TRACE("Leaving (Success, %d)\n", IOSB
->Information
);
711 if (Status
== STATUS_SUCCESS
&& lpOverlapped
&& lpCompletionRoutine
)
713 lpCompletionRoutine(Status
, IOSB
->Information
, lpOverlapped
, 0);
714 HeapFree(GlobalHeap
, 0, (PVOID
)APCContext
);
717 return MsafdReturnWithErrno( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
722 WSPSendTo(SOCKET Handle
,
725 LPDWORD lpNumberOfBytesSent
,
727 const struct sockaddr
*SocketAddress
,
728 int SocketAddressLength
,
729 LPWSAOVERLAPPED lpOverlapped
,
730 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
731 LPWSATHREADID lpThreadId
,
734 PIO_STATUS_BLOCK IOSB
;
735 IO_STATUS_BLOCK DummyIOSB
;
736 AFD_SEND_INFO_UDP SendInfo
;
741 PTRANSPORT_ADDRESS RemoteAddress
;
742 PSOCKADDR BindAddress
= NULL
;
743 INT BindAddressLength
;
745 PSOCKET_INFORMATION Socket
;
747 /* Get the Socket Structure associate to this Socket */
748 Socket
= GetSocketStructure(Handle
);
752 *lpErrno
= WSAENOTSOCK
;
755 if (!lpNumberOfBytesSent
&& !lpOverlapped
)
758 *lpErrno
= WSAEFAULT
;
762 if (!(Socket
->SharedData
->ServiceFlags1
& XP1_CONNECTIONLESS
))
764 /* Use WSPSend for connection-oriented sockets */
765 return WSPSend(Handle
,
777 if (Socket
->SharedData
->State
== SocketOpen
)
779 /* Get the Wildcard Address */
780 BindAddressLength
= Socket
->HelperData
->MaxWSAddressLength
;
781 BindAddress
= HeapAlloc(GlobalHeap
, 0, BindAddressLength
);
784 MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, NULL
);
785 return INVALID_SOCKET
;
788 Socket
->HelperData
->WSHGetWildcardSockaddr(Socket
->HelperContext
,
792 if (WSPBind(Handle
, BindAddress
, BindAddressLength
, lpErrno
) == SOCKET_ERROR
)
796 RemoteAddress
= HeapAlloc(GlobalHeap
, 0, 0x6 + SocketAddressLength
);
799 if (BindAddress
!= NULL
)
801 HeapFree(GlobalHeap
, 0, BindAddress
);
803 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, NULL
);
806 Status
= NtCreateEvent(&SockEvent
,
810 if (!NT_SUCCESS(Status
))
812 HeapFree(GlobalHeap
, 0, RemoteAddress
);
813 if (BindAddress
!= NULL
)
815 HeapFree(GlobalHeap
, 0, BindAddress
);
820 /* Set up Address in TDI Format */
821 RemoteAddress
->TAAddressCount
= 1;
822 RemoteAddress
->Address
[0].AddressLength
= SocketAddressLength
- sizeof(SocketAddress
->sa_family
);
823 RtlCopyMemory(&RemoteAddress
->Address
[0].AddressType
, SocketAddress
, SocketAddressLength
);
825 /* Set up Structure */
826 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
827 SendInfo
.AfdFlags
= Socket
->SharedData
->NonBlocking
? AFD_IMMEDIATE
: 0;
828 SendInfo
.BufferCount
= dwBufferCount
;
829 SendInfo
.TdiConnection
.RemoteAddress
= RemoteAddress
;
830 SendInfo
.TdiConnection
.RemoteAddressLength
= Socket
->HelperData
->MaxTDIAddressLength
;
832 /* Verify if we should use APC */
833 if (lpOverlapped
== NULL
)
835 /* Not using Overlapped structure, so use normal blocking on event */
843 /* Overlapped request for non overlapped opened socket */
844 if ((Socket
->SharedData
->CreateFlags
& SO_SYNCHRONOUS_NONALERT
) != 0)
846 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
847 return MsafdReturnWithErrno(0, lpErrno
, 0, lpNumberOfBytesSent
);
849 if (lpCompletionRoutine
== NULL
)
851 /* Using Overlapped Structure, but no Completion Routine, so no need for APC */
852 APCContext
= lpOverlapped
;
854 Event
= lpOverlapped
->hEvent
;
858 /* Using Overlapped Structure and a Completion Routine, so use an APC */
859 APCFunction
= &AfdAPC
; // should be a private io completion function inside us
860 APCContext
= HeapAlloc(GlobalHeap
, 0, sizeof(AFDAPCCONTEXT
));
863 ERR("Not enough memory for APC Context\n");
864 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, lpNumberOfBytesSent
);
866 ((PAFDAPCCONTEXT
)APCContext
)->lpCompletionRoutine
= lpCompletionRoutine
;
867 ((PAFDAPCCONTEXT
)APCContext
)->lpOverlapped
= lpOverlapped
;
868 ((PAFDAPCCONTEXT
)APCContext
)->lpSocket
= Socket
;
869 SendInfo
.AfdFlags
|= AFD_SKIP_FIO
;
872 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
873 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
877 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
882 IOCTL_AFD_SEND_DATAGRAM
,
888 /* Wait for completion of not overlapped */
889 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
891 /* BUGBUG, shouldn't wait infinitely for send... */
892 WaitForSingleObject(SockEvent
, INFINITE
);
893 Status
= IOSB
->Status
;
897 HeapFree(GlobalHeap
, 0, RemoteAddress
);
898 if (BindAddress
!= NULL
)
900 HeapFree(GlobalHeap
, 0, BindAddress
);
903 if (Status
== STATUS_PENDING
)
905 TRACE("Leaving (Pending)\n");
906 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
909 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
911 if (Status
== STATUS_SUCCESS
&& lpOverlapped
&& lpCompletionRoutine
)
913 lpCompletionRoutine(Status
, IOSB
->Information
, lpOverlapped
, 0);
914 HeapFree(GlobalHeap
, 0, (PVOID
)APCContext
);
917 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
922 WSPRecvDisconnect(IN SOCKET s
,
923 OUT LPWSABUF lpInboundDisconnectData
,
934 WSPSendDisconnect(IN SOCKET s
,
935 IN LPWSABUF lpOutboundDisconnectData
,