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