xref: /reactos/dll/win32/ws2_32/src/select.c (revision 53221834)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS WinSock 2 API
4  * FILE:        dll/win32/ws2_32/src/select.c
5  * PURPOSE:     Socket Select Support
6  * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ws2_32.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* FUNCTIONS *****************************************************************/
17 
18 /*
19  * @implemented
20  */
21 INT
22 WSPAPI
23 __WSAFDIsSet(SOCKET s,
24              LPFD_SET set)
25 {
26     INT i = set->fd_count;
27     INT Return = FALSE;
28 
29     /* Loop until a match is found */
30     while (i--) if (set->fd_array[i] == s) Return = TRUE;
31 
32     /* Return */
33     return Return;
34 }
35 
36 /*
37  * @implemented
38  */
39 INT
40 WSAAPI
41 select(IN INT s,
42        IN OUT LPFD_SET readfds,
43        IN OUT LPFD_SET writefds,
44        IN OUT LPFD_SET exceptfds,
45        IN CONST struct timeval *timeout)
46 {
47     PWSSOCKET Socket;
48     INT Status;
49     INT ErrorCode;
50     SOCKET Handle;
51     LPWSPSELECT WSPSelect;
52 
53     DPRINT("select: %lx %p %p %p %p\n", s, readfds, writefds, exceptfds, timeout);
54 
55     /* Check for WSAStartup */
56     ErrorCode = WsQuickProlog();
57 
58     if (ErrorCode != ERROR_SUCCESS)
59     {
60         SetLastError(ErrorCode);
61         return SOCKET_ERROR;
62     }
63 
64     /* Use the first Socket from the first valid set */
65     if (readfds && readfds->fd_count)
66     {
67         Handle = readfds->fd_array[0];
68     }
69     else if (writefds && writefds->fd_count)
70     {
71         Handle = writefds->fd_array[0];
72     }
73     else if (exceptfds && exceptfds->fd_count)
74     {
75         Handle = exceptfds->fd_array[0];
76     }
77     else
78     {
79         /* Invalid handles */
80         SetLastError(WSAEINVAL);
81         return SOCKET_ERROR;
82     }
83 
84     /* Get the Socket Context */
85     Socket = WsSockGetSocket(Handle);
86 
87     if (!Socket)
88     {
89         /* No Socket Context Found */
90         SetLastError(WSAENOTSOCK);
91         return SOCKET_ERROR;
92     }
93 
94     /* Get the select procedure */
95     WSPSelect = Socket->Provider->Service.lpWSPSelect;
96 
97     /* Make the call */
98     Status = WSPSelect(s, readfds, writefds, exceptfds, (struct timeval *)timeout,
99                        &ErrorCode);
100 
101     /* Deference the Socket Context */
102     WsSockDereference(Socket);
103 
104     /* Return Provider Value */
105     if (Status != SOCKET_ERROR)
106         return Status;
107 
108     /* If everything seemed fine, then the WSP call failed itself */
109     if (ErrorCode == NO_ERROR)
110         ErrorCode = WSASYSCALLFAILURE;
111 
112     /* Return with an error */
113     SetLastError(ErrorCode);
114     return SOCKET_ERROR;
115 }
116 
117 /*
118  * @unimplemented
119  */
120 INT
121 WSPAPI
122 WPUFDIsSet(IN SOCKET s,
123            IN LPFD_SET set)
124 {
125     UNIMPLEMENTED;
126     return (SOCKET)0;
127 }
128 
129 /*
130  * @implemented
131  */
132 INT
133 WSAAPI
134 WSAAsyncSelect(IN SOCKET s,
135                IN HWND hWnd,
136                IN UINT wMsg,
137                IN LONG lEvent)
138 {
139     PWSSOCKET Socket;
140     INT Status;
141     INT ErrorCode;
142     DPRINT("WSAAsyncSelect: %lx, %lx, %lx, %lx\n", s, hWnd, wMsg, lEvent);
143 
144     /* Check for WSAStartup */
145     if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
146     {
147         /* Get the Socket Context */
148         if ((Socket = WsSockGetSocket(s)))
149         {
150             /* Make the call */
151             Status = Socket->Provider->Service.lpWSPAsyncSelect(s,
152                                                                 hWnd,
153                                                                 wMsg,
154                                                                 lEvent,
155                                                                 &ErrorCode);
156             /* Deference the Socket Context */
157             WsSockDereference(Socket);
158 
159             /* Return Provider Value */
160             if (Status == ERROR_SUCCESS) return Status;
161 
162             /* If everything seemed fine, then the WSP call failed itself */
163             if (ErrorCode == NO_ERROR) ErrorCode = WSASYSCALLFAILURE;
164         }
165         else
166         {
167             /* No Socket Context Found */
168             ErrorCode = WSAENOTSOCK;
169         }
170     }
171 
172     /* Return with an Error */
173     SetLastError(ErrorCode);
174     return SOCKET_ERROR;
175 }
176 
177 /*
178  * @implemented
179  */
180 INT
181 WSAAPI
182 WSAEventSelect(IN SOCKET s,
183                IN WSAEVENT hEventObject,
184                IN LONG lNetworkEvents)
185 {
186     PWSSOCKET Socket;
187     INT Status;
188     INT ErrorCode;
189 
190     /* Check for WSAStartup */
191     if ((ErrorCode = WsQuickProlog()) == ERROR_SUCCESS)
192     {
193         /* Get the Socket Context */
194         if ((Socket = WsSockGetSocket(s)))
195         {
196             /* Make the call */
197             Status = Socket->Provider->Service.lpWSPEventSelect(s,
198                                                         hEventObject,
199                                                         lNetworkEvents,
200                                                         &ErrorCode);
201             /* Deference the Socket Context */
202             WsSockDereference(Socket);
203 
204             /* Return Provider Value */
205             if (Status == ERROR_SUCCESS) return Status;
206         }
207         else
208         {
209             /* No Socket Context Found */
210             ErrorCode = WSAENOTSOCK;
211         }
212     }
213 
214     /* Return with an Error */
215     SetLastError(ErrorCode);
216     return SOCKET_ERROR;
217 }
218