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
);
49 Socket
->SharedData
->NonBlocking
= TRUE
;
51 /* Deactive 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 PIO_STATUS_BLOCK IOSB
;
109 PSOCKET_INFORMATION Socket
;
111 TRACE("Called (%x)\n", Handle
);
113 /* Get the Socket Structure associate to this Socket*/
114 Socket
= GetSocketStructure(Handle
);
118 *lpErrno
= WSAENOTSOCK
;
121 if (!lpOverlapped
|| !lpdwBytes
|| !lpdwFlags
)
124 *lpErrno
= WSAEFAULT
;
127 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
131 *lpErrno
= WSAEFAULT
;
134 Status
= IOSB
->Status
;
136 /* Wait for completition of overlapped */
137 if (Status
== STATUS_PENDING
)
139 /* It's up to the protocol to time out recv. We must wait
140 * until the protocol decides it's had enough.
144 WaitForSingleObject(lpOverlapped
->hEvent
, INFINITE
);
145 Status
= IOSB
->Status
;
149 TRACE("Status %x Information %d\n", Status
, IOSB
->Information
);
151 if (Status
!= STATUS_PENDING
)
155 *lpdwBytes
= IOSB
->Information
;
157 /* Re-enable Async Event */
158 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
159 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
160 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
163 return Status
== STATUS_SUCCESS
;
168 AfdAPC(PVOID ApcContext
,
169 PIO_STATUS_BLOCK IoStatusBlock
,
172 PAFDAPCCONTEXT Context
= ApcContext
;
174 /* Re-enable Async Event */
175 SockReenableAsyncSelectEvent(Context
->lpSocket
, FD_OOB
);
176 SockReenableAsyncSelectEvent(Context
->lpSocket
, FD_READ
);
177 SockReenableAsyncSelectEvent(Context
->lpSocket
, FD_WRITE
);
179 Context
->lpCompletionRoutine(IoStatusBlock
->Status
, IoStatusBlock
->Information
, Context
->lpOverlapped
, 0);
180 HeapFree(GlobalHeap
, 0, ApcContext
);
185 WSPRecv(SOCKET Handle
,
188 LPDWORD lpNumberOfBytesRead
,
189 LPDWORD ReceiveFlags
,
190 LPWSAOVERLAPPED lpOverlapped
,
191 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
192 LPWSATHREADID lpThreadId
,
195 PIO_STATUS_BLOCK IOSB
;
196 IO_STATUS_BLOCK DummyIOSB
;
197 AFD_RECV_INFO RecvInfo
;
200 PIO_APC_ROUTINE APCFunction
;
203 PSOCKET_INFORMATION Socket
;
205 TRACE("Called (%x)\n", Handle
);
207 /* Get the Socket Structure associate to this Socket*/
208 Socket
= GetSocketStructure(Handle
);
212 *lpErrno
= WSAENOTSOCK
;
215 if (!lpNumberOfBytesRead
&& !lpOverlapped
)
218 *lpErrno
= WSAEFAULT
;
222 Status
= NtCreateEvent( &SockEvent
, EVENT_ALL_ACCESS
,
225 if( !NT_SUCCESS(Status
) )
228 /* Set up the Receive Structure */
229 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
230 RecvInfo
.BufferCount
= dwBufferCount
;
231 RecvInfo
.TdiFlags
= 0;
232 RecvInfo
.AfdFlags
= Socket
->SharedData
->NonBlocking
? AFD_IMMEDIATE
: 0;
234 /* Set the TDI Flags */
235 if (*ReceiveFlags
== 0)
237 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
241 if (*ReceiveFlags
& MSG_OOB
)
243 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
246 if (*ReceiveFlags
& MSG_PEEK
)
248 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
251 if (*ReceiveFlags
& MSG_PARTIAL
)
253 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
257 /* Verifiy if we should use APC */
259 if (lpOverlapped
== NULL
)
261 /* Not using Overlapped structure, so use normal blocking on event */
269 /* Overlapped request for non overlapped opened socket */
270 if ((Socket
->SharedData
->CreateFlags
& SO_SYNCHRONOUS_NONALERT
) != 0)
272 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
273 return MsafdReturnWithErrno(0, lpErrno
, 0, lpNumberOfBytesRead
);
275 if (lpCompletionRoutine
== NULL
)
277 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
278 APCContext
= lpOverlapped
;
280 Event
= lpOverlapped
->hEvent
;
284 /* Using Overlapped Structure and a Completition Routine, so use an APC */
285 APCFunction
= &AfdAPC
; // should be a private io completition function inside us
286 APCContext
= HeapAlloc(GlobalHeap
, 0, sizeof(AFDAPCCONTEXT
));
289 ERR("Not enough memory for APC Context\n");
290 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, lpNumberOfBytesRead
);
292 ((PAFDAPCCONTEXT
)APCContext
)->lpCompletionRoutine
= lpCompletionRoutine
;
293 ((PAFDAPCCONTEXT
)APCContext
)->lpOverlapped
= lpOverlapped
;
294 ((PAFDAPCCONTEXT
)APCContext
)->lpSocket
= Socket
;
295 RecvInfo
.AfdFlags
|= AFD_SKIP_FIO
;
298 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
299 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
302 IOSB
->Status
= STATUS_PENDING
;
305 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
316 /* Wait for completition of not overlapped */
317 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
319 /* It's up to the protocol to time out recv. We must wait
320 * until the protocol decides it's had enough.
322 WaitForSingleObject(SockEvent
, INFINITE
);
323 Status
= IOSB
->Status
;
326 NtClose( SockEvent
);
328 TRACE("Status %x Information %d\n", Status
, IOSB
->Information
);
330 if (Status
== STATUS_PENDING
)
332 TRACE("Leaving (Pending)\n");
333 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
336 /* Return the Flags */
341 case STATUS_RECEIVE_EXPEDITED
:
342 *ReceiveFlags
= MSG_OOB
;
344 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
345 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
347 case STATUS_RECEIVE_PARTIAL
:
348 *ReceiveFlags
= MSG_PARTIAL
;
352 /* Re-enable Async Event */
353 if (*ReceiveFlags
& MSG_OOB
)
355 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
359 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
362 if (Status
== STATUS_SUCCESS
&& lpOverlapped
&& lpCompletionRoutine
)
364 lpCompletionRoutine(Status
, IOSB
->Information
, lpOverlapped
, *ReceiveFlags
);
365 HeapFree(GlobalHeap
, 0, (PVOID
)APCContext
);
368 return MsafdReturnWithErrno ( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
373 WSPRecvFrom(SOCKET Handle
,
376 LPDWORD lpNumberOfBytesRead
,
377 LPDWORD ReceiveFlags
,
378 struct sockaddr
*SocketAddress
,
379 int *SocketAddressLength
,
380 LPWSAOVERLAPPED lpOverlapped
,
381 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
382 LPWSATHREADID lpThreadId
,
385 PIO_STATUS_BLOCK IOSB
;
386 IO_STATUS_BLOCK DummyIOSB
;
387 AFD_RECV_INFO_UDP RecvInfo
;
393 PSOCKET_INFORMATION Socket
;
395 /* Get the Socket Structure associate to this Socket*/
396 Socket
= GetSocketStructure(Handle
);
400 *lpErrno
= WSAENOTSOCK
;
403 if (!lpNumberOfBytesRead
&& !lpOverlapped
)
406 *lpErrno
= WSAEFAULT
;
410 if (!(Socket
->SharedData
->ServiceFlags1
& XP1_CONNECTIONLESS
))
412 /* Call WSPRecv for a non-datagram socket */
413 return WSPRecv(Handle
,
425 if (Socket
->SharedData
->State
== SocketOpen
)
427 Socket
->HelperData
->WSHGetWildcardSockaddr(Socket
->HelperContext
,
429 SocketAddressLength
);
431 if (WSPBind(Handle
, SocketAddress
, *SocketAddressLength
, lpErrno
) == SOCKET_ERROR
)
435 Status
= NtCreateEvent( &SockEvent
, EVENT_ALL_ACCESS
,
438 if( !NT_SUCCESS(Status
) )
441 /* Set up the Receive Structure */
442 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
443 RecvInfo
.BufferCount
= dwBufferCount
;
444 RecvInfo
.TdiFlags
= 0;
445 RecvInfo
.AfdFlags
= Socket
->SharedData
->NonBlocking
? AFD_IMMEDIATE
: 0;
446 RecvInfo
.AddressLength
= SocketAddressLength
;
447 RecvInfo
.Address
= SocketAddress
;
449 /* Set the TDI Flags */
450 if (*ReceiveFlags
== 0)
452 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
456 if (*ReceiveFlags
& MSG_OOB
)
458 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
461 if (*ReceiveFlags
& MSG_PEEK
)
463 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
466 if (*ReceiveFlags
& MSG_PARTIAL
)
468 RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
472 /* Verifiy if we should use APC */
474 if (lpOverlapped
== NULL
)
476 /* Not using Overlapped structure, so use normal blocking on event */
484 /* Overlapped request for non overlapped opened socket */
485 if ((Socket
->SharedData
->CreateFlags
& SO_SYNCHRONOUS_NONALERT
) != 0)
487 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
488 return MsafdReturnWithErrno(0, lpErrno
, 0, lpNumberOfBytesRead
);
490 if (lpCompletionRoutine
== NULL
)
492 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
493 APCContext
= lpOverlapped
;
495 Event
= lpOverlapped
->hEvent
;
499 /* Using Overlapped Structure and a Completition Routine, so use an APC */
500 APCFunction
= &AfdAPC
; // should be a private io completition function inside us
501 APCContext
= HeapAlloc(GlobalHeap
, 0, sizeof(AFDAPCCONTEXT
));
504 ERR("Not enough memory for APC Context\n");
505 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, lpNumberOfBytesRead
);
507 ((PAFDAPCCONTEXT
)APCContext
)->lpCompletionRoutine
= lpCompletionRoutine
;
508 ((PAFDAPCCONTEXT
)APCContext
)->lpOverlapped
= lpOverlapped
;
509 ((PAFDAPCCONTEXT
)APCContext
)->lpSocket
= Socket
;
510 RecvInfo
.AfdFlags
|= AFD_SKIP_FIO
;
513 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
514 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
517 IOSB
->Status
= STATUS_PENDING
;
520 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
525 IOCTL_AFD_RECV_DATAGRAM
,
531 /* Wait for completition of not overlapped */
532 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
534 WaitForSingleObject(SockEvent
, INFINITE
); // BUGBUG, shouldn wait infintely for receive...
535 Status
= IOSB
->Status
;
538 NtClose( SockEvent
);
540 if (Status
== STATUS_PENDING
)
542 TRACE("Leaving (Pending)\n");
543 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
546 /* Return the Flags */
551 case STATUS_RECEIVE_EXPEDITED
:
552 *ReceiveFlags
= MSG_OOB
;
554 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
555 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
557 case STATUS_RECEIVE_PARTIAL
:
558 *ReceiveFlags
= MSG_PARTIAL
;
562 /* Re-enable Async Event */
563 if (*ReceiveFlags
& MSG_OOB
)
565 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
569 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
572 if (Status
== STATUS_SUCCESS
&& lpOverlapped
&& lpCompletionRoutine
)
574 lpCompletionRoutine(Status
, IOSB
->Information
, lpOverlapped
, *ReceiveFlags
);
575 HeapFree(GlobalHeap
, 0, (PVOID
)APCContext
);
578 return MsafdReturnWithErrno ( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesRead
);
584 WSPSend(SOCKET Handle
,
587 LPDWORD lpNumberOfBytesSent
,
589 LPWSAOVERLAPPED lpOverlapped
,
590 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
591 LPWSATHREADID lpThreadId
,
594 PIO_STATUS_BLOCK IOSB
;
595 IO_STATUS_BLOCK DummyIOSB
;
596 AFD_SEND_INFO SendInfo
;
602 PSOCKET_INFORMATION Socket
;
604 /* Get the Socket Structure associate to this Socket*/
605 Socket
= GetSocketStructure(Handle
);
609 *lpErrno
= WSAENOTSOCK
;
612 if (!lpNumberOfBytesSent
&& !lpOverlapped
)
615 *lpErrno
= WSAEFAULT
;
619 Status
= NtCreateEvent( &SockEvent
, EVENT_ALL_ACCESS
,
622 if( !NT_SUCCESS(Status
) )
627 /* Set up the Send Structure */
628 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
629 SendInfo
.BufferCount
= dwBufferCount
;
630 SendInfo
.TdiFlags
= 0;
631 SendInfo
.AfdFlags
= Socket
->SharedData
->NonBlocking
? AFD_IMMEDIATE
: 0;
633 /* Set the TDI Flags */
636 if (iFlags
& MSG_OOB
)
638 SendInfo
.TdiFlags
|= TDI_SEND_EXPEDITED
;
640 if (iFlags
& MSG_PARTIAL
)
642 SendInfo
.TdiFlags
|= TDI_SEND_PARTIAL
;
646 /* Verifiy if we should use APC */
647 if (lpOverlapped
== NULL
)
649 /* Not using Overlapped structure, so use normal blocking on event */
657 /* Overlapped request for non overlapped opened socket */
658 if ((Socket
->SharedData
->CreateFlags
& SO_SYNCHRONOUS_NONALERT
) != 0)
660 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
661 return MsafdReturnWithErrno(0, lpErrno
, 0, lpNumberOfBytesSent
);
663 if (lpCompletionRoutine
== NULL
)
665 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
666 APCContext
= lpOverlapped
;
668 Event
= lpOverlapped
->hEvent
;
672 /* Using Overlapped Structure and a Completition Routine, so use an APC */
673 APCFunction
= &AfdAPC
; // should be a private io completition function inside us
674 APCContext
= HeapAlloc(GlobalHeap
, 0, sizeof(AFDAPCCONTEXT
));
677 ERR("Not enough memory for APC Context\n");
678 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, lpNumberOfBytesSent
);
680 ((PAFDAPCCONTEXT
)APCContext
)->lpCompletionRoutine
= lpCompletionRoutine
;
681 ((PAFDAPCCONTEXT
)APCContext
)->lpOverlapped
= lpOverlapped
;
682 ((PAFDAPCCONTEXT
)APCContext
)->lpSocket
= Socket
;
683 SendInfo
.AfdFlags
|= AFD_SKIP_FIO
;
686 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
687 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
690 IOSB
->Status
= STATUS_PENDING
;
693 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
704 /* Wait for completition of not overlapped */
705 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
707 WaitForSingleObject(SockEvent
, INFINITE
); // BUGBUG, shouldn wait infintely for send...
708 Status
= IOSB
->Status
;
711 NtClose( SockEvent
);
713 if (Status
== STATUS_PENDING
)
715 TRACE("Leaving (Pending)\n");
716 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
719 /* Re-enable Async Event */
720 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
722 TRACE("Leaving (Success, %d)\n", IOSB
->Information
);
724 if (Status
== STATUS_SUCCESS
&& lpOverlapped
&& lpCompletionRoutine
)
726 lpCompletionRoutine(Status
, IOSB
->Information
, lpOverlapped
, 0);
727 HeapFree(GlobalHeap
, 0, (PVOID
)APCContext
);
730 return MsafdReturnWithErrno( Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
735 WSPSendTo(SOCKET Handle
,
738 LPDWORD lpNumberOfBytesSent
,
740 const struct sockaddr
*SocketAddress
,
741 int SocketAddressLength
,
742 LPWSAOVERLAPPED lpOverlapped
,
743 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
744 LPWSATHREADID lpThreadId
,
747 PIO_STATUS_BLOCK IOSB
;
748 IO_STATUS_BLOCK DummyIOSB
;
749 AFD_SEND_INFO_UDP SendInfo
;
754 PTRANSPORT_ADDRESS RemoteAddress
;
755 PSOCKADDR BindAddress
= NULL
;
756 INT BindAddressLength
;
758 PSOCKET_INFORMATION Socket
;
760 /* Get the Socket Structure associate to this Socket */
761 Socket
= GetSocketStructure(Handle
);
765 *lpErrno
= WSAENOTSOCK
;
768 if (!lpNumberOfBytesSent
&& !lpOverlapped
)
771 *lpErrno
= WSAEFAULT
;
775 if (!(Socket
->SharedData
->ServiceFlags1
& XP1_CONNECTIONLESS
))
777 /* Use WSPSend for connection-oriented sockets */
778 return WSPSend(Handle
,
790 if (Socket
->SharedData
->State
== SocketOpen
)
792 /* Get the Wildcard Address */
793 BindAddressLength
= Socket
->HelperData
->MaxWSAddressLength
;
794 BindAddress
= HeapAlloc(GlobalHeap
, 0, BindAddressLength
);
797 MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, NULL
);
798 return INVALID_SOCKET
;
801 Socket
->HelperData
->WSHGetWildcardSockaddr(Socket
->HelperContext
,
805 if (WSPBind(Handle
, BindAddress
, BindAddressLength
, lpErrno
) == SOCKET_ERROR
)
809 RemoteAddress
= HeapAlloc(GlobalHeap
, 0, 0x6 + SocketAddressLength
);
812 if (BindAddress
!= NULL
)
814 HeapFree(GlobalHeap
, 0, BindAddress
);
816 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, NULL
);
819 Status
= NtCreateEvent(&SockEvent
,
823 if (!NT_SUCCESS(Status
))
825 HeapFree(GlobalHeap
, 0, RemoteAddress
);
826 if (BindAddress
!= NULL
)
828 HeapFree(GlobalHeap
, 0, BindAddress
);
833 /* Set up Address in TDI Format */
834 RemoteAddress
->TAAddressCount
= 1;
835 RemoteAddress
->Address
[0].AddressLength
= SocketAddressLength
- sizeof(SocketAddress
->sa_family
);
836 RtlCopyMemory(&RemoteAddress
->Address
[0].AddressType
, SocketAddress
, SocketAddressLength
);
838 /* Set up Structure */
839 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
840 SendInfo
.AfdFlags
= Socket
->SharedData
->NonBlocking
? AFD_IMMEDIATE
: 0;
841 SendInfo
.BufferCount
= dwBufferCount
;
842 SendInfo
.TdiConnection
.RemoteAddress
= RemoteAddress
;
843 SendInfo
.TdiConnection
.RemoteAddressLength
= Socket
->HelperData
->MaxTDIAddressLength
;
845 /* Verifiy if we should use APC */
846 if (lpOverlapped
== NULL
)
848 /* Not using Overlapped structure, so use normal blocking on event */
856 /* Overlapped request for non overlapped opened socket */
857 if ((Socket
->SharedData
->CreateFlags
& SO_SYNCHRONOUS_NONALERT
) != 0)
859 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
860 return MsafdReturnWithErrno(0, lpErrno
, 0, lpNumberOfBytesSent
);
862 if (lpCompletionRoutine
== NULL
)
864 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
865 APCContext
= lpOverlapped
;
867 Event
= lpOverlapped
->hEvent
;
871 /* Using Overlapped Structure and a Completition Routine, so use an APC */
872 APCFunction
= &AfdAPC
; // should be a private io completition function inside us
873 APCContext
= HeapAlloc(GlobalHeap
, 0, sizeof(AFDAPCCONTEXT
));
876 ERR("Not enough memory for APC Context\n");
877 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES
, lpErrno
, 0, lpNumberOfBytesSent
);
879 ((PAFDAPCCONTEXT
)APCContext
)->lpCompletionRoutine
= lpCompletionRoutine
;
880 ((PAFDAPCCONTEXT
)APCContext
)->lpOverlapped
= lpOverlapped
;
881 ((PAFDAPCCONTEXT
)APCContext
)->lpSocket
= Socket
;
882 SendInfo
.AfdFlags
|= AFD_SKIP_FIO
;
885 IOSB
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
886 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
890 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
895 IOCTL_AFD_SEND_DATAGRAM
,
901 /* Wait for completition of not overlapped */
902 if (Status
== STATUS_PENDING
&& lpOverlapped
== NULL
)
904 /* BUGBUG, shouldn't wait infintely for send... */
905 WaitForSingleObject(SockEvent
, INFINITE
);
906 Status
= IOSB
->Status
;
910 HeapFree(GlobalHeap
, 0, RemoteAddress
);
911 if (BindAddress
!= NULL
)
913 HeapFree(GlobalHeap
, 0, BindAddress
);
916 if (Status
== STATUS_PENDING
)
918 TRACE("Leaving (Pending)\n");
919 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
922 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
924 if (Status
== STATUS_SUCCESS
&& lpOverlapped
&& lpCompletionRoutine
)
926 lpCompletionRoutine(Status
, IOSB
->Information
, lpOverlapped
, 0);
927 HeapFree(GlobalHeap
, 0, (PVOID
)APCContext
);
930 return MsafdReturnWithErrno(Status
, lpErrno
, IOSB
->Information
, lpNumberOfBytesSent
);
935 WSPRecvDisconnect(IN SOCKET s
,
936 OUT LPWSABUF lpInboundDisconnectData
,
947 WSPSendDisconnect(IN SOCKET s
,
948 IN LPWSABUF lpOutboundDisconnectData
,