2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Winsock 2 SPI
4 * FILE: lib/mswsock/lib/init.c
5 * PURPOSE: DLL Initialization
8 /* INCLUDES ******************************************************************/
11 /* DATA **********************************************************************/
13 /* FUNCTIONS *****************************************************************/
17 WSPSend(SOCKET Handle
,
20 LPDWORD lpNumberOfBytesSent
,
22 LPWSAOVERLAPPED lpOverlapped
,
23 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
24 LPWSATHREADID lpThreadId
,
27 PIO_STATUS_BLOCK IoStatusBlock
;
28 IO_STATUS_BLOCK DummyIoStatusBlock
;
29 AFD_SEND_INFO SendInfo
;
34 PWINSOCK_TEB_DATA ThreadData
;
35 PSOCKET_INFORMATION Socket
;
40 ErrorCode
= SockEnterApiFast(&ThreadData
);
41 if (ErrorCode
!= NO_ERROR
)
48 /* Set up the Receive Structure */
49 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
50 SendInfo
.BufferCount
= dwBufferCount
;
51 SendInfo
.TdiFlags
= 0;
52 SendInfo
.AfdFlags
= 0;
54 /* Set the TDI Flags */
57 /* Check for valid flags */
58 if ((iFlags
& ~(MSG_OOB
| MSG_DONTROUTE
| MSG_PARTIAL
)))
61 ErrorCode
= WSAEOPNOTSUPP
;
65 /* Check if OOB is being used */
68 /* Use Expedited Send for OOB */
69 SendInfo
.TdiFlags
|= TDI_SEND_EXPEDITED
;
72 /* Use Partial Send if enabled */
73 if (iFlags
& MSG_PARTIAL
) SendInfo
.TdiFlags
|= TDI_SEND_PARTIAL
;
76 /* Verifiy if we should use APC */
79 /* Not using Overlapped structure, so use normal blocking on event */
82 Event
= ThreadData
->EventHandle
;
83 IoStatusBlock
= &DummyIoStatusBlock
;
87 /* Using apc, check if we have a completion routine */
88 if (!lpCompletionRoutine
)
91 APCContext
= lpOverlapped
;
93 Event
= lpOverlapped
->hEvent
;
98 ApcFunction
= SockIoCompletion
;
99 APCContext
= lpCompletionRoutine
;
103 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
106 /* Use the overlapped's structure buffer for the I/O Status Block */
107 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
109 /* Make this an overlapped I/O in AFD */
110 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
113 /* Set is as Pending for now */
114 IoStatusBlock
->Status
= STATUS_PENDING
;
117 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
128 /* Increase the pending APC Count if we're using an APC */
129 if (!NT_ERROR(Status
) && ApcFunction
)
131 ThreadData
->PendingAPCs
++;
132 InterlockedIncrement(&SockProcessPendingAPCCount
);
135 /* Wait for completition if not overlapped */
136 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
138 /* Wait for completion */
139 ReturnValue
= SockWaitForSingleObject(Event
,
144 /* Check if the wait was successful */
148 Status
= IoStatusBlock
->Status
;
153 SockCancelIo(Handle
);
154 Status
= STATUS_IO_TIMEOUT
;
167 ErrorCode
= WSA_IO_PENDING
;
172 if (!NT_SUCCESS(Status
))
175 ErrorCode
= NtStatusToSocketError(Status
);
181 /* Return the number of bytes sent */
182 *lpNumberOfBytesSent
= PtrToUlong(IoStatusBlock
->Information
);
186 /* Check if async select was active and this blocked */
187 if (SockAsyncSelectCalled
&& (ErrorCode
== WSAEWOULDBLOCK
))
190 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
194 EnterCriticalSection(&Socket
->Lock
);
196 /* Re-enable the regular write event */
197 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
199 /* Unlock and dereference socket */
200 LeaveCriticalSection(&Socket
->Lock
);
201 SockDereferenceSocket(Socket
);
205 /* Check for error */
206 if (ErrorCode
!= NO_ERROR
)
209 *lpErrno
= ErrorCode
;
219 WSPSendTo(SOCKET Handle
,
222 LPDWORD lpNumberOfBytesSent
,
224 const struct sockaddr
*SocketAddress
,
225 INT SocketAddressLength
,
226 LPWSAOVERLAPPED lpOverlapped
,
227 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
228 LPWSATHREADID lpThreadId
,
231 PIO_STATUS_BLOCK IoStatusBlock
;
232 IO_STATUS_BLOCK DummyIoStatusBlock
;
233 AFD_SEND_INFO_UDP SendInfo
;
238 PWINSOCK_TEB_DATA ThreadData
;
239 PSOCKET_INFORMATION Socket
;
242 CHAR AddressBuffer
[FIELD_OFFSET(TDI_ADDRESS_INFO
, Address
) +
243 MAX_TDI_ADDRESS_LENGTH
];
244 PTRANSPORT_ADDRESS TdiAddress
= (PTRANSPORT_ADDRESS
)AddressBuffer
;
245 ULONG TdiAddressSize
;
248 SOCKADDR_INFO SocketInfo
;
251 ErrorCode
= SockEnterApiFast(&ThreadData
);
252 if (ErrorCode
!= NO_ERROR
)
255 *lpErrno
= ErrorCode
;
259 /* Get the socket structure */
260 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
264 ErrorCode
= WSAENOTSOCK
;
269 * Check if this isn't a datagram socket or if it's a connected socket
272 if (!MSAFD_IS_DGRAM_SOCK(Socket
) ||
273 ((Socket
->SharedData
.State
== SocketConnected
) &&
274 (!SocketAddress
|| !SocketAddressLength
)))
276 /* Call WSPSend instead */
277 SockDereferenceSocket(Socket
);
278 return WSPSend(Handle
,
289 /* If the socket isn't connected, we need an address*/
290 if ((Socket
->SharedData
.State
!= SocketConnected
) && (!SocketAddress
))
293 ErrorCode
= WSAENOTCONN
;
297 /* Validate length */
298 if (SocketAddressLength
< Socket
->HelperData
->MaxWSAddressLength
)
301 ErrorCode
= WSAEFAULT
;
306 if (iFlags
& ~MSG_DONTROUTE
)
309 ErrorCode
= WSAEOPNOTSUPP
;
313 /* Make sure send shutdown isn't active */
314 if (Socket
->SharedData
.SendShutdown
)
317 ErrorCode
= WSAESHUTDOWN
;
321 /* Make sure address families match */
322 if (Socket
->SharedData
.AddressFamily
!= SocketAddress
->sa_family
)
325 ErrorCode
= WSAEOPNOTSUPP
;
329 /* Check if broadcast is enabled */
330 if (!Socket
->SharedData
.Broadcast
)
332 /* The caller might want to enable it; get the Sockaddr type */
333 ErrorCode
= Socket
->HelperData
->WSHGetSockaddrType((PSOCKADDR
)SocketAddress
,
336 if (ErrorCode
!= NO_ERROR
) goto error
;
338 /* Check if this is a broadcast attempt */
339 if (SocketInfo
.AddressInfo
== SockaddrAddressInfoBroadcast
)
341 /* The socket won't allow it */
342 ErrorCode
= WSAEACCES
;
347 /* Check if this socket isn't bound yet */
348 if (Socket
->SharedData
.State
== SocketOpen
)
350 /* Check if we can request the wildcard address */
351 if (Socket
->HelperData
->WSHGetWildcardSockaddr
)
353 /* Allocate a new Sockaddr */
354 SockaddrLength
= Socket
->HelperData
->MaxWSAddressLength
;
355 Sockaddr
= SockAllocateHeapRoutine(SockPrivateHeap
, 0, SockaddrLength
);
359 ErrorCode
= WSAENOBUFS
;
363 /* Get the wildcard sockaddr */
364 ErrorCode
= Socket
->HelperData
->WSHGetWildcardSockaddr(Socket
->HelperContext
,
367 if (ErrorCode
!= NO_ERROR
)
369 /* Free memory and fail */
370 RtlFreeHeap(SockPrivateHeap
, 0, Sockaddr
);
374 /* Lock the socket */
375 EnterCriticalSection(&Socket
->Lock
);
377 /* Make sure it's still unbound */
378 if (Socket
->SharedData
.State
== SocketOpen
)
381 ReturnValue
= WSPBind(Handle
,
388 /* It's bound now, fake success */
389 ReturnValue
= NO_ERROR
;
392 /* Release the lock and free memory */
393 LeaveCriticalSection(&Socket
->Lock
);
394 RtlFreeHeap(SockPrivateHeap
, 0, Sockaddr
);
396 /* Check if we failed */
397 if (ReturnValue
== SOCKET_ERROR
) goto error
;
401 /* Unbound socket, but can't get the wildcard. Fail */
402 ErrorCode
= WSAEINVAL
;
407 /* Check how long the TDI Address is */
408 TdiAddressSize
= Socket
->HelperData
->MaxTDIAddressLength
;
410 /* See if it can fit in the stack */
411 if (TdiAddressSize
> sizeof(AddressBuffer
))
413 /* Allocate from heap */
414 TdiAddress
= SockAllocateHeapRoutine(SockPrivateHeap
, 0, TdiAddressSize
);
418 ErrorCode
= WSAENOBUFS
;
423 /* Build the TDI Address */
424 ErrorCode
= SockBuildTdiAddress(TdiAddress
,
425 (PSOCKADDR
)SocketAddress
,
426 min(SocketAddressLength
,
427 Socket
->HelperData
->MaxWSAddressLength
));
428 if (ErrorCode
!= NO_ERROR
) goto error
;
430 /* Set up the Send Structure */
431 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
432 SendInfo
.BufferCount
= dwBufferCount
;
433 SendInfo
.AfdFlags
= 0;
434 SendInfo
.TdiConnection
.RemoteAddress
= TdiAddress
;
435 SendInfo
.TdiConnection
.RemoteAddressLength
= TdiAddressSize
;
437 /* Verifiy if we should use APC */
440 /* Not using Overlapped structure, so use normal blocking on event */
443 Event
= ThreadData
->EventHandle
;
444 IoStatusBlock
= &DummyIoStatusBlock
;
448 /* Using apc, check if we have a completion routine */
449 if (!lpCompletionRoutine
)
451 /* No need for APC */
452 APCContext
= lpOverlapped
;
454 Event
= lpOverlapped
->hEvent
;
459 ApcFunction
= SockIoCompletion
;
460 APCContext
= lpCompletionRoutine
;
464 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
467 /* Use the overlapped's structure buffer for the I/O Status Block */
468 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
470 /* Make this an overlapped I/O in AFD */
471 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
474 /* Set is as Pending for now */
475 IoStatusBlock
->Status
= STATUS_PENDING
;
478 Status
= NtDeviceIoControlFile(Socket
->WshContext
.Handle
,
483 IOCTL_AFD_SEND_DATAGRAM
,
489 /* Increase the pending APC Count if we're using an APC */
490 if (!NT_ERROR(Status
) && ApcFunction
)
492 ThreadData
->PendingAPCs
++;
493 InterlockedIncrement(&SockProcessPendingAPCCount
);
496 /* Wait for completition if not overlapped */
497 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
499 /* Wait for completion */
500 ReturnValue
= SockWaitForSingleObject(Event
,
505 /* Check if the wait was successful */
509 Status
= IoStatusBlock
->Status
;
514 SockCancelIo(Handle
);
515 Status
= STATUS_IO_TIMEOUT
;
528 ErrorCode
= WSA_IO_PENDING
;
533 if (!NT_SUCCESS(Status
))
536 ErrorCode
= NtStatusToSocketError(Status
);
542 /* Return the number of bytes sent */
543 *lpNumberOfBytesSent
= PtrToUlong(IoStatusBlock
->Information
);
547 /* Check if we have a socket */
550 /* Check if async select was active and this blocked */
551 if (SockAsyncSelectCalled
&& (ErrorCode
== WSAEWOULDBLOCK
))
554 EnterCriticalSection(&Socket
->Lock
);
556 /* Re-enable the regular write event */
557 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
560 LeaveCriticalSection(&Socket
->Lock
);
563 /* Dereference socket */
564 SockDereferenceSocket(Socket
);
567 /* Check if we should free the TDI Address */
568 if (TdiAddress
&& (TdiAddress
!= (PVOID
)AddressBuffer
))
570 /* Free it from the heap */
571 RtlFreeHeap(SockPrivateHeap
, 0, TdiAddress
);
574 /* Check for error */
575 if (ErrorCode
!= NO_ERROR
)
578 *lpErrno
= ErrorCode
;
587 * COPYRIGHT: See COPYING in the top level directory
588 * PROJECT: ReactOS Winsock 2 SPI
589 * FILE: lib/mswsock/lib/init.c
590 * PURPOSE: DLL Initialization
593 /* INCLUDES ******************************************************************/
596 /* DATA **********************************************************************/
598 /* FUNCTIONS *****************************************************************/
602 WSPSend(SOCKET Handle
,
605 LPDWORD lpNumberOfBytesSent
,
607 LPWSAOVERLAPPED lpOverlapped
,
608 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
609 LPWSATHREADID lpThreadId
,
612 PIO_STATUS_BLOCK IoStatusBlock
;
613 IO_STATUS_BLOCK DummyIoStatusBlock
;
614 AFD_SEND_INFO SendInfo
;
619 PWINSOCK_TEB_DATA ThreadData
;
620 PSOCKET_INFORMATION Socket
;
625 ErrorCode
= SockEnterApiFast(&ThreadData
);
626 if (ErrorCode
!= NO_ERROR
)
629 *lpErrno
= ErrorCode
;
633 /* Set up the Receive Structure */
634 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
635 SendInfo
.BufferCount
= dwBufferCount
;
636 SendInfo
.TdiFlags
= 0;
637 SendInfo
.AfdFlags
= 0;
639 /* Set the TDI Flags */
642 /* Check for valid flags */
643 if ((iFlags
& ~(MSG_OOB
| MSG_DONTROUTE
| MSG_PARTIAL
)))
646 ErrorCode
= WSAEOPNOTSUPP
;
650 /* Check if OOB is being used */
651 if (iFlags
& MSG_OOB
)
653 /* Use Expedited Send for OOB */
654 SendInfo
.TdiFlags
|= TDI_SEND_EXPEDITED
;
657 /* Use Partial Send if enabled */
658 if (iFlags
& MSG_PARTIAL
) SendInfo
.TdiFlags
|= TDI_SEND_PARTIAL
;
661 /* Verifiy if we should use APC */
664 /* Not using Overlapped structure, so use normal blocking on event */
667 Event
= ThreadData
->EventHandle
;
668 IoStatusBlock
= &DummyIoStatusBlock
;
672 /* Using apc, check if we have a completion routine */
673 if (!lpCompletionRoutine
)
675 /* No need for APC */
676 APCContext
= lpOverlapped
;
678 Event
= lpOverlapped
->hEvent
;
683 ApcFunction
= SockIoCompletion
;
684 APCContext
= lpCompletionRoutine
;
688 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
691 /* Use the overlapped's structure buffer for the I/O Status Block */
692 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
694 /* Make this an overlapped I/O in AFD */
695 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
698 /* Set is as Pending for now */
699 IoStatusBlock
->Status
= STATUS_PENDING
;
702 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
713 /* Increase the pending APC Count if we're using an APC */
714 if (!NT_ERROR(Status
) && ApcFunction
)
716 ThreadData
->PendingAPCs
++;
717 InterlockedIncrement(&SockProcessPendingAPCCount
);
720 /* Wait for completition if not overlapped */
721 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
723 /* Wait for completion */
724 ReturnValue
= SockWaitForSingleObject(Event
,
729 /* Check if the wait was successful */
733 Status
= IoStatusBlock
->Status
;
738 SockCancelIo(Handle
);
739 Status
= STATUS_IO_TIMEOUT
;
752 ErrorCode
= WSA_IO_PENDING
;
757 if (!NT_SUCCESS(Status
))
760 ErrorCode
= NtStatusToSocketError(Status
);
766 /* Return the number of bytes sent */
767 *lpNumberOfBytesSent
= PtrToUlong(IoStatusBlock
->Information
);
771 /* Check if async select was active and this blocked */
772 if (SockAsyncSelectCalled
&& (ErrorCode
== WSAEWOULDBLOCK
))
775 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
779 EnterCriticalSection(&Socket
->Lock
);
781 /* Re-enable the regular write event */
782 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
784 /* Unlock and dereference socket */
785 LeaveCriticalSection(&Socket
->Lock
);
786 SockDereferenceSocket(Socket
);
790 /* Check for error */
791 if (ErrorCode
!= NO_ERROR
)
794 *lpErrno
= ErrorCode
;
804 WSPSendTo(SOCKET Handle
,
807 LPDWORD lpNumberOfBytesSent
,
809 const struct sockaddr
*SocketAddress
,
810 INT SocketAddressLength
,
811 LPWSAOVERLAPPED lpOverlapped
,
812 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
813 LPWSATHREADID lpThreadId
,
816 PIO_STATUS_BLOCK IoStatusBlock
;
817 IO_STATUS_BLOCK DummyIoStatusBlock
;
818 AFD_SEND_INFO_UDP SendInfo
;
823 PWINSOCK_TEB_DATA ThreadData
;
824 PSOCKET_INFORMATION Socket
;
827 CHAR AddressBuffer
[FIELD_OFFSET(TDI_ADDRESS_INFO
, Address
) +
828 MAX_TDI_ADDRESS_LENGTH
];
829 PTRANSPORT_ADDRESS TdiAddress
= (PTRANSPORT_ADDRESS
)AddressBuffer
;
830 ULONG TdiAddressSize
;
833 SOCKADDR_INFO SocketInfo
;
836 ErrorCode
= SockEnterApiFast(&ThreadData
);
837 if (ErrorCode
!= NO_ERROR
)
840 *lpErrno
= ErrorCode
;
844 /* Get the socket structure */
845 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
849 ErrorCode
= WSAENOTSOCK
;
854 * Check if this isn't a datagram socket or if it's a connected socket
857 if (!MSAFD_IS_DGRAM_SOCK(Socket
) ||
858 ((Socket
->SharedData
.State
== SocketConnected
) &&
859 (!SocketAddress
|| !SocketAddressLength
)))
861 /* Call WSPSend instead */
862 SockDereferenceSocket(Socket
);
863 return WSPSend(Handle
,
874 /* If the socket isn't connected, we need an address*/
875 if ((Socket
->SharedData
.State
!= SocketConnected
) && (!SocketAddress
))
878 ErrorCode
= WSAENOTCONN
;
882 /* Validate length */
883 if (SocketAddressLength
< Socket
->HelperData
->MaxWSAddressLength
)
886 ErrorCode
= WSAEFAULT
;
891 if (iFlags
& ~MSG_DONTROUTE
)
894 ErrorCode
= WSAEOPNOTSUPP
;
898 /* Make sure send shutdown isn't active */
899 if (Socket
->SharedData
.SendShutdown
)
902 ErrorCode
= WSAESHUTDOWN
;
906 /* Make sure address families match */
907 if (Socket
->SharedData
.AddressFamily
!= SocketAddress
->sa_family
)
910 ErrorCode
= WSAEOPNOTSUPP
;
914 /* Check if broadcast is enabled */
915 if (!Socket
->SharedData
.Broadcast
)
917 /* The caller might want to enable it; get the Sockaddr type */
918 ErrorCode
= Socket
->HelperData
->WSHGetSockaddrType((PSOCKADDR
)SocketAddress
,
921 if (ErrorCode
!= NO_ERROR
) goto error
;
923 /* Check if this is a broadcast attempt */
924 if (SocketInfo
.AddressInfo
== SockaddrAddressInfoBroadcast
)
926 /* The socket won't allow it */
927 ErrorCode
= WSAEACCES
;
932 /* Check if this socket isn't bound yet */
933 if (Socket
->SharedData
.State
== SocketOpen
)
935 /* Check if we can request the wildcard address */
936 if (Socket
->HelperData
->WSHGetWildcardSockaddr
)
938 /* Allocate a new Sockaddr */
939 SockaddrLength
= Socket
->HelperData
->MaxWSAddressLength
;
940 Sockaddr
= SockAllocateHeapRoutine(SockPrivateHeap
, 0, SockaddrLength
);
944 ErrorCode
= WSAENOBUFS
;
948 /* Get the wildcard sockaddr */
949 ErrorCode
= Socket
->HelperData
->WSHGetWildcardSockaddr(Socket
->HelperContext
,
952 if (ErrorCode
!= NO_ERROR
)
954 /* Free memory and fail */
955 RtlFreeHeap(SockPrivateHeap
, 0, Sockaddr
);
959 /* Lock the socket */
960 EnterCriticalSection(&Socket
->Lock
);
962 /* Make sure it's still unbound */
963 if (Socket
->SharedData
.State
== SocketOpen
)
966 ReturnValue
= WSPBind(Handle
,
973 /* It's bound now, fake success */
974 ReturnValue
= NO_ERROR
;
977 /* Release the lock and free memory */
978 LeaveCriticalSection(&Socket
->Lock
);
979 RtlFreeHeap(SockPrivateHeap
, 0, Sockaddr
);
981 /* Check if we failed */
982 if (ReturnValue
== SOCKET_ERROR
) goto error
;
986 /* Unbound socket, but can't get the wildcard. Fail */
987 ErrorCode
= WSAEINVAL
;
992 /* Check how long the TDI Address is */
993 TdiAddressSize
= Socket
->HelperData
->MaxTDIAddressLength
;
995 /* See if it can fit in the stack */
996 if (TdiAddressSize
> sizeof(AddressBuffer
))
998 /* Allocate from heap */
999 TdiAddress
= SockAllocateHeapRoutine(SockPrivateHeap
, 0, TdiAddressSize
);
1003 ErrorCode
= WSAENOBUFS
;
1008 /* Build the TDI Address */
1009 ErrorCode
= SockBuildTdiAddress(TdiAddress
,
1010 (PSOCKADDR
)SocketAddress
,
1011 min(SocketAddressLength
,
1012 Socket
->HelperData
->MaxWSAddressLength
));
1013 if (ErrorCode
!= NO_ERROR
) goto error
;
1015 /* Set up the Send Structure */
1016 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
1017 SendInfo
.BufferCount
= dwBufferCount
;
1018 SendInfo
.AfdFlags
= 0;
1019 SendInfo
.TdiConnection
.RemoteAddress
= TdiAddress
;
1020 SendInfo
.TdiConnection
.RemoteAddressLength
= TdiAddressSize
;
1022 /* Verifiy if we should use APC */
1025 /* Not using Overlapped structure, so use normal blocking on event */
1028 Event
= ThreadData
->EventHandle
;
1029 IoStatusBlock
= &DummyIoStatusBlock
;
1033 /* Using apc, check if we have a completion routine */
1034 if (!lpCompletionRoutine
)
1036 /* No need for APC */
1037 APCContext
= lpOverlapped
;
1039 Event
= lpOverlapped
->hEvent
;
1044 ApcFunction
= SockIoCompletion
;
1045 APCContext
= lpCompletionRoutine
;
1049 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
1052 /* Use the overlapped's structure buffer for the I/O Status Block */
1053 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
1055 /* Make this an overlapped I/O in AFD */
1056 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
1059 /* Set is as Pending for now */
1060 IoStatusBlock
->Status
= STATUS_PENDING
;
1063 Status
= NtDeviceIoControlFile(Socket
->WshContext
.Handle
,
1068 IOCTL_AFD_SEND_DATAGRAM
,
1074 /* Increase the pending APC Count if we're using an APC */
1075 if (!NT_ERROR(Status
) && ApcFunction
)
1077 ThreadData
->PendingAPCs
++;
1078 InterlockedIncrement(&SockProcessPendingAPCCount
);
1081 /* Wait for completition if not overlapped */
1082 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
1084 /* Wait for completion */
1085 ReturnValue
= SockWaitForSingleObject(Event
,
1087 MAYBE_BLOCKING_HOOK
,
1090 /* Check if the wait was successful */
1093 /* Get new status */
1094 Status
= IoStatusBlock
->Status
;
1098 /* Cancel the I/O */
1099 SockCancelIo(Handle
);
1100 Status
= STATUS_IO_TIMEOUT
;
1108 case STATUS_SUCCESS
:
1112 case STATUS_PENDING
:
1113 ErrorCode
= WSA_IO_PENDING
;
1116 /* Other NT Error */
1118 if (!NT_SUCCESS(Status
))
1121 ErrorCode
= NtStatusToSocketError(Status
);
1127 /* Return the number of bytes sent */
1128 *lpNumberOfBytesSent
= PtrToUlong(IoStatusBlock
->Information
);
1132 /* Check if we have a socket */
1135 /* Check if async select was active and this blocked */
1136 if (SockAsyncSelectCalled
&& (ErrorCode
== WSAEWOULDBLOCK
))
1139 EnterCriticalSection(&Socket
->Lock
);
1141 /* Re-enable the regular write event */
1142 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
1145 LeaveCriticalSection(&Socket
->Lock
);
1148 /* Dereference socket */
1149 SockDereferenceSocket(Socket
);
1152 /* Check if we should free the TDI Address */
1153 if (TdiAddress
&& (TdiAddress
!= (PVOID
)AddressBuffer
))
1155 /* Free it from the heap */
1156 RtlFreeHeap(SockPrivateHeap
, 0, TdiAddress
);
1159 /* Check for error */
1160 if (ErrorCode
!= NO_ERROR
)
1163 *lpErrno
= ErrorCode
;
1164 return SOCKET_ERROR
;
1167 /* Return success */
1172 * COPYRIGHT: See COPYING in the top level directory
1173 * PROJECT: ReactOS Winsock 2 SPI
1174 * FILE: lib/mswsock/lib/init.c
1175 * PURPOSE: DLL Initialization
1178 /* INCLUDES ******************************************************************/
1181 /* DATA **********************************************************************/
1183 /* FUNCTIONS *****************************************************************/
1187 WSPSend(SOCKET Handle
,
1189 DWORD dwBufferCount
,
1190 LPDWORD lpNumberOfBytesSent
,
1192 LPWSAOVERLAPPED lpOverlapped
,
1193 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
1194 LPWSATHREADID lpThreadId
,
1197 PIO_STATUS_BLOCK IoStatusBlock
;
1198 IO_STATUS_BLOCK DummyIoStatusBlock
;
1199 AFD_SEND_INFO SendInfo
;
1204 PWINSOCK_TEB_DATA ThreadData
;
1205 PSOCKET_INFORMATION Socket
;
1207 BOOLEAN ReturnValue
;
1210 ErrorCode
= SockEnterApiFast(&ThreadData
);
1211 if (ErrorCode
!= NO_ERROR
)
1214 *lpErrno
= ErrorCode
;
1215 return SOCKET_ERROR
;
1218 /* Set up the Receive Structure */
1219 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
1220 SendInfo
.BufferCount
= dwBufferCount
;
1221 SendInfo
.TdiFlags
= 0;
1222 SendInfo
.AfdFlags
= 0;
1224 /* Set the TDI Flags */
1227 /* Check for valid flags */
1228 if ((iFlags
& ~(MSG_OOB
| MSG_DONTROUTE
| MSG_PARTIAL
)))
1231 ErrorCode
= WSAEOPNOTSUPP
;
1235 /* Check if OOB is being used */
1236 if (iFlags
& MSG_OOB
)
1238 /* Use Expedited Send for OOB */
1239 SendInfo
.TdiFlags
|= TDI_SEND_EXPEDITED
;
1242 /* Use Partial Send if enabled */
1243 if (iFlags
& MSG_PARTIAL
) SendInfo
.TdiFlags
|= TDI_SEND_PARTIAL
;
1246 /* Verifiy if we should use APC */
1249 /* Not using Overlapped structure, so use normal blocking on event */
1252 Event
= ThreadData
->EventHandle
;
1253 IoStatusBlock
= &DummyIoStatusBlock
;
1257 /* Using apc, check if we have a completion routine */
1258 if (!lpCompletionRoutine
)
1260 /* No need for APC */
1261 APCContext
= lpOverlapped
;
1263 Event
= lpOverlapped
->hEvent
;
1268 ApcFunction
= SockIoCompletion
;
1269 APCContext
= lpCompletionRoutine
;
1273 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
1276 /* Use the overlapped's structure buffer for the I/O Status Block */
1277 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
1279 /* Make this an overlapped I/O in AFD */
1280 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
1283 /* Set is as Pending for now */
1284 IoStatusBlock
->Status
= STATUS_PENDING
;
1287 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
1298 /* Increase the pending APC Count if we're using an APC */
1299 if (!NT_ERROR(Status
) && ApcFunction
)
1301 ThreadData
->PendingAPCs
++;
1302 InterlockedIncrement(&SockProcessPendingAPCCount
);
1305 /* Wait for completition if not overlapped */
1306 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
1308 /* Wait for completion */
1309 ReturnValue
= SockWaitForSingleObject(Event
,
1311 MAYBE_BLOCKING_HOOK
,
1314 /* Check if the wait was successful */
1317 /* Get new status */
1318 Status
= IoStatusBlock
->Status
;
1322 /* Cancel the I/O */
1323 SockCancelIo(Handle
);
1324 Status
= STATUS_IO_TIMEOUT
;
1332 case STATUS_SUCCESS
:
1336 case STATUS_PENDING
:
1337 ErrorCode
= WSA_IO_PENDING
;
1340 /* Other NT Error */
1342 if (!NT_SUCCESS(Status
))
1345 ErrorCode
= NtStatusToSocketError(Status
);
1351 /* Return the number of bytes sent */
1352 *lpNumberOfBytesSent
= PtrToUlong(IoStatusBlock
->Information
);
1356 /* Check if async select was active and this blocked */
1357 if (SockAsyncSelectCalled
&& (ErrorCode
== WSAEWOULDBLOCK
))
1359 /* Get the socket */
1360 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
1364 EnterCriticalSection(&Socket
->Lock
);
1366 /* Re-enable the regular write event */
1367 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
1369 /* Unlock and dereference socket */
1370 LeaveCriticalSection(&Socket
->Lock
);
1371 SockDereferenceSocket(Socket
);
1375 /* Check for error */
1376 if (ErrorCode
!= NO_ERROR
)
1379 *lpErrno
= ErrorCode
;
1380 return SOCKET_ERROR
;
1383 /* Return success */
1389 WSPSendTo(SOCKET Handle
,
1391 DWORD dwBufferCount
,
1392 LPDWORD lpNumberOfBytesSent
,
1394 const struct sockaddr
*SocketAddress
,
1395 INT SocketAddressLength
,
1396 LPWSAOVERLAPPED lpOverlapped
,
1397 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
1398 LPWSATHREADID lpThreadId
,
1401 PIO_STATUS_BLOCK IoStatusBlock
;
1402 IO_STATUS_BLOCK DummyIoStatusBlock
;
1403 AFD_SEND_INFO_UDP SendInfo
;
1408 PWINSOCK_TEB_DATA ThreadData
;
1409 PSOCKET_INFORMATION Socket
;
1412 CHAR AddressBuffer
[FIELD_OFFSET(TDI_ADDRESS_INFO
, Address
) +
1413 MAX_TDI_ADDRESS_LENGTH
];
1414 PTRANSPORT_ADDRESS TdiAddress
= (PTRANSPORT_ADDRESS
)AddressBuffer
;
1415 ULONG TdiAddressSize
;
1418 SOCKADDR_INFO SocketInfo
;
1421 ErrorCode
= SockEnterApiFast(&ThreadData
);
1422 if (ErrorCode
!= NO_ERROR
)
1425 *lpErrno
= ErrorCode
;
1426 return SOCKET_ERROR
;
1429 /* Get the socket structure */
1430 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
1434 ErrorCode
= WSAENOTSOCK
;
1439 * Check if this isn't a datagram socket or if it's a connected socket
1440 * without an address
1442 if (!MSAFD_IS_DGRAM_SOCK(Socket
) ||
1443 ((Socket
->SharedData
.State
== SocketConnected
) &&
1444 (!SocketAddress
|| !SocketAddressLength
)))
1446 /* Call WSPSend instead */
1447 SockDereferenceSocket(Socket
);
1448 return WSPSend(Handle
,
1451 lpNumberOfBytesSent
,
1454 lpCompletionRoutine
,
1459 /* If the socket isn't connected, we need an address*/
1460 if ((Socket
->SharedData
.State
!= SocketConnected
) && (!SocketAddress
))
1463 ErrorCode
= WSAENOTCONN
;
1467 /* Validate length */
1468 if (SocketAddressLength
< Socket
->HelperData
->MaxWSAddressLength
)
1471 ErrorCode
= WSAEFAULT
;
1476 if (iFlags
& ~MSG_DONTROUTE
)
1479 ErrorCode
= WSAEOPNOTSUPP
;
1483 /* Make sure send shutdown isn't active */
1484 if (Socket
->SharedData
.SendShutdown
)
1487 ErrorCode
= WSAESHUTDOWN
;
1491 /* Make sure address families match */
1492 if (Socket
->SharedData
.AddressFamily
!= SocketAddress
->sa_family
)
1495 ErrorCode
= WSAEOPNOTSUPP
;
1499 /* Check if broadcast is enabled */
1500 if (!Socket
->SharedData
.Broadcast
)
1502 /* The caller might want to enable it; get the Sockaddr type */
1503 ErrorCode
= Socket
->HelperData
->WSHGetSockaddrType((PSOCKADDR
)SocketAddress
,
1504 SocketAddressLength
,
1506 if (ErrorCode
!= NO_ERROR
) goto error
;
1508 /* Check if this is a broadcast attempt */
1509 if (SocketInfo
.AddressInfo
== SockaddrAddressInfoBroadcast
)
1511 /* The socket won't allow it */
1512 ErrorCode
= WSAEACCES
;
1517 /* Check if this socket isn't bound yet */
1518 if (Socket
->SharedData
.State
== SocketOpen
)
1520 /* Check if we can request the wildcard address */
1521 if (Socket
->HelperData
->WSHGetWildcardSockaddr
)
1523 /* Allocate a new Sockaddr */
1524 SockaddrLength
= Socket
->HelperData
->MaxWSAddressLength
;
1525 Sockaddr
= SockAllocateHeapRoutine(SockPrivateHeap
, 0, SockaddrLength
);
1529 ErrorCode
= WSAENOBUFS
;
1533 /* Get the wildcard sockaddr */
1534 ErrorCode
= Socket
->HelperData
->WSHGetWildcardSockaddr(Socket
->HelperContext
,
1537 if (ErrorCode
!= NO_ERROR
)
1539 /* Free memory and fail */
1540 RtlFreeHeap(SockPrivateHeap
, 0, Sockaddr
);
1544 /* Lock the socket */
1545 EnterCriticalSection(&Socket
->Lock
);
1547 /* Make sure it's still unbound */
1548 if (Socket
->SharedData
.State
== SocketOpen
)
1551 ReturnValue
= WSPBind(Handle
,
1558 /* It's bound now, fake success */
1559 ReturnValue
= NO_ERROR
;
1562 /* Release the lock and free memory */
1563 LeaveCriticalSection(&Socket
->Lock
);
1564 RtlFreeHeap(SockPrivateHeap
, 0, Sockaddr
);
1566 /* Check if we failed */
1567 if (ReturnValue
== SOCKET_ERROR
) goto error
;
1571 /* Unbound socket, but can't get the wildcard. Fail */
1572 ErrorCode
= WSAEINVAL
;
1577 /* Check how long the TDI Address is */
1578 TdiAddressSize
= Socket
->HelperData
->MaxTDIAddressLength
;
1580 /* See if it can fit in the stack */
1581 if (TdiAddressSize
> sizeof(AddressBuffer
))
1583 /* Allocate from heap */
1584 TdiAddress
= SockAllocateHeapRoutine(SockPrivateHeap
, 0, TdiAddressSize
);
1588 ErrorCode
= WSAENOBUFS
;
1593 /* Build the TDI Address */
1594 ErrorCode
= SockBuildTdiAddress(TdiAddress
,
1595 (PSOCKADDR
)SocketAddress
,
1596 min(SocketAddressLength
,
1597 Socket
->HelperData
->MaxWSAddressLength
));
1598 if (ErrorCode
!= NO_ERROR
) goto error
;
1600 /* Set up the Send Structure */
1601 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
1602 SendInfo
.BufferCount
= dwBufferCount
;
1603 SendInfo
.AfdFlags
= 0;
1604 SendInfo
.TdiConnection
.RemoteAddress
= TdiAddress
;
1605 SendInfo
.TdiConnection
.RemoteAddressLength
= TdiAddressSize
;
1607 /* Verifiy if we should use APC */
1610 /* Not using Overlapped structure, so use normal blocking on event */
1613 Event
= ThreadData
->EventHandle
;
1614 IoStatusBlock
= &DummyIoStatusBlock
;
1618 /* Using apc, check if we have a completion routine */
1619 if (!lpCompletionRoutine
)
1621 /* No need for APC */
1622 APCContext
= lpOverlapped
;
1624 Event
= lpOverlapped
->hEvent
;
1629 ApcFunction
= SockIoCompletion
;
1630 APCContext
= lpCompletionRoutine
;
1634 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
1637 /* Use the overlapped's structure buffer for the I/O Status Block */
1638 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
1640 /* Make this an overlapped I/O in AFD */
1641 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
1644 /* Set is as Pending for now */
1645 IoStatusBlock
->Status
= STATUS_PENDING
;
1648 Status
= NtDeviceIoControlFile(Socket
->WshContext
.Handle
,
1653 IOCTL_AFD_SEND_DATAGRAM
,
1659 /* Increase the pending APC Count if we're using an APC */
1660 if (!NT_ERROR(Status
) && ApcFunction
)
1662 ThreadData
->PendingAPCs
++;
1663 InterlockedIncrement(&SockProcessPendingAPCCount
);
1666 /* Wait for completition if not overlapped */
1667 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
1669 /* Wait for completion */
1670 ReturnValue
= SockWaitForSingleObject(Event
,
1672 MAYBE_BLOCKING_HOOK
,
1675 /* Check if the wait was successful */
1678 /* Get new status */
1679 Status
= IoStatusBlock
->Status
;
1683 /* Cancel the I/O */
1684 SockCancelIo(Handle
);
1685 Status
= STATUS_IO_TIMEOUT
;
1693 case STATUS_SUCCESS
:
1697 case STATUS_PENDING
:
1698 ErrorCode
= WSA_IO_PENDING
;
1701 /* Other NT Error */
1703 if (!NT_SUCCESS(Status
))
1706 ErrorCode
= NtStatusToSocketError(Status
);
1712 /* Return the number of bytes sent */
1713 *lpNumberOfBytesSent
= PtrToUlong(IoStatusBlock
->Information
);
1717 /* Check if we have a socket */
1720 /* Check if async select was active and this blocked */
1721 if (SockAsyncSelectCalled
&& (ErrorCode
== WSAEWOULDBLOCK
))
1724 EnterCriticalSection(&Socket
->Lock
);
1726 /* Re-enable the regular write event */
1727 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
1730 LeaveCriticalSection(&Socket
->Lock
);
1733 /* Dereference socket */
1734 SockDereferenceSocket(Socket
);
1737 /* Check if we should free the TDI Address */
1738 if (TdiAddress
&& (TdiAddress
!= (PVOID
)AddressBuffer
))
1740 /* Free it from the heap */
1741 RtlFreeHeap(SockPrivateHeap
, 0, TdiAddress
);
1744 /* Check for error */
1745 if (ErrorCode
!= NO_ERROR
)
1748 *lpErrno
= ErrorCode
;
1749 return SOCKET_ERROR
;
1752 /* Return success */
1757 * COPYRIGHT: See COPYING in the top level directory
1758 * PROJECT: ReactOS Winsock 2 SPI
1759 * FILE: lib/mswsock/lib/init.c
1760 * PURPOSE: DLL Initialization
1763 /* INCLUDES ******************************************************************/
1766 /* DATA **********************************************************************/
1768 /* FUNCTIONS *****************************************************************/
1772 WSPSend(SOCKET Handle
,
1774 DWORD dwBufferCount
,
1775 LPDWORD lpNumberOfBytesSent
,
1777 LPWSAOVERLAPPED lpOverlapped
,
1778 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
1779 LPWSATHREADID lpThreadId
,
1782 PIO_STATUS_BLOCK IoStatusBlock
;
1783 IO_STATUS_BLOCK DummyIoStatusBlock
;
1784 AFD_SEND_INFO SendInfo
;
1789 PWINSOCK_TEB_DATA ThreadData
;
1790 PSOCKET_INFORMATION Socket
;
1792 BOOLEAN ReturnValue
;
1795 ErrorCode
= SockEnterApiFast(&ThreadData
);
1796 if (ErrorCode
!= NO_ERROR
)
1799 *lpErrno
= ErrorCode
;
1800 return SOCKET_ERROR
;
1803 /* Set up the Receive Structure */
1804 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
1805 SendInfo
.BufferCount
= dwBufferCount
;
1806 SendInfo
.TdiFlags
= 0;
1807 SendInfo
.AfdFlags
= 0;
1809 /* Set the TDI Flags */
1812 /* Check for valid flags */
1813 if ((iFlags
& ~(MSG_OOB
| MSG_DONTROUTE
| MSG_PARTIAL
)))
1816 ErrorCode
= WSAEOPNOTSUPP
;
1820 /* Check if OOB is being used */
1821 if (iFlags
& MSG_OOB
)
1823 /* Use Expedited Send for OOB */
1824 SendInfo
.TdiFlags
|= TDI_SEND_EXPEDITED
;
1827 /* Use Partial Send if enabled */
1828 if (iFlags
& MSG_PARTIAL
) SendInfo
.TdiFlags
|= TDI_SEND_PARTIAL
;
1831 /* Verifiy if we should use APC */
1834 /* Not using Overlapped structure, so use normal blocking on event */
1837 Event
= ThreadData
->EventHandle
;
1838 IoStatusBlock
= &DummyIoStatusBlock
;
1842 /* Using apc, check if we have a completion routine */
1843 if (!lpCompletionRoutine
)
1845 /* No need for APC */
1846 APCContext
= lpOverlapped
;
1848 Event
= lpOverlapped
->hEvent
;
1853 ApcFunction
= SockIoCompletion
;
1854 APCContext
= lpCompletionRoutine
;
1858 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
1861 /* Use the overlapped's structure buffer for the I/O Status Block */
1862 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
1864 /* Make this an overlapped I/O in AFD */
1865 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
1868 /* Set is as Pending for now */
1869 IoStatusBlock
->Status
= STATUS_PENDING
;
1872 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
1883 /* Increase the pending APC Count if we're using an APC */
1884 if (!NT_ERROR(Status
) && ApcFunction
)
1886 ThreadData
->PendingAPCs
++;
1887 InterlockedIncrement(&SockProcessPendingAPCCount
);
1890 /* Wait for completition if not overlapped */
1891 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
1893 /* Wait for completion */
1894 ReturnValue
= SockWaitForSingleObject(Event
,
1896 MAYBE_BLOCKING_HOOK
,
1899 /* Check if the wait was successful */
1902 /* Get new status */
1903 Status
= IoStatusBlock
->Status
;
1907 /* Cancel the I/O */
1908 SockCancelIo(Handle
);
1909 Status
= STATUS_IO_TIMEOUT
;
1917 case STATUS_SUCCESS
:
1921 case STATUS_PENDING
:
1922 ErrorCode
= WSA_IO_PENDING
;
1925 /* Other NT Error */
1927 if (!NT_SUCCESS(Status
))
1930 ErrorCode
= NtStatusToSocketError(Status
);
1936 /* Return the number of bytes sent */
1937 *lpNumberOfBytesSent
= PtrToUlong(IoStatusBlock
->Information
);
1941 /* Check if async select was active and this blocked */
1942 if (SockAsyncSelectCalled
&& (ErrorCode
== WSAEWOULDBLOCK
))
1944 /* Get the socket */
1945 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
1949 EnterCriticalSection(&Socket
->Lock
);
1951 /* Re-enable the regular write event */
1952 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
1954 /* Unlock and dereference socket */
1955 LeaveCriticalSection(&Socket
->Lock
);
1956 SockDereferenceSocket(Socket
);
1960 /* Check for error */
1961 if (ErrorCode
!= NO_ERROR
)
1964 *lpErrno
= ErrorCode
;
1965 return SOCKET_ERROR
;
1968 /* Return success */
1974 WSPSendTo(SOCKET Handle
,
1976 DWORD dwBufferCount
,
1977 LPDWORD lpNumberOfBytesSent
,
1979 const struct sockaddr
*SocketAddress
,
1980 INT SocketAddressLength
,
1981 LPWSAOVERLAPPED lpOverlapped
,
1982 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
1983 LPWSATHREADID lpThreadId
,
1986 PIO_STATUS_BLOCK IoStatusBlock
;
1987 IO_STATUS_BLOCK DummyIoStatusBlock
;
1988 AFD_SEND_INFO_UDP SendInfo
;
1993 PWINSOCK_TEB_DATA ThreadData
;
1994 PSOCKET_INFORMATION Socket
;
1997 CHAR AddressBuffer
[FIELD_OFFSET(TDI_ADDRESS_INFO
, Address
) +
1998 MAX_TDI_ADDRESS_LENGTH
];
1999 PTRANSPORT_ADDRESS TdiAddress
= (PTRANSPORT_ADDRESS
)AddressBuffer
;
2000 ULONG TdiAddressSize
;
2003 SOCKADDR_INFO SocketInfo
;
2006 ErrorCode
= SockEnterApiFast(&ThreadData
);
2007 if (ErrorCode
!= NO_ERROR
)
2010 *lpErrno
= ErrorCode
;
2011 return SOCKET_ERROR
;
2014 /* Get the socket structure */
2015 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
2019 ErrorCode
= WSAENOTSOCK
;
2024 * Check if this isn't a datagram socket or if it's a connected socket
2025 * without an address
2027 if (!MSAFD_IS_DGRAM_SOCK(Socket
) ||
2028 ((Socket
->SharedData
.State
== SocketConnected
) &&
2029 (!SocketAddress
|| !SocketAddressLength
)))
2031 /* Call WSPSend instead */
2032 SockDereferenceSocket(Socket
);
2033 return WSPSend(Handle
,
2036 lpNumberOfBytesSent
,
2039 lpCompletionRoutine
,
2044 /* If the socket isn't connected, we need an address*/
2045 if ((Socket
->SharedData
.State
!= SocketConnected
) && (!SocketAddress
))
2048 ErrorCode
= WSAENOTCONN
;
2052 /* Validate length */
2053 if (SocketAddressLength
< Socket
->HelperData
->MaxWSAddressLength
)
2056 ErrorCode
= WSAEFAULT
;
2061 if (iFlags
& ~MSG_DONTROUTE
)
2064 ErrorCode
= WSAEOPNOTSUPP
;
2068 /* Make sure send shutdown isn't active */
2069 if (Socket
->SharedData
.SendShutdown
)
2072 ErrorCode
= WSAESHUTDOWN
;
2076 /* Make sure address families match */
2077 if (Socket
->SharedData
.AddressFamily
!= SocketAddress
->sa_family
)
2080 ErrorCode
= WSAEOPNOTSUPP
;
2084 /* Check if broadcast is enabled */
2085 if (!Socket
->SharedData
.Broadcast
)
2087 /* The caller might want to enable it; get the Sockaddr type */
2088 ErrorCode
= Socket
->HelperData
->WSHGetSockaddrType((PSOCKADDR
)SocketAddress
,
2089 SocketAddressLength
,
2091 if (ErrorCode
!= NO_ERROR
) goto error
;
2093 /* Check if this is a broadcast attempt */
2094 if (SocketInfo
.AddressInfo
== SockaddrAddressInfoBroadcast
)
2096 /* The socket won't allow it */
2097 ErrorCode
= WSAEACCES
;
2102 /* Check if this socket isn't bound yet */
2103 if (Socket
->SharedData
.State
== SocketOpen
)
2105 /* Check if we can request the wildcard address */
2106 if (Socket
->HelperData
->WSHGetWildcardSockaddr
)
2108 /* Allocate a new Sockaddr */
2109 SockaddrLength
= Socket
->HelperData
->MaxWSAddressLength
;
2110 Sockaddr
= SockAllocateHeapRoutine(SockPrivateHeap
, 0, SockaddrLength
);
2114 ErrorCode
= WSAENOBUFS
;
2118 /* Get the wildcard sockaddr */
2119 ErrorCode
= Socket
->HelperData
->WSHGetWildcardSockaddr(Socket
->HelperContext
,
2122 if (ErrorCode
!= NO_ERROR
)
2124 /* Free memory and fail */
2125 RtlFreeHeap(SockPrivateHeap
, 0, Sockaddr
);
2129 /* Lock the socket */
2130 EnterCriticalSection(&Socket
->Lock
);
2132 /* Make sure it's still unbound */
2133 if (Socket
->SharedData
.State
== SocketOpen
)
2136 ReturnValue
= WSPBind(Handle
,
2143 /* It's bound now, fake success */
2144 ReturnValue
= NO_ERROR
;
2147 /* Release the lock and free memory */
2148 LeaveCriticalSection(&Socket
->Lock
);
2149 RtlFreeHeap(SockPrivateHeap
, 0, Sockaddr
);
2151 /* Check if we failed */
2152 if (ReturnValue
== SOCKET_ERROR
) goto error
;
2156 /* Unbound socket, but can't get the wildcard. Fail */
2157 ErrorCode
= WSAEINVAL
;
2162 /* Check how long the TDI Address is */
2163 TdiAddressSize
= Socket
->HelperData
->MaxTDIAddressLength
;
2165 /* See if it can fit in the stack */
2166 if (TdiAddressSize
> sizeof(AddressBuffer
))
2168 /* Allocate from heap */
2169 TdiAddress
= SockAllocateHeapRoutine(SockPrivateHeap
, 0, TdiAddressSize
);
2173 ErrorCode
= WSAENOBUFS
;
2178 /* Build the TDI Address */
2179 ErrorCode
= SockBuildTdiAddress(TdiAddress
,
2180 (PSOCKADDR
)SocketAddress
,
2181 min(SocketAddressLength
,
2182 Socket
->HelperData
->MaxWSAddressLength
));
2183 if (ErrorCode
!= NO_ERROR
) goto error
;
2185 /* Set up the Send Structure */
2186 SendInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
2187 SendInfo
.BufferCount
= dwBufferCount
;
2188 SendInfo
.AfdFlags
= 0;
2189 SendInfo
.TdiConnection
.RemoteAddress
= TdiAddress
;
2190 SendInfo
.TdiConnection
.RemoteAddressLength
= TdiAddressSize
;
2192 /* Verifiy if we should use APC */
2195 /* Not using Overlapped structure, so use normal blocking on event */
2198 Event
= ThreadData
->EventHandle
;
2199 IoStatusBlock
= &DummyIoStatusBlock
;
2203 /* Using apc, check if we have a completion routine */
2204 if (!lpCompletionRoutine
)
2206 /* No need for APC */
2207 APCContext
= lpOverlapped
;
2209 Event
= lpOverlapped
->hEvent
;
2214 ApcFunction
= SockIoCompletion
;
2215 APCContext
= lpCompletionRoutine
;
2219 SendInfo
.AfdFlags
= AFD_SKIP_FIO
;
2222 /* Use the overlapped's structure buffer for the I/O Status Block */
2223 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
2225 /* Make this an overlapped I/O in AFD */
2226 SendInfo
.AfdFlags
|= AFD_OVERLAPPED
;
2229 /* Set is as Pending for now */
2230 IoStatusBlock
->Status
= STATUS_PENDING
;
2233 Status
= NtDeviceIoControlFile(Socket
->WshContext
.Handle
,
2238 IOCTL_AFD_SEND_DATAGRAM
,
2244 /* Increase the pending APC Count if we're using an APC */
2245 if (!NT_ERROR(Status
) && ApcFunction
)
2247 ThreadData
->PendingAPCs
++;
2248 InterlockedIncrement(&SockProcessPendingAPCCount
);
2251 /* Wait for completition if not overlapped */
2252 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
2254 /* Wait for completion */
2255 ReturnValue
= SockWaitForSingleObject(Event
,
2257 MAYBE_BLOCKING_HOOK
,
2260 /* Check if the wait was successful */
2263 /* Get new status */
2264 Status
= IoStatusBlock
->Status
;
2268 /* Cancel the I/O */
2269 SockCancelIo(Handle
);
2270 Status
= STATUS_IO_TIMEOUT
;
2278 case STATUS_SUCCESS
:
2282 case STATUS_PENDING
:
2283 ErrorCode
= WSA_IO_PENDING
;
2286 /* Other NT Error */
2288 if (!NT_SUCCESS(Status
))
2291 ErrorCode
= NtStatusToSocketError(Status
);
2297 /* Return the number of bytes sent */
2298 *lpNumberOfBytesSent
= PtrToUlong(IoStatusBlock
->Information
);
2302 /* Check if we have a socket */
2305 /* Check if async select was active and this blocked */
2306 if (SockAsyncSelectCalled
&& (ErrorCode
== WSAEWOULDBLOCK
))
2309 EnterCriticalSection(&Socket
->Lock
);
2311 /* Re-enable the regular write event */
2312 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
2315 LeaveCriticalSection(&Socket
->Lock
);
2318 /* Dereference socket */
2319 SockDereferenceSocket(Socket
);
2322 /* Check if we should free the TDI Address */
2323 if (TdiAddress
&& (TdiAddress
!= (PVOID
)AddressBuffer
))
2325 /* Free it from the heap */
2326 RtlFreeHeap(SockPrivateHeap
, 0, TdiAddress
);
2329 /* Check for error */
2330 if (ErrorCode
!= NO_ERROR
)
2333 *lpErrno
= ErrorCode
;
2334 return SOCKET_ERROR
;
2337 /* Return success */