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 WSPRecv(SOCKET Handle
,
20 LPDWORD lpNumberOfBytesRead
,
22 LPWSAOVERLAPPED lpOverlapped
,
23 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
24 LPWSATHREADID lpThreadId
,
27 PIO_STATUS_BLOCK IoStatusBlock
;
28 IO_STATUS_BLOCK DummyIoStatusBlock
;
29 AFD_RECV_INFO RecvInfo
;
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 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
50 RecvInfo
.BufferCount
= dwBufferCount
;
51 RecvInfo
.TdiFlags
= 0;
52 RecvInfo
.AfdFlags
= 0;
54 /* Set the TDI Flags */
57 /* Use normal TDI Receive */
58 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
62 /* Check for valid flags */
63 if ((*ReceiveFlags
& ~(MSG_OOB
| MSG_PEEK
| MSG_PARTIAL
)))
66 ErrorCode
= WSAEOPNOTSUPP
;
70 /* Check if OOB is being used */
71 if (*ReceiveFlags
& MSG_OOB
)
73 /* Use Expedited Receive for OOB */
74 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
78 /* Use normal receive */
79 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
82 /* Use Peek Receive if enabled */
83 if (*ReceiveFlags
& MSG_PEEK
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
85 /* Use Partial Receive if enabled */
86 if (*ReceiveFlags
& MSG_PARTIAL
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
89 /* Verifiy if we should use APC */
92 /* Not using Overlapped structure, so use normal blocking on event */
95 Event
= ThreadData
->EventHandle
;
96 IoStatusBlock
= &DummyIoStatusBlock
;
100 /* Using apc, check if we have a completion routine */
101 if (!lpCompletionRoutine
)
103 /* No need for APC */
104 APCContext
= lpOverlapped
;
106 Event
= lpOverlapped
->hEvent
;
111 ApcFunction
= SockIoCompletion
;
112 APCContext
= lpCompletionRoutine
;
116 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
119 /* Use the overlapped's structure buffer for the I/O Status Block */
120 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
122 /* Make this an overlapped I/O in AFD */
123 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
126 /* Set is as Pending for now */
127 IoStatusBlock
->Status
= STATUS_PENDING
;
130 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
141 /* Increase the pending APC Count if we're using an APC */
142 if (!NT_ERROR(Status
) && ApcFunction
)
144 ThreadData
->PendingAPCs
++;
145 InterlockedIncrement(&SockProcessPendingAPCCount
);
148 /* Wait for completition if not overlapped */
149 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
151 /* Wait for completion */
152 ReturnValue
= SockWaitForSingleObject(Event
,
157 /* Check if the wait was successful */
161 Status
= IoStatusBlock
->Status
;
166 SockCancelIo(Handle
);
168 /* Get new status and normalize */
169 Status
= IoStatusBlock
->Status
;
170 if (Status
== STATUS_CANCELLED
) Status
= STATUS_IO_TIMEOUT
;
174 /* Return the Flags */
184 ErrorCode
= WSA_IO_PENDING
;
187 /* Buffer Overflow */
188 case STATUS_BUFFER_OVERFLOW
:
189 /* Check if this was overlapped */
192 /* Return without bytes read */
193 ErrorCode
= WSA_IO_PENDING
;
197 /* Return failure with bytes read */
198 ErrorCode
= WSAEMSGSIZE
;
202 case STATUS_RECEIVE_EXPEDITED
:
203 *ReceiveFlags
= MSG_OOB
;
206 /* Partial OOB Receive */
207 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
208 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
212 case STATUS_RECEIVE_PARTIAL
:
213 *ReceiveFlags
= MSG_PARTIAL
;
218 if (!NT_SUCCESS(Status
))
221 ErrorCode
= NtStatusToSocketError(Status
);
227 /* Return the number of bytes read */
228 *lpNumberOfBytesRead
= PtrToUlong(IoStatusBlock
->Information
);
232 /* Check if async select was active */
233 if (SockAsyncSelectCalled
)
236 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
240 EnterCriticalSection(&Socket
->Lock
);
242 /* Check which event to re-enable */
243 if (RecvInfo
.TdiFlags
& TDI_RECEIVE_EXPEDITED
)
245 /* Re-enable the OOB event */
246 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
250 /* Re-enable the regular read event */
251 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
254 /* Unlock and dereference socket */
255 LeaveCriticalSection(&Socket
->Lock
);
256 SockDereferenceSocket(Socket
);
260 /* Check for error */
261 if (ErrorCode
!= NO_ERROR
)
264 *lpErrno
= ErrorCode
;
274 WSPRecvFrom(SOCKET Handle
,
277 LPDWORD lpNumberOfBytesRead
,
278 LPDWORD ReceiveFlags
,
279 PSOCKADDR SocketAddress
,
280 PINT SocketAddressLength
,
281 LPWSAOVERLAPPED lpOverlapped
,
282 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
283 LPWSATHREADID lpThreadId
,
286 PIO_STATUS_BLOCK IoStatusBlock
;
287 IO_STATUS_BLOCK DummyIoStatusBlock
;
288 AFD_RECV_INFO_UDP RecvInfo
;
293 PWINSOCK_TEB_DATA ThreadData
;
294 PSOCKET_INFORMATION Socket
;
299 ErrorCode
= SockEnterApiFast(&ThreadData
);
300 if (ErrorCode
!= NO_ERROR
)
303 *lpErrno
= ErrorCode
;
308 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
312 ErrorCode
= WSAENOTSOCK
;
316 /* Fail if the socket isn't bound */
317 if (Socket
->SharedData
.State
== SocketOpen
)
320 ErrorCode
= WSAEINVAL
;
324 /* If this is an unconnected or non datagram socket */
325 if (!(MSAFD_IS_DGRAM_SOCK(Socket
)) ||
326 (!SocketAddress
&& !SocketAddressLength
))
329 SockDereferenceSocket(Socket
);
330 return WSPRecv(Handle
,
341 /* If receive shutdown is enabled, fail */
342 if (Socket
->SharedData
.ReceiveShutdown
)
345 ErrorCode
= WSAESHUTDOWN
;
349 /* Check for valid Socket Address (Length) flags */
350 if (!(SocketAddress
) ^ (!SocketAddressLength
|| !(*SocketAddressLength
)))
353 ErrorCode
= WSAEFAULT
;
357 /* Check for valid flags */
358 if ((*ReceiveFlags
& ~(MSG_PEEK
| MSG_PARTIAL
)))
361 ErrorCode
= WSAEOPNOTSUPP
;
365 /* Check that the length is respected */
366 if (SocketAddressLength
&&
367 (*SocketAddressLength
< Socket
->HelperData
->MinWSAddressLength
))
370 ErrorCode
= WSAEFAULT
;
374 /* Set up the Receive Structure */
375 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
376 RecvInfo
.BufferCount
= dwBufferCount
;
377 RecvInfo
.TdiFlags
= TDI_RECEIVE_NORMAL
;
378 RecvInfo
.AfdFlags
= 0;
379 RecvInfo
.Address
= SocketAddress
;
380 RecvInfo
.AddressLength
= SocketAddressLength
;
382 /* Use Peek Receive if enabled */
383 if (*ReceiveFlags
& MSG_PEEK
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
385 /* Use Partial Receive if enabled */
386 if (*ReceiveFlags
& MSG_PARTIAL
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
388 /* Verifiy if we should use APC */
391 /* Not using Overlapped structure, so use normal blocking on event */
394 Event
= ThreadData
->EventHandle
;
395 IoStatusBlock
= &DummyIoStatusBlock
;
399 /* Using apc, check if we have a completion routine */
400 if (!lpCompletionRoutine
)
402 /* No need for APC */
403 APCContext
= lpOverlapped
;
405 Event
= lpOverlapped
->hEvent
;
410 ApcFunction
= SockIoCompletion
;
411 APCContext
= lpCompletionRoutine
;
415 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
418 /* Use the overlapped's structure buffer for the I/O Status Block */
419 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
421 /* Make this an overlapped I/O in AFD */
422 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
425 /* Set is as Pending for now */
426 IoStatusBlock
->Status
= STATUS_PENDING
;
429 Status
= NtDeviceIoControlFile(Socket
->WshContext
.Handle
,
434 IOCTL_AFD_RECV_DATAGRAM
,
440 /* Increase the pending APC Count if we're using an APC */
441 if (!NT_ERROR(Status
) && ApcFunction
)
443 ThreadData
->PendingAPCs
++;
444 InterlockedIncrement(&SockProcessPendingAPCCount
);
447 /* Wait for completition if not overlapped */
448 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
450 /* Wait for completion */
451 ReturnValue
= SockWaitForSingleObject(Event
,
456 /* Check if the wait was successful */
460 Status
= IoStatusBlock
->Status
;
465 SockCancelIo(Handle
);
467 /* Get new status and normalize */
468 Status
= IoStatusBlock
->Status
;
469 if (Status
== STATUS_CANCELLED
) Status
= STATUS_IO_TIMEOUT
;
473 /* Return the Flags */
483 ErrorCode
= WSA_IO_PENDING
;
486 /* Buffer Overflow */
487 case STATUS_BUFFER_OVERFLOW
:
488 /* Check if this was overlapped */
491 /* Return without bytes read */
492 ErrorCode
= WSA_IO_PENDING
;
496 /* Return failure with bytes read */
497 ErrorCode
= WSAEMSGSIZE
;
501 case STATUS_RECEIVE_EXPEDITED
:
502 *ReceiveFlags
= MSG_OOB
;
505 /* Partial OOB Receive */
506 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
507 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
511 case STATUS_RECEIVE_PARTIAL
:
512 *ReceiveFlags
= MSG_PARTIAL
;
517 if (!NT_SUCCESS(Status
))
520 ErrorCode
= NtStatusToSocketError(Status
);
526 /* Return the number of bytes read */
527 *lpNumberOfBytesRead
= PtrToUlong(IoStatusBlock
->Information
);
531 /* Check if we have a socket here */
534 /* Check if async select was active */
535 if (SockAsyncSelectCalled
)
537 /* Lock the socket */
538 EnterCriticalSection(&Socket
->Lock
);
540 /* Re-enable the regular read event */
541 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
544 LeaveCriticalSection(&Socket
->Lock
);
548 SockDereferenceSocket(Socket
);
551 /* Check for error */
552 if (ErrorCode
!= NO_ERROR
)
555 *lpErrno
= ErrorCode
;
564 * COPYRIGHT: See COPYING in the top level directory
565 * PROJECT: ReactOS Winsock 2 SPI
566 * FILE: lib/mswsock/lib/init.c
567 * PURPOSE: DLL Initialization
570 /* INCLUDES ******************************************************************/
573 /* DATA **********************************************************************/
575 /* FUNCTIONS *****************************************************************/
579 WSPRecv(SOCKET Handle
,
582 LPDWORD lpNumberOfBytesRead
,
583 LPDWORD ReceiveFlags
,
584 LPWSAOVERLAPPED lpOverlapped
,
585 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
586 LPWSATHREADID lpThreadId
,
589 PIO_STATUS_BLOCK IoStatusBlock
;
590 IO_STATUS_BLOCK DummyIoStatusBlock
;
591 AFD_RECV_INFO RecvInfo
;
596 PWINSOCK_TEB_DATA ThreadData
;
597 PSOCKET_INFORMATION Socket
;
602 ErrorCode
= SockEnterApiFast(&ThreadData
);
603 if (ErrorCode
!= NO_ERROR
)
606 *lpErrno
= ErrorCode
;
610 /* Set up the Receive Structure */
611 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
612 RecvInfo
.BufferCount
= dwBufferCount
;
613 RecvInfo
.TdiFlags
= 0;
614 RecvInfo
.AfdFlags
= 0;
616 /* Set the TDI Flags */
617 if (!(*ReceiveFlags
))
619 /* Use normal TDI Receive */
620 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
624 /* Check for valid flags */
625 if ((*ReceiveFlags
& ~(MSG_OOB
| MSG_PEEK
| MSG_PARTIAL
)))
628 ErrorCode
= WSAEOPNOTSUPP
;
632 /* Check if OOB is being used */
633 if (*ReceiveFlags
& MSG_OOB
)
635 /* Use Expedited Receive for OOB */
636 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
640 /* Use normal receive */
641 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
644 /* Use Peek Receive if enabled */
645 if (*ReceiveFlags
& MSG_PEEK
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
647 /* Use Partial Receive if enabled */
648 if (*ReceiveFlags
& MSG_PARTIAL
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
651 /* Verifiy if we should use APC */
654 /* Not using Overlapped structure, so use normal blocking on event */
657 Event
= ThreadData
->EventHandle
;
658 IoStatusBlock
= &DummyIoStatusBlock
;
662 /* Using apc, check if we have a completion routine */
663 if (!lpCompletionRoutine
)
665 /* No need for APC */
666 APCContext
= lpOverlapped
;
668 Event
= lpOverlapped
->hEvent
;
673 ApcFunction
= SockIoCompletion
;
674 APCContext
= lpCompletionRoutine
;
678 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
681 /* Use the overlapped's structure buffer for the I/O Status Block */
682 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
684 /* Make this an overlapped I/O in AFD */
685 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
688 /* Set is as Pending for now */
689 IoStatusBlock
->Status
= STATUS_PENDING
;
692 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
703 /* Increase the pending APC Count if we're using an APC */
704 if (!NT_ERROR(Status
) && ApcFunction
)
706 ThreadData
->PendingAPCs
++;
707 InterlockedIncrement(&SockProcessPendingAPCCount
);
710 /* Wait for completition if not overlapped */
711 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
713 /* Wait for completion */
714 ReturnValue
= SockWaitForSingleObject(Event
,
719 /* Check if the wait was successful */
723 Status
= IoStatusBlock
->Status
;
728 SockCancelIo(Handle
);
730 /* Get new status and normalize */
731 Status
= IoStatusBlock
->Status
;
732 if (Status
== STATUS_CANCELLED
) Status
= STATUS_IO_TIMEOUT
;
736 /* Return the Flags */
746 ErrorCode
= WSA_IO_PENDING
;
749 /* Buffer Overflow */
750 case STATUS_BUFFER_OVERFLOW
:
751 /* Check if this was overlapped */
754 /* Return without bytes read */
755 ErrorCode
= WSA_IO_PENDING
;
759 /* Return failure with bytes read */
760 ErrorCode
= WSAEMSGSIZE
;
764 case STATUS_RECEIVE_EXPEDITED
:
765 *ReceiveFlags
= MSG_OOB
;
768 /* Partial OOB Receive */
769 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
770 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
774 case STATUS_RECEIVE_PARTIAL
:
775 *ReceiveFlags
= MSG_PARTIAL
;
780 if (!NT_SUCCESS(Status
))
783 ErrorCode
= NtStatusToSocketError(Status
);
789 /* Return the number of bytes read */
790 *lpNumberOfBytesRead
= PtrToUlong(IoStatusBlock
->Information
);
794 /* Check if async select was active */
795 if (SockAsyncSelectCalled
)
798 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
802 EnterCriticalSection(&Socket
->Lock
);
804 /* Check which event to re-enable */
805 if (RecvInfo
.TdiFlags
& TDI_RECEIVE_EXPEDITED
)
807 /* Re-enable the OOB event */
808 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
812 /* Re-enable the regular read event */
813 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
816 /* Unlock and dereference socket */
817 LeaveCriticalSection(&Socket
->Lock
);
818 SockDereferenceSocket(Socket
);
822 /* Check for error */
823 if (ErrorCode
!= NO_ERROR
)
826 *lpErrno
= ErrorCode
;
836 WSPRecvFrom(SOCKET Handle
,
839 LPDWORD lpNumberOfBytesRead
,
840 LPDWORD ReceiveFlags
,
841 PSOCKADDR SocketAddress
,
842 PINT SocketAddressLength
,
843 LPWSAOVERLAPPED lpOverlapped
,
844 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
845 LPWSATHREADID lpThreadId
,
848 PIO_STATUS_BLOCK IoStatusBlock
;
849 IO_STATUS_BLOCK DummyIoStatusBlock
;
850 AFD_RECV_INFO_UDP RecvInfo
;
855 PWINSOCK_TEB_DATA ThreadData
;
856 PSOCKET_INFORMATION Socket
;
861 ErrorCode
= SockEnterApiFast(&ThreadData
);
862 if (ErrorCode
!= NO_ERROR
)
865 *lpErrno
= ErrorCode
;
870 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
874 ErrorCode
= WSAENOTSOCK
;
878 /* Fail if the socket isn't bound */
879 if (Socket
->SharedData
.State
== SocketOpen
)
882 ErrorCode
= WSAEINVAL
;
886 /* If this is an unconnected or non datagram socket */
887 if (!(MSAFD_IS_DGRAM_SOCK(Socket
)) ||
888 (!SocketAddress
&& !SocketAddressLength
))
891 SockDereferenceSocket(Socket
);
892 return WSPRecv(Handle
,
903 /* If receive shutdown is enabled, fail */
904 if (Socket
->SharedData
.ReceiveShutdown
)
907 ErrorCode
= WSAESHUTDOWN
;
911 /* Check for valid Socket Address (Length) flags */
912 if (!(SocketAddress
) ^ (!SocketAddressLength
|| !(*SocketAddressLength
)))
915 ErrorCode
= WSAEFAULT
;
919 /* Check for valid flags */
920 if ((*ReceiveFlags
& ~(MSG_PEEK
| MSG_PARTIAL
)))
923 ErrorCode
= WSAEOPNOTSUPP
;
927 /* Check that the length is respected */
928 if (SocketAddressLength
&&
929 (*SocketAddressLength
< Socket
->HelperData
->MinWSAddressLength
))
932 ErrorCode
= WSAEFAULT
;
936 /* Set up the Receive Structure */
937 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
938 RecvInfo
.BufferCount
= dwBufferCount
;
939 RecvInfo
.TdiFlags
= TDI_RECEIVE_NORMAL
;
940 RecvInfo
.AfdFlags
= 0;
941 RecvInfo
.Address
= SocketAddress
;
942 RecvInfo
.AddressLength
= SocketAddressLength
;
944 /* Use Peek Receive if enabled */
945 if (*ReceiveFlags
& MSG_PEEK
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
947 /* Use Partial Receive if enabled */
948 if (*ReceiveFlags
& MSG_PARTIAL
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
950 /* Verifiy if we should use APC */
953 /* Not using Overlapped structure, so use normal blocking on event */
956 Event
= ThreadData
->EventHandle
;
957 IoStatusBlock
= &DummyIoStatusBlock
;
961 /* Using apc, check if we have a completion routine */
962 if (!lpCompletionRoutine
)
964 /* No need for APC */
965 APCContext
= lpOverlapped
;
967 Event
= lpOverlapped
->hEvent
;
972 ApcFunction
= SockIoCompletion
;
973 APCContext
= lpCompletionRoutine
;
977 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
980 /* Use the overlapped's structure buffer for the I/O Status Block */
981 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
983 /* Make this an overlapped I/O in AFD */
984 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
987 /* Set is as Pending for now */
988 IoStatusBlock
->Status
= STATUS_PENDING
;
991 Status
= NtDeviceIoControlFile(Socket
->WshContext
.Handle
,
996 IOCTL_AFD_RECV_DATAGRAM
,
1002 /* Increase the pending APC Count if we're using an APC */
1003 if (!NT_ERROR(Status
) && ApcFunction
)
1005 ThreadData
->PendingAPCs
++;
1006 InterlockedIncrement(&SockProcessPendingAPCCount
);
1009 /* Wait for completition if not overlapped */
1010 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
1012 /* Wait for completion */
1013 ReturnValue
= SockWaitForSingleObject(Event
,
1015 MAYBE_BLOCKING_HOOK
,
1018 /* Check if the wait was successful */
1021 /* Get new status */
1022 Status
= IoStatusBlock
->Status
;
1026 /* Cancel the I/O */
1027 SockCancelIo(Handle
);
1029 /* Get new status and normalize */
1030 Status
= IoStatusBlock
->Status
;
1031 if (Status
== STATUS_CANCELLED
) Status
= STATUS_IO_TIMEOUT
;
1035 /* Return the Flags */
1040 case STATUS_SUCCESS
:
1044 case STATUS_PENDING
:
1045 ErrorCode
= WSA_IO_PENDING
;
1048 /* Buffer Overflow */
1049 case STATUS_BUFFER_OVERFLOW
:
1050 /* Check if this was overlapped */
1053 /* Return without bytes read */
1054 ErrorCode
= WSA_IO_PENDING
;
1058 /* Return failure with bytes read */
1059 ErrorCode
= WSAEMSGSIZE
;
1063 case STATUS_RECEIVE_EXPEDITED
:
1064 *ReceiveFlags
= MSG_OOB
;
1067 /* Partial OOB Receive */
1068 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
1069 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
1072 /* Parial Receive */
1073 case STATUS_RECEIVE_PARTIAL
:
1074 *ReceiveFlags
= MSG_PARTIAL
;
1077 /* Other NT Error */
1079 if (!NT_SUCCESS(Status
))
1082 ErrorCode
= NtStatusToSocketError(Status
);
1088 /* Return the number of bytes read */
1089 *lpNumberOfBytesRead
= PtrToUlong(IoStatusBlock
->Information
);
1093 /* Check if we have a socket here */
1096 /* Check if async select was active */
1097 if (SockAsyncSelectCalled
)
1099 /* Lock the socket */
1100 EnterCriticalSection(&Socket
->Lock
);
1102 /* Re-enable the regular read event */
1103 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
1106 LeaveCriticalSection(&Socket
->Lock
);
1109 /* Dereference it */
1110 SockDereferenceSocket(Socket
);
1113 /* Check for error */
1114 if (ErrorCode
!= NO_ERROR
)
1117 *lpErrno
= ErrorCode
;
1118 return SOCKET_ERROR
;
1121 /* Return success */
1126 * COPYRIGHT: See COPYING in the top level directory
1127 * PROJECT: ReactOS Winsock 2 SPI
1128 * FILE: lib/mswsock/lib/init.c
1129 * PURPOSE: DLL Initialization
1132 /* INCLUDES ******************************************************************/
1135 /* DATA **********************************************************************/
1137 /* FUNCTIONS *****************************************************************/
1141 WSPRecv(SOCKET Handle
,
1143 DWORD dwBufferCount
,
1144 LPDWORD lpNumberOfBytesRead
,
1145 LPDWORD ReceiveFlags
,
1146 LPWSAOVERLAPPED lpOverlapped
,
1147 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
1148 LPWSATHREADID lpThreadId
,
1151 PIO_STATUS_BLOCK IoStatusBlock
;
1152 IO_STATUS_BLOCK DummyIoStatusBlock
;
1153 AFD_RECV_INFO RecvInfo
;
1158 PWINSOCK_TEB_DATA ThreadData
;
1159 PSOCKET_INFORMATION Socket
;
1161 BOOLEAN ReturnValue
;
1164 ErrorCode
= SockEnterApiFast(&ThreadData
);
1165 if (ErrorCode
!= NO_ERROR
)
1168 *lpErrno
= ErrorCode
;
1169 return SOCKET_ERROR
;
1172 /* Set up the Receive Structure */
1173 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
1174 RecvInfo
.BufferCount
= dwBufferCount
;
1175 RecvInfo
.TdiFlags
= 0;
1176 RecvInfo
.AfdFlags
= 0;
1178 /* Set the TDI Flags */
1179 if (!(*ReceiveFlags
))
1181 /* Use normal TDI Receive */
1182 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
1186 /* Check for valid flags */
1187 if ((*ReceiveFlags
& ~(MSG_OOB
| MSG_PEEK
| MSG_PARTIAL
)))
1190 ErrorCode
= WSAEOPNOTSUPP
;
1194 /* Check if OOB is being used */
1195 if (*ReceiveFlags
& MSG_OOB
)
1197 /* Use Expedited Receive for OOB */
1198 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
1202 /* Use normal receive */
1203 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
1206 /* Use Peek Receive if enabled */
1207 if (*ReceiveFlags
& MSG_PEEK
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
1209 /* Use Partial Receive if enabled */
1210 if (*ReceiveFlags
& MSG_PARTIAL
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
1213 /* Verifiy if we should use APC */
1216 /* Not using Overlapped structure, so use normal blocking on event */
1219 Event
= ThreadData
->EventHandle
;
1220 IoStatusBlock
= &DummyIoStatusBlock
;
1224 /* Using apc, check if we have a completion routine */
1225 if (!lpCompletionRoutine
)
1227 /* No need for APC */
1228 APCContext
= lpOverlapped
;
1230 Event
= lpOverlapped
->hEvent
;
1235 ApcFunction
= SockIoCompletion
;
1236 APCContext
= lpCompletionRoutine
;
1240 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
1243 /* Use the overlapped's structure buffer for the I/O Status Block */
1244 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
1246 /* Make this an overlapped I/O in AFD */
1247 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
1250 /* Set is as Pending for now */
1251 IoStatusBlock
->Status
= STATUS_PENDING
;
1254 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
1265 /* Increase the pending APC Count if we're using an APC */
1266 if (!NT_ERROR(Status
) && ApcFunction
)
1268 ThreadData
->PendingAPCs
++;
1269 InterlockedIncrement(&SockProcessPendingAPCCount
);
1272 /* Wait for completition if not overlapped */
1273 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
1275 /* Wait for completion */
1276 ReturnValue
= SockWaitForSingleObject(Event
,
1278 MAYBE_BLOCKING_HOOK
,
1281 /* Check if the wait was successful */
1284 /* Get new status */
1285 Status
= IoStatusBlock
->Status
;
1289 /* Cancel the I/O */
1290 SockCancelIo(Handle
);
1292 /* Get new status and normalize */
1293 Status
= IoStatusBlock
->Status
;
1294 if (Status
== STATUS_CANCELLED
) Status
= STATUS_IO_TIMEOUT
;
1298 /* Return the Flags */
1303 case STATUS_SUCCESS
:
1307 case STATUS_PENDING
:
1308 ErrorCode
= WSA_IO_PENDING
;
1311 /* Buffer Overflow */
1312 case STATUS_BUFFER_OVERFLOW
:
1313 /* Check if this was overlapped */
1316 /* Return without bytes read */
1317 ErrorCode
= WSA_IO_PENDING
;
1321 /* Return failure with bytes read */
1322 ErrorCode
= WSAEMSGSIZE
;
1326 case STATUS_RECEIVE_EXPEDITED
:
1327 *ReceiveFlags
= MSG_OOB
;
1330 /* Partial OOB Receive */
1331 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
1332 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
1335 /* Parial Receive */
1336 case STATUS_RECEIVE_PARTIAL
:
1337 *ReceiveFlags
= MSG_PARTIAL
;
1340 /* Other NT Error */
1342 if (!NT_SUCCESS(Status
))
1345 ErrorCode
= NtStatusToSocketError(Status
);
1351 /* Return the number of bytes read */
1352 *lpNumberOfBytesRead
= PtrToUlong(IoStatusBlock
->Information
);
1356 /* Check if async select was active */
1357 if (SockAsyncSelectCalled
)
1359 /* Get the socket */
1360 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
1364 EnterCriticalSection(&Socket
->Lock
);
1366 /* Check which event to re-enable */
1367 if (RecvInfo
.TdiFlags
& TDI_RECEIVE_EXPEDITED
)
1369 /* Re-enable the OOB event */
1370 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
1374 /* Re-enable the regular read event */
1375 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
1378 /* Unlock and dereference socket */
1379 LeaveCriticalSection(&Socket
->Lock
);
1380 SockDereferenceSocket(Socket
);
1384 /* Check for error */
1385 if (ErrorCode
!= NO_ERROR
)
1388 *lpErrno
= ErrorCode
;
1389 return SOCKET_ERROR
;
1392 /* Return success */
1398 WSPRecvFrom(SOCKET Handle
,
1400 DWORD dwBufferCount
,
1401 LPDWORD lpNumberOfBytesRead
,
1402 LPDWORD ReceiveFlags
,
1403 PSOCKADDR SocketAddress
,
1404 PINT SocketAddressLength
,
1405 LPWSAOVERLAPPED lpOverlapped
,
1406 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
1407 LPWSATHREADID lpThreadId
,
1410 PIO_STATUS_BLOCK IoStatusBlock
;
1411 IO_STATUS_BLOCK DummyIoStatusBlock
;
1412 AFD_RECV_INFO_UDP RecvInfo
;
1417 PWINSOCK_TEB_DATA ThreadData
;
1418 PSOCKET_INFORMATION Socket
;
1420 BOOLEAN ReturnValue
;
1423 ErrorCode
= SockEnterApiFast(&ThreadData
);
1424 if (ErrorCode
!= NO_ERROR
)
1427 *lpErrno
= ErrorCode
;
1428 return SOCKET_ERROR
;
1431 /* Get the socket */
1432 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
1436 ErrorCode
= WSAENOTSOCK
;
1440 /* Fail if the socket isn't bound */
1441 if (Socket
->SharedData
.State
== SocketOpen
)
1444 ErrorCode
= WSAEINVAL
;
1448 /* If this is an unconnected or non datagram socket */
1449 if (!(MSAFD_IS_DGRAM_SOCK(Socket
)) ||
1450 (!SocketAddress
&& !SocketAddressLength
))
1453 SockDereferenceSocket(Socket
);
1454 return WSPRecv(Handle
,
1457 lpNumberOfBytesRead
,
1460 lpCompletionRoutine
,
1465 /* If receive shutdown is enabled, fail */
1466 if (Socket
->SharedData
.ReceiveShutdown
)
1469 ErrorCode
= WSAESHUTDOWN
;
1473 /* Check for valid Socket Address (Length) flags */
1474 if (!(SocketAddress
) ^ (!SocketAddressLength
|| !(*SocketAddressLength
)))
1477 ErrorCode
= WSAEFAULT
;
1481 /* Check for valid flags */
1482 if ((*ReceiveFlags
& ~(MSG_PEEK
| MSG_PARTIAL
)))
1485 ErrorCode
= WSAEOPNOTSUPP
;
1489 /* Check that the length is respected */
1490 if (SocketAddressLength
&&
1491 (*SocketAddressLength
< Socket
->HelperData
->MinWSAddressLength
))
1494 ErrorCode
= WSAEFAULT
;
1498 /* Set up the Receive Structure */
1499 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
1500 RecvInfo
.BufferCount
= dwBufferCount
;
1501 RecvInfo
.TdiFlags
= TDI_RECEIVE_NORMAL
;
1502 RecvInfo
.AfdFlags
= 0;
1503 RecvInfo
.Address
= SocketAddress
;
1504 RecvInfo
.AddressLength
= SocketAddressLength
;
1506 /* Use Peek Receive if enabled */
1507 if (*ReceiveFlags
& MSG_PEEK
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
1509 /* Use Partial Receive if enabled */
1510 if (*ReceiveFlags
& MSG_PARTIAL
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
1512 /* Verifiy if we should use APC */
1515 /* Not using Overlapped structure, so use normal blocking on event */
1518 Event
= ThreadData
->EventHandle
;
1519 IoStatusBlock
= &DummyIoStatusBlock
;
1523 /* Using apc, check if we have a completion routine */
1524 if (!lpCompletionRoutine
)
1526 /* No need for APC */
1527 APCContext
= lpOverlapped
;
1529 Event
= lpOverlapped
->hEvent
;
1534 ApcFunction
= SockIoCompletion
;
1535 APCContext
= lpCompletionRoutine
;
1539 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
1542 /* Use the overlapped's structure buffer for the I/O Status Block */
1543 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
1545 /* Make this an overlapped I/O in AFD */
1546 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
1549 /* Set is as Pending for now */
1550 IoStatusBlock
->Status
= STATUS_PENDING
;
1553 Status
= NtDeviceIoControlFile(Socket
->WshContext
.Handle
,
1558 IOCTL_AFD_RECV_DATAGRAM
,
1564 /* Increase the pending APC Count if we're using an APC */
1565 if (!NT_ERROR(Status
) && ApcFunction
)
1567 ThreadData
->PendingAPCs
++;
1568 InterlockedIncrement(&SockProcessPendingAPCCount
);
1571 /* Wait for completition if not overlapped */
1572 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
1574 /* Wait for completion */
1575 ReturnValue
= SockWaitForSingleObject(Event
,
1577 MAYBE_BLOCKING_HOOK
,
1580 /* Check if the wait was successful */
1583 /* Get new status */
1584 Status
= IoStatusBlock
->Status
;
1588 /* Cancel the I/O */
1589 SockCancelIo(Handle
);
1591 /* Get new status and normalize */
1592 Status
= IoStatusBlock
->Status
;
1593 if (Status
== STATUS_CANCELLED
) Status
= STATUS_IO_TIMEOUT
;
1597 /* Return the Flags */
1602 case STATUS_SUCCESS
:
1606 case STATUS_PENDING
:
1607 ErrorCode
= WSA_IO_PENDING
;
1610 /* Buffer Overflow */
1611 case STATUS_BUFFER_OVERFLOW
:
1612 /* Check if this was overlapped */
1615 /* Return without bytes read */
1616 ErrorCode
= WSA_IO_PENDING
;
1620 /* Return failure with bytes read */
1621 ErrorCode
= WSAEMSGSIZE
;
1625 case STATUS_RECEIVE_EXPEDITED
:
1626 *ReceiveFlags
= MSG_OOB
;
1629 /* Partial OOB Receive */
1630 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
1631 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
1634 /* Parial Receive */
1635 case STATUS_RECEIVE_PARTIAL
:
1636 *ReceiveFlags
= MSG_PARTIAL
;
1639 /* Other NT Error */
1641 if (!NT_SUCCESS(Status
))
1644 ErrorCode
= NtStatusToSocketError(Status
);
1650 /* Return the number of bytes read */
1651 *lpNumberOfBytesRead
= PtrToUlong(IoStatusBlock
->Information
);
1655 /* Check if we have a socket here */
1658 /* Check if async select was active */
1659 if (SockAsyncSelectCalled
)
1661 /* Lock the socket */
1662 EnterCriticalSection(&Socket
->Lock
);
1664 /* Re-enable the regular read event */
1665 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
1668 LeaveCriticalSection(&Socket
->Lock
);
1671 /* Dereference it */
1672 SockDereferenceSocket(Socket
);
1675 /* Check for error */
1676 if (ErrorCode
!= NO_ERROR
)
1679 *lpErrno
= ErrorCode
;
1680 return SOCKET_ERROR
;
1683 /* Return success */
1688 * COPYRIGHT: See COPYING in the top level directory
1689 * PROJECT: ReactOS Winsock 2 SPI
1690 * FILE: lib/mswsock/lib/init.c
1691 * PURPOSE: DLL Initialization
1694 /* INCLUDES ******************************************************************/
1697 /* DATA **********************************************************************/
1699 /* FUNCTIONS *****************************************************************/
1703 WSPRecv(SOCKET Handle
,
1705 DWORD dwBufferCount
,
1706 LPDWORD lpNumberOfBytesRead
,
1707 LPDWORD ReceiveFlags
,
1708 LPWSAOVERLAPPED lpOverlapped
,
1709 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
1710 LPWSATHREADID lpThreadId
,
1713 PIO_STATUS_BLOCK IoStatusBlock
;
1714 IO_STATUS_BLOCK DummyIoStatusBlock
;
1715 AFD_RECV_INFO RecvInfo
;
1720 PWINSOCK_TEB_DATA ThreadData
;
1721 PSOCKET_INFORMATION Socket
;
1723 BOOLEAN ReturnValue
;
1726 ErrorCode
= SockEnterApiFast(&ThreadData
);
1727 if (ErrorCode
!= NO_ERROR
)
1730 *lpErrno
= ErrorCode
;
1731 return SOCKET_ERROR
;
1734 /* Set up the Receive Structure */
1735 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
1736 RecvInfo
.BufferCount
= dwBufferCount
;
1737 RecvInfo
.TdiFlags
= 0;
1738 RecvInfo
.AfdFlags
= 0;
1740 /* Set the TDI Flags */
1741 if (!(*ReceiveFlags
))
1743 /* Use normal TDI Receive */
1744 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
1748 /* Check for valid flags */
1749 if ((*ReceiveFlags
& ~(MSG_OOB
| MSG_PEEK
| MSG_PARTIAL
)))
1752 ErrorCode
= WSAEOPNOTSUPP
;
1756 /* Check if OOB is being used */
1757 if (*ReceiveFlags
& MSG_OOB
)
1759 /* Use Expedited Receive for OOB */
1760 RecvInfo
.TdiFlags
|= TDI_RECEIVE_EXPEDITED
;
1764 /* Use normal receive */
1765 RecvInfo
.TdiFlags
|= TDI_RECEIVE_NORMAL
;
1768 /* Use Peek Receive if enabled */
1769 if (*ReceiveFlags
& MSG_PEEK
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
1771 /* Use Partial Receive if enabled */
1772 if (*ReceiveFlags
& MSG_PARTIAL
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
1775 /* Verifiy if we should use APC */
1778 /* Not using Overlapped structure, so use normal blocking on event */
1781 Event
= ThreadData
->EventHandle
;
1782 IoStatusBlock
= &DummyIoStatusBlock
;
1786 /* Using apc, check if we have a completion routine */
1787 if (!lpCompletionRoutine
)
1789 /* No need for APC */
1790 APCContext
= lpOverlapped
;
1792 Event
= lpOverlapped
->hEvent
;
1797 ApcFunction
= SockIoCompletion
;
1798 APCContext
= lpCompletionRoutine
;
1802 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
1805 /* Use the overlapped's structure buffer for the I/O Status Block */
1806 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
1808 /* Make this an overlapped I/O in AFD */
1809 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
1812 /* Set is as Pending for now */
1813 IoStatusBlock
->Status
= STATUS_PENDING
;
1816 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
1827 /* Increase the pending APC Count if we're using an APC */
1828 if (!NT_ERROR(Status
) && ApcFunction
)
1830 ThreadData
->PendingAPCs
++;
1831 InterlockedIncrement(&SockProcessPendingAPCCount
);
1834 /* Wait for completition if not overlapped */
1835 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
1837 /* Wait for completion */
1838 ReturnValue
= SockWaitForSingleObject(Event
,
1840 MAYBE_BLOCKING_HOOK
,
1843 /* Check if the wait was successful */
1846 /* Get new status */
1847 Status
= IoStatusBlock
->Status
;
1851 /* Cancel the I/O */
1852 SockCancelIo(Handle
);
1854 /* Get new status and normalize */
1855 Status
= IoStatusBlock
->Status
;
1856 if (Status
== STATUS_CANCELLED
) Status
= STATUS_IO_TIMEOUT
;
1860 /* Return the Flags */
1865 case STATUS_SUCCESS
:
1869 case STATUS_PENDING
:
1870 ErrorCode
= WSA_IO_PENDING
;
1873 /* Buffer Overflow */
1874 case STATUS_BUFFER_OVERFLOW
:
1875 /* Check if this was overlapped */
1878 /* Return without bytes read */
1879 ErrorCode
= WSA_IO_PENDING
;
1883 /* Return failure with bytes read */
1884 ErrorCode
= WSAEMSGSIZE
;
1888 case STATUS_RECEIVE_EXPEDITED
:
1889 *ReceiveFlags
= MSG_OOB
;
1892 /* Partial OOB Receive */
1893 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
1894 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
1897 /* Parial Receive */
1898 case STATUS_RECEIVE_PARTIAL
:
1899 *ReceiveFlags
= MSG_PARTIAL
;
1902 /* Other NT Error */
1904 if (!NT_SUCCESS(Status
))
1907 ErrorCode
= NtStatusToSocketError(Status
);
1913 /* Return the number of bytes read */
1914 *lpNumberOfBytesRead
= PtrToUlong(IoStatusBlock
->Information
);
1918 /* Check if async select was active */
1919 if (SockAsyncSelectCalled
)
1921 /* Get the socket */
1922 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
1926 EnterCriticalSection(&Socket
->Lock
);
1928 /* Check which event to re-enable */
1929 if (RecvInfo
.TdiFlags
& TDI_RECEIVE_EXPEDITED
)
1931 /* Re-enable the OOB event */
1932 SockReenableAsyncSelectEvent(Socket
, FD_OOB
);
1936 /* Re-enable the regular read event */
1937 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
1940 /* Unlock and dereference socket */
1941 LeaveCriticalSection(&Socket
->Lock
);
1942 SockDereferenceSocket(Socket
);
1946 /* Check for error */
1947 if (ErrorCode
!= NO_ERROR
)
1950 *lpErrno
= ErrorCode
;
1951 return SOCKET_ERROR
;
1954 /* Return success */
1960 WSPRecvFrom(SOCKET Handle
,
1962 DWORD dwBufferCount
,
1963 LPDWORD lpNumberOfBytesRead
,
1964 LPDWORD ReceiveFlags
,
1965 PSOCKADDR SocketAddress
,
1966 PINT SocketAddressLength
,
1967 LPWSAOVERLAPPED lpOverlapped
,
1968 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
1969 LPWSATHREADID lpThreadId
,
1972 PIO_STATUS_BLOCK IoStatusBlock
;
1973 IO_STATUS_BLOCK DummyIoStatusBlock
;
1974 AFD_RECV_INFO_UDP RecvInfo
;
1979 PWINSOCK_TEB_DATA ThreadData
;
1980 PSOCKET_INFORMATION Socket
;
1982 BOOLEAN ReturnValue
;
1985 ErrorCode
= SockEnterApiFast(&ThreadData
);
1986 if (ErrorCode
!= NO_ERROR
)
1989 *lpErrno
= ErrorCode
;
1990 return SOCKET_ERROR
;
1993 /* Get the socket */
1994 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
1998 ErrorCode
= WSAENOTSOCK
;
2002 /* Fail if the socket isn't bound */
2003 if (Socket
->SharedData
.State
== SocketOpen
)
2006 ErrorCode
= WSAEINVAL
;
2010 /* If this is an unconnected or non datagram socket */
2011 if (!(MSAFD_IS_DGRAM_SOCK(Socket
)) ||
2012 (!SocketAddress
&& !SocketAddressLength
))
2015 SockDereferenceSocket(Socket
);
2016 return WSPRecv(Handle
,
2019 lpNumberOfBytesRead
,
2022 lpCompletionRoutine
,
2027 /* If receive shutdown is enabled, fail */
2028 if (Socket
->SharedData
.ReceiveShutdown
)
2031 ErrorCode
= WSAESHUTDOWN
;
2035 /* Check for valid Socket Address (Length) flags */
2036 if (!(SocketAddress
) ^ (!SocketAddressLength
|| !(*SocketAddressLength
)))
2039 ErrorCode
= WSAEFAULT
;
2043 /* Check for valid flags */
2044 if ((*ReceiveFlags
& ~(MSG_PEEK
| MSG_PARTIAL
)))
2047 ErrorCode
= WSAEOPNOTSUPP
;
2051 /* Check that the length is respected */
2052 if (SocketAddressLength
&&
2053 (*SocketAddressLength
< Socket
->HelperData
->MinWSAddressLength
))
2056 ErrorCode
= WSAEFAULT
;
2060 /* Set up the Receive Structure */
2061 RecvInfo
.BufferArray
= (PAFD_WSABUF
)lpBuffers
;
2062 RecvInfo
.BufferCount
= dwBufferCount
;
2063 RecvInfo
.TdiFlags
= TDI_RECEIVE_NORMAL
;
2064 RecvInfo
.AfdFlags
= 0;
2065 RecvInfo
.Address
= SocketAddress
;
2066 RecvInfo
.AddressLength
= SocketAddressLength
;
2068 /* Use Peek Receive if enabled */
2069 if (*ReceiveFlags
& MSG_PEEK
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PEEK
;
2071 /* Use Partial Receive if enabled */
2072 if (*ReceiveFlags
& MSG_PARTIAL
) RecvInfo
.TdiFlags
|= TDI_RECEIVE_PARTIAL
;
2074 /* Verifiy if we should use APC */
2077 /* Not using Overlapped structure, so use normal blocking on event */
2080 Event
= ThreadData
->EventHandle
;
2081 IoStatusBlock
= &DummyIoStatusBlock
;
2085 /* Using apc, check if we have a completion routine */
2086 if (!lpCompletionRoutine
)
2088 /* No need for APC */
2089 APCContext
= lpOverlapped
;
2091 Event
= lpOverlapped
->hEvent
;
2096 ApcFunction
= SockIoCompletion
;
2097 APCContext
= lpCompletionRoutine
;
2101 RecvInfo
.AfdFlags
= AFD_SKIP_FIO
;
2104 /* Use the overlapped's structure buffer for the I/O Status Block */
2105 IoStatusBlock
= (PIO_STATUS_BLOCK
)&lpOverlapped
->Internal
;
2107 /* Make this an overlapped I/O in AFD */
2108 RecvInfo
.AfdFlags
|= AFD_OVERLAPPED
;
2111 /* Set is as Pending for now */
2112 IoStatusBlock
->Status
= STATUS_PENDING
;
2115 Status
= NtDeviceIoControlFile(Socket
->WshContext
.Handle
,
2120 IOCTL_AFD_RECV_DATAGRAM
,
2126 /* Increase the pending APC Count if we're using an APC */
2127 if (!NT_ERROR(Status
) && ApcFunction
)
2129 ThreadData
->PendingAPCs
++;
2130 InterlockedIncrement(&SockProcessPendingAPCCount
);
2133 /* Wait for completition if not overlapped */
2134 if ((Status
== STATUS_PENDING
) && !(lpOverlapped
))
2136 /* Wait for completion */
2137 ReturnValue
= SockWaitForSingleObject(Event
,
2139 MAYBE_BLOCKING_HOOK
,
2142 /* Check if the wait was successful */
2145 /* Get new status */
2146 Status
= IoStatusBlock
->Status
;
2150 /* Cancel the I/O */
2151 SockCancelIo(Handle
);
2153 /* Get new status and normalize */
2154 Status
= IoStatusBlock
->Status
;
2155 if (Status
== STATUS_CANCELLED
) Status
= STATUS_IO_TIMEOUT
;
2159 /* Return the Flags */
2164 case STATUS_SUCCESS
:
2168 case STATUS_PENDING
:
2169 ErrorCode
= WSA_IO_PENDING
;
2172 /* Buffer Overflow */
2173 case STATUS_BUFFER_OVERFLOW
:
2174 /* Check if this was overlapped */
2177 /* Return without bytes read */
2178 ErrorCode
= WSA_IO_PENDING
;
2182 /* Return failure with bytes read */
2183 ErrorCode
= WSAEMSGSIZE
;
2187 case STATUS_RECEIVE_EXPEDITED
:
2188 *ReceiveFlags
= MSG_OOB
;
2191 /* Partial OOB Receive */
2192 case STATUS_RECEIVE_PARTIAL_EXPEDITED
:
2193 *ReceiveFlags
= MSG_PARTIAL
| MSG_OOB
;
2196 /* Parial Receive */
2197 case STATUS_RECEIVE_PARTIAL
:
2198 *ReceiveFlags
= MSG_PARTIAL
;
2201 /* Other NT Error */
2203 if (!NT_SUCCESS(Status
))
2206 ErrorCode
= NtStatusToSocketError(Status
);
2212 /* Return the number of bytes read */
2213 *lpNumberOfBytesRead
= PtrToUlong(IoStatusBlock
->Information
);
2217 /* Check if we have a socket here */
2220 /* Check if async select was active */
2221 if (SockAsyncSelectCalled
)
2223 /* Lock the socket */
2224 EnterCriticalSection(&Socket
->Lock
);
2226 /* Re-enable the regular read event */
2227 SockReenableAsyncSelectEvent(Socket
, FD_READ
);
2230 LeaveCriticalSection(&Socket
->Lock
);
2233 /* Dereference it */
2234 SockDereferenceSocket(Socket
);
2237 /* Check for error */
2238 if (ErrorCode
!= NO_ERROR
)
2241 *lpErrno
= ErrorCode
;
2242 return SOCKET_ERROR
;
2245 /* Return success */