blob: 44dfa6e37918837e3f03bd854d8b1a2ba9a1c4d6 [file] [log] [blame]
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001/*
2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
4 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00005 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Alexandre Julliard23946ad1997-06-16 17:43:53 +000020 *
Alexandre Julliard60ce85c1998-02-01 18:33:27 +000021 * NOTE: If you make any changes to fix a particular app, make sure
22 * they don't break something else like Netscape or telnet and ftp
23 * clients and servers (www.winsite.com got a lot of those).
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000024 */
Francois Gouget27202312001-11-14 21:26:23 +000025
François Gouget14259412001-11-06 20:57:11 +000026#include "config.h"
Francois Gouget386cf6e2001-10-14 16:25:47 +000027#include "wine/port.h"
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000028
Dimitrie O. Paun0b7a7bb2000-11-25 01:31:17 +000029#include <stdio.h>
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000030#include <string.h>
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000031#include <sys/types.h>
Patrik Stridvall2c928351999-10-31 02:07:54 +000032#ifdef HAVE_SYS_IPC_H
33# include <sys/ipc.h>
34#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000035#include <sys/ioctl.h>
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000036#ifdef HAVE_SYS_FILIO_H
37# include <sys/filio.h>
38#endif
Patrik Stridvall2c928351999-10-31 02:07:54 +000039#ifdef HAVE_SYS_SOCKIO_H
40# include <sys/sockio.h>
41#endif
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000042
Alexandre Julliard01d63461997-01-20 19:43:45 +000043#if defined(__EMX__)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000044# include <sys/so_ioctl.h>
Alexandre Julliard01d63461997-01-20 19:43:45 +000045#endif
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000046
47#ifdef HAVE_SYS_PARAM_H
48# include <sys/param.h>
49#endif
50
Patrik Stridvall2c928351999-10-31 02:07:54 +000051#ifdef HAVE_SYS_MSG_H
52# include <sys/msg.h>
53#endif
54#ifdef HAVE_SYS_WAIT_H
55# include <sys/wait.h>
56#endif
Gerald Pfeifer37e87f72002-04-08 20:14:58 +000057#include <sys/uio.h>
Patrik Stridvall2c928351999-10-31 02:07:54 +000058#ifdef HAVE_SYS_SOCKET_H
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000059#include <sys/socket.h>
Patrik Stridvall2c928351999-10-31 02:07:54 +000060#endif
61#ifdef HAVE_NETINET_IN_H
62# include <netinet/in.h>
63#endif
64#ifdef HAVE_NETINET_TCP_H
65# include <netinet/tcp.h>
66#endif
67#ifdef HAVE_ARPA_INET_H
68# include <arpa/inet.h>
69#endif
Alexandre Julliard60ce85c1998-02-01 18:33:27 +000070#include <ctype.h>
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000071#include <fcntl.h>
72#include <errno.h>
Howard Abrams13277481999-07-10 13:16:29 +000073#ifdef HAVE_SYS_ERRNO_H
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000074#include <sys/errno.h>
Howard Abrams13277481999-07-10 13:16:29 +000075#endif
Hidenori Takeshima5d1a6382000-11-26 04:00:53 +000076#ifdef HAVE_NETDB_H
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000077#include <netdb.h>
Hidenori Takeshima5d1a6382000-11-26 04:00:53 +000078#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000079#include <unistd.h>
Michael Vekslerca1bc861999-01-01 18:57:33 +000080#include <stdlib.h>
Marcus Meissner664c2721999-02-28 11:23:44 +000081#ifdef HAVE_ARPA_NAMESER_H
82# include <arpa/nameser.h>
83#endif
Marcus Meissner3b092841999-02-20 16:46:39 +000084#ifdef HAVE_RESOLV_H
85# include <resolv.h>
86#endif
James Hathewayc9d25822000-07-23 19:28:24 +000087#ifdef HAVE_NET_IF_H
88# include <net/if.h>
89#endif
Alexandre Julliard83f52d12000-09-26 22:20:14 +000090#ifdef HAVE_IPX_GNU
91# include <netipx/ipx.h>
92# define HAVE_IPX
93#endif
94#ifdef HAVE_IPX_LINUX
95# include <asm/types.h>
96# include <linux/ipx.h>
97# define HAVE_IPX
98#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000099
Marcus Meissner5a82fa12002-03-25 20:51:48 +0000100#ifdef HAVE_SYS_TIME_H
101# include <sys/time.h>
102#endif
103
Marcus Meissner04c3e1d1999-02-19 10:37:02 +0000104#include "wine/winbase16.h"
Patrik Stridvall6cc47d42000-03-08 18:26:56 +0000105#include "wingdi.h"
106#include "winuser.h"
Martin Wilckaf16c982002-04-25 21:34:24 +0000107#include "winerror.h"
Ove Kaavenf45608f1999-10-23 16:53:34 +0000108#include "winsock2.h"
Francois Gouget27202312001-11-14 21:26:23 +0000109#include "ws2tcpip.h"
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000110#include "wsipx.h"
Andreas Mohrae509412000-08-03 22:19:09 +0000111#include "wine/winsock16.h"
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000112#include "winnt.h"
Alexandre Julliard37e95032001-07-19 00:39:09 +0000113#include "wine/server.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +0000114#include "wine/debug.h"
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000115
James Hathewayc9d25822000-07-23 19:28:24 +0000116
Alexandre Julliard0799c1a2002-03-09 23:29:33 +0000117WINE_DEFAULT_DEBUG_CHANNEL(winsock);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +0000118
Rein Klazesff7a61f2000-09-24 19:41:57 +0000119/* critical section to protect some non-rentrant net function */
120extern CRITICAL_SECTION csWSgetXXXbyYYY;
121
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000122#define DEBUG_SOCKADDR 0
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000123#define dump_sockaddr(a) \
Alexandre Julliard61fece01999-06-26 19:09:08 +0000124 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000125 ((struct sockaddr_in *)a)->sin_family, \
126 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
127 ntohs(((struct sockaddr_in *)a)->sin_port))
128
Martin Wilckaf16c982002-04-25 21:34:24 +0000129/****************************************************************
130 * Async IO declarations
131 ****************************************************************/
132#include "async.h"
133
134static DWORD ws2_async_get_status (const struct async_private *ovp);
135static DWORD ws2_async_get_count (const struct async_private *ovp);
136static void ws2_async_set_status (struct async_private *ovp, const DWORD status);
137static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
138static void ws2_async_cleanup ( struct async_private *ovp );
139
140static struct async_ops ws2_async_ops =
141{
142 ws2_async_get_status,
143 ws2_async_set_status,
144 ws2_async_get_count,
145 ws2_async_call_completion,
146 ws2_async_cleanup
147};
148
149static struct async_ops ws2_nocomp_async_ops =
150{
151 ws2_async_get_status,
152 ws2_async_set_status,
153 ws2_async_get_count,
154 NULL, /* call_completion */
155 ws2_async_cleanup
156};
157
158typedef struct ws2_async
159{
160 async_private async;
161 LPWSAOVERLAPPED overlapped;
162 LPWSAOVERLAPPED user_overlapped;
163 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
164 struct iovec *iovec;
165 int n_iovecs;
166 struct WS_sockaddr *addr;
167 union {
168 int val; /* for send operations */
169 int *ptr; /* for recv operations */
170 } addrlen;
171 DWORD flags;
172} ws2_async;
173
174/****************************************************************/
175
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000176/* ----------------------------------- internal data */
177
Ove Kaavenf45608f1999-10-23 16:53:34 +0000178/* ws_... struct conversion flags */
179
180#define WS_DUP_LINEAR 0x0001
Alexandre Julliard85129792001-12-24 20:30:24 +0000181#define WS_DUP_SEGPTR 0x0002 /* internal pointers are SEGPTRs */
Ove Kaavenf45608f1999-10-23 16:53:34 +0000182 /* by default, internal pointers are linear */
183typedef struct /* WSAAsyncSelect() control struct */
184{
185 HANDLE service, event, sock;
186 HWND hWnd;
187 UINT uMsg;
Ove Kaavencb98a6e2000-03-26 18:21:16 +0000188 LONG lEvent;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000189} ws_select_info;
190
191#define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
192#define WS_MAX_UDP_DATAGRAM 1024
193
James Hathewayc9d25822000-07-23 19:28:24 +0000194#define PROCFS_NETDEV_FILE "/proc/net/dev" /* Points to the file in the /proc fs
195 that lists the network devices.
196 Do we need an #ifdef LINUX for this? */
197
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000198static void *he_buffer; /* typecast for Win16/32 ws_hostent */
Alexandre Julliard85129792001-12-24 20:30:24 +0000199static SEGPTR he_buffer_seg;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000200static void *se_buffer; /* typecast for Win16/32 ws_servent */
Alexandre Julliard85129792001-12-24 20:30:24 +0000201static SEGPTR se_buffer_seg;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000202static void *pe_buffer; /* typecast for Win16/32 ws_protoent */
Alexandre Julliard85129792001-12-24 20:30:24 +0000203static SEGPTR pe_buffer_seg;
204static char* local_buffer;
205static SEGPTR dbuffer_seg;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000206static INT num_startup; /* reference counter */
207static FARPROC blocking_hook;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000208
209/* function prototypes */
Alexandre Julliard85129792001-12-24 20:30:24 +0000210static int WS_dup_he(struct hostent* p_he, int flag);
211static int WS_dup_pe(struct protoent* p_pe, int flag);
212static int WS_dup_se(struct servent* p_se, int flag);
Ove Kaavenf45608f1999-10-23 16:53:34 +0000213
Andreas Mohrae509412000-08-03 22:19:09 +0000214typedef void WIN_hostent;
215typedef void WIN_protoent;
216typedef void WIN_servent;
217
James Hathewayc9d25822000-07-23 19:28:24 +0000218int WSAIOCTL_GetInterfaceCount(void);
219int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
220
Ove Kaavenf45608f1999-10-23 16:53:34 +0000221UINT16 wsaErrno(void);
Rein Klazesff7a61f2000-09-24 19:41:57 +0000222UINT16 wsaHerrno(int errnr);
Ove Kaavenf45608f1999-10-23 16:53:34 +0000223
Alexandre Julliarda3960291999-02-26 11:11:13 +0000224static HANDLE _WSHeap = 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000225
226#define WS_ALLOC(size) \
227 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
228#define WS_FREE(ptr) \
229 HeapFree(_WSHeap, 0, (ptr) )
230
Alexandre Julliarda3960291999-02-26 11:11:13 +0000231static INT _ws_sock_ops[] =
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000232 { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
233 WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
John Gilmore5180d562000-09-16 20:51:40 +0000234 WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE,
Marcus Meissner751dc4c1999-03-24 14:53:55 +0000235#ifdef SO_RCVTIMEO
236 WS_SO_RCVTIMEO,
237#endif
John Gilmore5180d562000-09-16 20:51:40 +0000238#ifdef SO_SNDTIMEO
239 WS_SO_SNDTIMEO,
240#endif
Marcus Meissner751dc4c1999-03-24 14:53:55 +0000241 0 };
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000242static int _px_sock_ops[] =
243 { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
244 SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
Marcus Meissner751dc4c1999-03-24 14:53:55 +0000245#ifdef SO_RCVTIMEO
246 SO_RCVTIMEO,
247#endif
John Gilmore5180d562000-09-16 20:51:40 +0000248#ifdef SO_SNDTIMEO
249 SO_SNDTIMEO,
250#endif
Marcus Meissner751dc4c1999-03-24 14:53:55 +0000251 };
Marcus Meissner5eaf7751999-03-09 17:31:42 +0000252
253static INT _ws_tcp_ops[] = {
254#ifdef TCP_NODELAY
255 WS_TCP_NODELAY,
256#endif
257 0
258};
259static int _px_tcp_ops[] = {
260#ifdef TCP_NODELAY
261 TCP_NODELAY,
262#endif
263 0
264};
265
Martin Wilckcf518bc2002-04-27 01:05:35 +0000266static DWORD opentype_tls_index = -1; /* TLS index for SO_OPENTYPE flag */
Paul Rupe99ed3422001-12-14 22:48:38 +0000267
Martin Wilckaf16c982002-04-25 21:34:24 +0000268inline static DWORD NtStatusToWSAError ( const DWORD status )
269{
270 /* We only need to cover the status codes set by server async request handling */
271 DWORD wserr;
272 switch ( status )
273 {
274 case STATUS_SUCCESS: wserr = 0; break;
275 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
276 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
277 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
278 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
279 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
280 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
281 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
282 default:
283 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
284 /* It is not a NT status code but a winsock error */
285 wserr = status;
286 else
287 {
288 wserr = RtlNtStatusToDosError( status );
289 FIXME ( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
290 }
291 }
292 return wserr;
293}
294
Alexandre Julliard67a74992001-02-27 02:09:16 +0000295/* set last error code from NT status without mapping WSA errors */
296inline static unsigned int set_error( unsigned int err )
Alexandre Julliardcb1fc732000-01-24 21:58:06 +0000297{
Alexandre Julliard67a74992001-02-27 02:09:16 +0000298 if (err)
Alexandre Julliardcb1fc732000-01-24 21:58:06 +0000299 {
Martin Wilckaf16c982002-04-25 21:34:24 +0000300 err = NtStatusToWSAError ( err );
Alexandre Julliard67a74992001-02-27 02:09:16 +0000301 SetLastError( err );
Alexandre Julliardcb1fc732000-01-24 21:58:06 +0000302 }
Alexandre Julliard67a74992001-02-27 02:09:16 +0000303 return err;
Alexandre Julliardcb1fc732000-01-24 21:58:06 +0000304}
305
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000306static char* check_buffer(int size);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000307
Alexandre Julliard81f2a732002-03-23 20:43:52 +0000308inline static int _get_sock_fd(SOCKET s)
Marcus Meissnerbdb6bec1999-04-10 16:58:55 +0000309{
Alexandre Julliard81f2a732002-03-23 20:43:52 +0000310 int fd;
311
312 if (set_error( wine_server_handle_to_fd( s, GENERIC_READ, &fd, NULL, NULL ) )) return -1;
313 return fd;
Marcus Meissnerbdb6bec1999-04-10 16:58:55 +0000314}
315
Martin Wilckaf16c982002-04-25 21:34:24 +0000316inline static int _get_sock_fd_type( SOCKET s, DWORD access, enum fd_type *type, int *flags )
Martin Wilckaba59472002-04-17 16:46:49 +0000317{
318 int fd;
Martin Wilckaf16c982002-04-25 21:34:24 +0000319 if (set_error( wine_server_handle_to_fd( s, access, &fd, type, flags ) )) return -1;
320 if ( ( (access & GENERIC_READ) && (*flags & FD_FLAG_RECV_SHUTDOWN ) ) ||
321 ( (access & GENERIC_WRITE) && (*flags & FD_FLAG_SEND_SHUTDOWN ) ) )
322 {
323 close (fd);
324 WSASetLastError ( WSAESHUTDOWN );
325 return -1;
326 }
Martin Wilckaba59472002-04-17 16:46:49 +0000327 return fd;
328}
329
Ove Kaavenf45608f1999-10-23 16:53:34 +0000330static void _enable_event(SOCKET s, unsigned int event,
331 unsigned int sstate, unsigned int cstate)
332{
Alexandre Julliard67a74992001-02-27 02:09:16 +0000333 SERVER_START_REQ( enable_socket_event )
Alexandre Julliard92643002000-08-31 01:59:51 +0000334 {
Alexandre Julliard92643002000-08-31 01:59:51 +0000335 req->handle = s;
336 req->mask = event;
337 req->sstate = sstate;
338 req->cstate = cstate;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000339 wine_server_call( req );
Alexandre Julliard92643002000-08-31 01:59:51 +0000340 }
341 SERVER_END_REQ;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000342}
343
344static int _is_blocking(SOCKET s)
345{
Alexandre Julliard92643002000-08-31 01:59:51 +0000346 int ret;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000347 SERVER_START_REQ( get_socket_event )
Alexandre Julliard92643002000-08-31 01:59:51 +0000348 {
Alexandre Julliard92643002000-08-31 01:59:51 +0000349 req->handle = s;
350 req->service = FALSE;
Alexandre Julliard92643002000-08-31 01:59:51 +0000351 req->c_event = 0;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000352 wine_server_call( req );
353 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
Alexandre Julliard92643002000-08-31 01:59:51 +0000354 }
355 SERVER_END_REQ;
356 return ret;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000357}
358
359static unsigned int _get_sock_mask(SOCKET s)
360{
Alexandre Julliard92643002000-08-31 01:59:51 +0000361 unsigned int ret;
Alexandre Julliard67a74992001-02-27 02:09:16 +0000362 SERVER_START_REQ( get_socket_event )
Alexandre Julliard92643002000-08-31 01:59:51 +0000363 {
Alexandre Julliard92643002000-08-31 01:59:51 +0000364 req->handle = s;
365 req->service = FALSE;
Alexandre Julliard92643002000-08-31 01:59:51 +0000366 req->c_event = 0;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000367 wine_server_call( req );
368 ret = reply->mask;
Alexandre Julliard92643002000-08-31 01:59:51 +0000369 }
370 SERVER_END_REQ;
371 return ret;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000372}
373
374static void _sync_sock_state(SOCKET s)
375{
376 /* do a dummy wineserver request in order to let
377 the wineserver run through its select loop once */
378 (void)_is_blocking(s);
379}
380
381static int _get_sock_error(SOCKET s, unsigned int bit)
382{
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000383 int events[FD_MAX_EVENTS];
384
385 SERVER_START_REQ( get_socket_event )
Alexandre Julliard92643002000-08-31 01:59:51 +0000386 {
Alexandre Julliard92643002000-08-31 01:59:51 +0000387 req->handle = s;
388 req->service = FALSE;
Alexandre Julliard92643002000-08-31 01:59:51 +0000389 req->c_event = 0;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000390 wine_server_set_reply( req, events, sizeof(events) );
391 wine_server_call( req );
Alexandre Julliard92643002000-08-31 01:59:51 +0000392 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000393 SERVER_END_REQ;
394 return events[bit];
Ove Kaavenf45608f1999-10-23 16:53:34 +0000395}
396
Ove Kaavenf45608f1999-10-23 16:53:34 +0000397static void WINSOCK_DeleteIData(void)
398{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000399 /* delete scratch buffers */
Ove Kaavenf45608f1999-10-23 16:53:34 +0000400
Alexandre Julliard85129792001-12-24 20:30:24 +0000401 UnMapLS( he_buffer_seg );
402 UnMapLS( se_buffer_seg );
403 UnMapLS( pe_buffer_seg );
404 UnMapLS( dbuffer_seg );
405 if (he_buffer) HeapFree( GetProcessHeap(), 0, he_buffer );
406 if (se_buffer) HeapFree( GetProcessHeap(), 0, se_buffer );
407 if (pe_buffer) HeapFree( GetProcessHeap(), 0, pe_buffer );
408 if (local_buffer) HeapFree( GetProcessHeap(), 0, local_buffer );
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000409 he_buffer = NULL;
410 se_buffer = NULL;
411 pe_buffer = NULL;
412 local_buffer = NULL;
Alexandre Julliard85129792001-12-24 20:30:24 +0000413 he_buffer_seg = 0;
414 se_buffer_seg = 0;
415 pe_buffer_seg = 0;
416 dbuffer_seg = 0;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000417 num_startup = 0;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000418}
419
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000420/***********************************************************************
Francois Gouget27202312001-11-14 21:26:23 +0000421 * WS_LibMain (WS2_32.init)
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000422 */
Francois Gouget27202312001-11-14 21:26:23 +0000423BOOL WINAPI WS_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
Ove Kaavenf45608f1999-10-23 16:53:34 +0000424{
425 TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
426 switch (fdwReason) {
Martin Wilckcf518bc2002-04-27 01:05:35 +0000427 case DLL_PROCESS_ATTACH:
428 opentype_tls_index = TlsAlloc();
429 break;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000430 case DLL_PROCESS_DETACH:
Martin Wilckcf518bc2002-04-27 01:05:35 +0000431 TlsFree( opentype_tls_index );
Ove Kaavenf45608f1999-10-23 16:53:34 +0000432 WINSOCK_DeleteIData();
433 break;
434 }
435 return TRUE;
436}
437
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000438/***********************************************************************
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000439 * convert_sockopt()
440 *
441 * Converts socket flags from Windows format.
John Gilmore5180d562000-09-16 20:51:40 +0000442 * Return 1 if converted, 0 if not (error).
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000443 */
John Gilmore5180d562000-09-16 20:51:40 +0000444static int convert_sockopt(INT *level, INT *optname)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000445{
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000446 int i;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000447 switch (*level)
448 {
449 case WS_SOL_SOCKET:
450 *level = SOL_SOCKET;
451 for(i=0; _ws_sock_ops[i]; i++)
452 if( _ws_sock_ops[i] == *optname ) break;
John Gilmore5180d562000-09-16 20:51:40 +0000453 if( _ws_sock_ops[i] ) {
454 *optname = _px_sock_ops[i];
455 return 1;
456 }
457 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000458 break;
459 case WS_IPPROTO_TCP:
Marcus Meissner5eaf7751999-03-09 17:31:42 +0000460 *level = IPPROTO_TCP;
461 for(i=0; _ws_tcp_ops[i]; i++)
462 if ( _ws_tcp_ops[i] == *optname ) break;
John Gilmore5180d562000-09-16 20:51:40 +0000463 if( _ws_tcp_ops[i] ) {
464 *optname = _px_tcp_ops[i];
465 return 1;
466 }
467 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
Marcus Meissner5eaf7751999-03-09 17:31:42 +0000468 break;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000469 }
John Gilmore5180d562000-09-16 20:51:40 +0000470 return 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000471}
472
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000473/* ----------------------------------- Per-thread info (or per-process?) */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000474
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000475static int wsi_strtolo(const char* name, const char* opt)
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000476{
477 /* Stuff a lowercase copy of the string into the local buffer */
478
479 int i = strlen(name) + 2;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000480 char* p = check_buffer(i + ((opt)?strlen(opt):0));
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000481
482 if( p )
483 {
484 do *p++ = tolower(*name); while(*name++);
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000485 i = (p - local_buffer);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000486 if( opt ) do *p++ = tolower(*opt); while(*opt++);
487 return i;
488 }
489 return 0;
490}
491
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000492static fd_set* fd_set_import( fd_set* fds, void* wsfds, int* highfd, int lfd[], BOOL b32 )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000493{
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000494 /* translate Winsock fd set into local fd set */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000495
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000496 if( wsfds )
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000497 {
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000498#define wsfds16 ((ws_fd_set16*)wsfds)
Francois Gouget27202312001-11-14 21:26:23 +0000499#define wsfds32 ((WS_fd_set*)wsfds)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000500 int i, count;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000501
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000502 FD_ZERO(fds);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000503 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
504
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000505 for( i = 0; i < count; i++ )
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000506 {
Ove Kaavenf45608f1999-10-23 16:53:34 +0000507 int s = (b32) ? wsfds32->fd_array[i]
508 : wsfds16->fd_array[i];
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000509 int fd = _get_sock_fd(s);
510 if (fd != -1)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000511 {
Ove Kaavenf45608f1999-10-23 16:53:34 +0000512 lfd[ i ] = fd;
513 if( fd > *highfd ) *highfd = fd;
514 FD_SET(fd, fds);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000515 }
Ove Kaavenf45608f1999-10-23 16:53:34 +0000516 else lfd[ i ] = -1;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000517 }
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000518#undef wsfds32
519#undef wsfds16
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000520 return fds;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000521 }
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000522 return NULL;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000523}
524
Patrik Stridvall896889f1999-05-08 12:50:36 +0000525inline static int sock_error_p(int s)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000526{
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000527 unsigned int optval, optlen;
528
529 optlen = sizeof(optval);
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000530 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
Alexandre Julliard61fece01999-06-26 19:09:08 +0000531 if (optval) WARN("\t[%i] error: %d\n", s, optval);
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000532 return optval != 0;
533}
534
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000535static int fd_set_export( fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000536{
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000537 int num_err = 0;
538
539 /* translate local fd set into Winsock fd set, adding
540 * errors to exceptfds (only if app requested it) */
541
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000542 if( wsfds )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000543 {
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000544#define wsfds16 ((ws_fd_set16*)wsfds)
Francois Gouget27202312001-11-14 21:26:23 +0000545#define wsfds32 ((WS_fd_set*)wsfds)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000546 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000547
548 for( i = 0, j = 0; i < count; i++ )
549 {
Ove Kaavenf45608f1999-10-23 16:53:34 +0000550 if( lfd[i] >= 0 )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000551 {
Ove Kaavenf45608f1999-10-23 16:53:34 +0000552 int fd = lfd[i];
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000553 if( FD_ISSET(fd, fds) )
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000554 {
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000555 if ( exceptfds && sock_error_p(fd) )
556 {
557 FD_SET(fd, exceptfds);
558 num_err++;
559 }
560 else if( b32 )
561 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
562 else
563 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000564 }
Ove Kaavenf45608f1999-10-23 16:53:34 +0000565 close(fd);
566 lfd[i] = -1;
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000567 }
568 }
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000569
570 if( b32 ) wsfds32->fd_count = j;
571 else wsfds16->fd_count = j;
572
Alexandre Julliard61fece01999-06-26 19:09:08 +0000573 TRACE("\n");
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000574#undef wsfds32
575#undef wsfds16
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000576 }
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000577 return num_err;
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000578}
579
Ove Kaavenf45608f1999-10-23 16:53:34 +0000580static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000581{
Ove Kaavenf45608f1999-10-23 16:53:34 +0000582 if ( wsfds )
583 {
584#define wsfds16 ((ws_fd_set16*)wsfds)
Francois Gouget27202312001-11-14 21:26:23 +0000585#define wsfds32 ((WS_fd_set*)wsfds)
Ove Kaavenf45608f1999-10-23 16:53:34 +0000586 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
587
588 for( i = 0; i < count; i++ )
589 if ( lfd[i] >= 0 )
590 close(lfd[i]);
591
592 TRACE("\n");
593#undef wsfds32
594#undef wsfds16
595 }
596}
597
598static int do_block( int fd, int mask )
599{
600 fd_set fds[3];
601 int i, r;
602
603 FD_ZERO(&fds[0]);
604 FD_ZERO(&fds[1]);
605 FD_ZERO(&fds[2]);
606 for (i=0; i<3; i++)
607 if (mask & (1<<i))
608 FD_SET(fd, &fds[i]);
609 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
610 if (i <= 0) return -1;
611 r = 0;
612 for (i=0; i<3; i++)
613 if (FD_ISSET(fd, &fds[i]))
614 r |= 1<<i;
615 return r;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000616}
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000617
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000618void* __ws_memalloc( int size )
619{
620 return WS_ALLOC(size);
621}
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000622
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000623void __ws_memfree(void* ptr)
624{
625 WS_FREE(ptr);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000626}
627
Ulrich Weigand89fc6fd1999-05-24 08:13:02 +0000628
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000629/* ----------------------------------- API -----
630 *
631 * Init / cleanup / error checking.
632 */
633
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000634/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000635 * WSAStartup (WINSOCK.115)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000636 *
637 * Create socket control struct, attach it to the global list and
638 * update a pointer in the task struct.
639 */
Francois Gouget14b06d42001-08-24 21:33:58 +0000640INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA16 lpWSAData)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000641{
Francois Gouget14b06d42001-08-24 21:33:58 +0000642 static const WSADATA16 data =
643 {
644 0x0101, 0x0101,
645 "WINE Sockets 1.1",
646#ifdef linux
647 "Linux/i386",
648#elif defined(__NetBSD__)
649 "NetBSD/i386",
650#elif defined(sunos)
651 "SunOS",
652#elif defined(__FreeBSD__)
653 "FreeBSD",
654#elif defined(__OpenBSD__)
655 "OpenBSD/i386",
656#else
657 "Unknown",
658#endif
659 WS_MAX_SOCKETS_PER_PROCESS,
660 WS_MAX_UDP_DATAGRAM,
661 0
662 };
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000663
Alexandre Julliard61fece01999-06-26 19:09:08 +0000664 TRACE("verReq=%x\n", wVersionRequested);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000665
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000666 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
667 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000668
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000669 if (!lpWSAData) return WSAEINVAL;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000670
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000671 /* initialize socket heap */
672
Ove Kaavenf45608f1999-10-23 16:53:34 +0000673 if( !_WSHeap )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000674 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000675 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
Ove Kaavenf45608f1999-10-23 16:53:34 +0000676 if( !_WSHeap )
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000677 {
Alexandre Julliard61fece01999-06-26 19:09:08 +0000678 ERR("Fatal: failed to create WinSock heap\n");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000679 return 0;
680 }
681 }
682 if( _WSHeap == 0 ) return WSASYSNOTREADY;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000683
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000684 num_startup++;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000685
686 /* return winsock information */
687
Francois Gouget14b06d42001-08-24 21:33:58 +0000688 memcpy(lpWSAData, &data, sizeof(data));
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000689
Alexandre Julliard61fece01999-06-26 19:09:08 +0000690 TRACE("succeeded\n");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000691 return 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000692}
693
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000694/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000695 * WSAStartup (WS2_32.115)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000696 */
Francois Gougetd97fe262001-09-14 00:19:52 +0000697int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000698{
Francois Gouget14b06d42001-08-24 21:33:58 +0000699 static const WSADATA data =
700 {
701 0x0202, 0x0202,
702 "WINE Sockets 2.0",
703#ifdef linux
704 "Linux",
705#elif defined(__NetBSD__)
706 "NetBSD",
707#elif defined(sunos)
708 "SunOS",
709#elif defined(__FreeBSD__)
710 "FreeBSD",
711#elif defined(__OpenBSD__)
712 "OpenBSD",
713#else
714 "Unknown",
715#endif
716 WS_MAX_SOCKETS_PER_PROCESS,
717 WS_MAX_UDP_DATAGRAM,
718 NULL
719 };
James Hatheway829405a2000-06-18 17:23:17 +0000720
721 TRACE("verReq=%x\n", wVersionRequested);
722
Alexandre Julliardc6075322000-07-09 11:19:35 +0000723 if (LOBYTE(wVersionRequested) < 1)
James Hatheway829405a2000-06-18 17:23:17 +0000724 return WSAVERNOTSUPPORTED;
725
726 if (!lpWSAData) return WSAEINVAL;
727
728 /* initialize socket heap */
729
730 if( !_WSHeap )
731 {
732 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
733 if( !_WSHeap )
734 {
735 ERR("Fatal: failed to create WinSock heap\n");
736 return 0;
737 }
738 }
739 if( _WSHeap == 0 ) return WSASYSNOTREADY;
740
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000741 num_startup++;
James Hatheway829405a2000-06-18 17:23:17 +0000742
743 /* return winsock information */
Francois Gouget14b06d42001-08-24 21:33:58 +0000744 memcpy(lpWSAData, &data, sizeof(data));
James Hatheway829405a2000-06-18 17:23:17 +0000745
Gerard Patel0b42d3c2000-07-10 10:57:46 +0000746 /* that's the whole of the negotiation for now */
747 lpWSAData->wVersion = wVersionRequested;
748
James Hatheway829405a2000-06-18 17:23:17 +0000749 TRACE("succeeded\n");
750 return 0;
751}
752
753
754/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000755 * WSACleanup (WINSOCK.116)
Patrik Stridvall044855c2001-07-11 18:56:41 +0000756 * WSACleanup (WS2_32.116)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000757 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000758INT WINAPI WSACleanup(void)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000759{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000760 if (num_startup)
761 {
762 if (--num_startup > 0) return 0;
763 WINSOCK_DeleteIData();
764 return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000765 }
Ove Kaaven4ff3b202000-03-04 19:29:42 +0000766 SetLastError(WSANOTINITIALISED);
Ove Kaavenf45608f1999-10-23 16:53:34 +0000767 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000768}
769
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000770
771/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000772 * WSAGetLastError (WINSOCK.111)
773 * WSAGetLastError (WS2_32.111)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000774 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000775INT WINAPI WSAGetLastError(void)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000776{
Marcus Meissner01f3dc31999-05-12 10:34:03 +0000777 return GetLastError();
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000778}
779
780/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000781 * WSASetLastError (WS2_32.112)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000782 */
Marcus Meissner01f3dc31999-05-12 10:34:03 +0000783void WINAPI WSASetLastError(INT iError) {
784 SetLastError(iError);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000785}
786
787/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000788 * WSASetLastError (WINSOCK.112)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000789 */
790void WINAPI WSASetLastError16(INT16 iError)
791{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000792 WSASetLastError(iError);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000793}
794
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000795static char* check_buffer(int size)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000796{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000797 static int local_buflen;
798
799 if (local_buffer)
Jesper Skov5c3e4571998-11-01 19:27:22 +0000800 {
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000801 if (local_buflen >= size ) return local_buffer;
Alexandre Julliard85129792001-12-24 20:30:24 +0000802 HeapFree( GetProcessHeap(), 0, local_buffer );
Jesper Skov5c3e4571998-11-01 19:27:22 +0000803 }
Alexandre Julliard85129792001-12-24 20:30:24 +0000804 local_buffer = HeapAlloc( GetProcessHeap(), 0, (local_buflen = size) );
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000805 return local_buffer;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000806}
807
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000808static struct ws_hostent* check_buffer_he(int size)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000809{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000810 static int he_len;
811 if (he_buffer)
812 {
813 if (he_len >= size ) return he_buffer;
Alexandre Julliard85129792001-12-24 20:30:24 +0000814 UnMapLS( he_buffer_seg );
815 HeapFree( GetProcessHeap(), 0, he_buffer );
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000816 }
Alexandre Julliard85129792001-12-24 20:30:24 +0000817 he_buffer = HeapAlloc( GetProcessHeap(), 0, (he_len = size) );
818 he_buffer_seg = MapLS( he_buffer );
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000819 return he_buffer;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000820}
821
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000822static void* check_buffer_se(int size)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000823{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000824 static int se_len;
825 if (se_buffer)
826 {
827 if (se_len >= size ) return se_buffer;
Alexandre Julliard85129792001-12-24 20:30:24 +0000828 UnMapLS( se_buffer_seg );
829 HeapFree( GetProcessHeap(), 0, se_buffer );
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000830 }
Alexandre Julliard85129792001-12-24 20:30:24 +0000831 se_buffer = HeapAlloc( GetProcessHeap(), 0, (se_len = size) );
832 se_buffer_seg = MapLS( he_buffer );
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000833 return se_buffer;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000834}
835
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000836static struct ws_protoent* check_buffer_pe(int size)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000837{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000838 static int pe_len;
839 if (pe_buffer)
840 {
841 if (pe_len >= size ) return pe_buffer;
Alexandre Julliard85129792001-12-24 20:30:24 +0000842 UnMapLS( pe_buffer_seg );
843 HeapFree( GetProcessHeap(), 0, pe_buffer );
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000844 }
Alexandre Julliard85129792001-12-24 20:30:24 +0000845 pe_buffer = HeapAlloc( GetProcessHeap(), 0, (pe_len = size) );
846 pe_buffer_seg = MapLS( he_buffer );
Alexandre Julliard641c7ae2001-02-20 01:57:13 +0000847 return pe_buffer;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000848}
849
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000850/* ----------------------------------- i/o APIs */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000851
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000852#ifdef HAVE_IPX
Michael C. Maggiof3b01aa2002-01-15 20:26:28 +0000853#define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000854#else
Michael C. Maggiof3b01aa2002-01-15 20:26:28 +0000855#define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000856#endif
857
Ove Kaavencb98a6e2000-03-26 18:21:16 +0000858
Patrik Stridvall2b3aa612000-12-01 23:58:28 +0000859/**********************************************************************/
860
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000861/* Returns the converted address if successful, NULL if it was too small to
862 * start with. Note that the returned pointer may be the original pointer
863 * if no conversion is necessary.
864 */
Francois Gouget85498212002-01-10 18:18:43 +0000865static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000866{
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000867 switch (wsaddr->sa_family)
868 {
Pavel Roskin94d99641998-12-26 11:52:51 +0000869#ifdef HAVE_IPX
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000870 case WS_AF_IPX:
871 {
Francois Gouget27202312001-11-14 21:26:23 +0000872 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000873 struct sockaddr_ipx* uipx;
874
Francois Gouget27202312001-11-14 21:26:23 +0000875 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000876 return NULL;
877
878 *uaddrlen=sizeof(struct sockaddr_ipx);
879 uipx=malloc(*uaddrlen);
880 uipx->sipx_family=AF_IPX;
881 uipx->sipx_port=wsipx->sa_socket;
882 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
883 * in one go
884 */
885 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
886 uipx->sipx_type=IPX_FRAME_NONE;
887 uipx->sipx_zero=0;
888 return (const struct sockaddr*)uipx;
889 }
Stephen Langasekdc163421998-11-08 15:42:40 +0000890#endif
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000891
892 default:
Francois Gouget27202312001-11-14 21:26:23 +0000893 if (wsaddrlen<sizeof(struct WS_sockaddr))
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000894 return NULL;
895
896 /* No conversion needed, just return the original address */
897 *uaddrlen=wsaddrlen;
898 return (const struct sockaddr*)wsaddr;
899 }
900 return NULL;
901}
902
903/* allocates a Unix sockaddr structure to receive the data */
Francois Gouget27202312001-11-14 21:26:23 +0000904inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000905{
Lawson Whitneyf6a3a522002-02-14 19:20:12 +0000906 if (wsaddr==NULL)
907 return NULL;
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000908 if (*wsaddrlen==0)
909 *uaddrlen=0;
910 else
911 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000912
913 return malloc(*uaddrlen);
914}
915
916/* Returns 0 if successful, -1 if the buffer is too small */
Francois Gouget85498212002-01-10 18:18:43 +0000917static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000918{
919 int res;
920
921 switch(uaddr->sa_family)
922 {
923#ifdef HAVE_IPX
924 case AF_IPX:
925 {
926 struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
Francois Gouget27202312001-11-14 21:26:23 +0000927 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000928
929 res=-1;
930 switch (*wsaddrlen) /* how much can we copy? */
931 {
932 default:
933 res=0; /* enough */
Francois Gouget85498212002-01-10 18:18:43 +0000934 *wsaddrlen=uaddrlen;
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000935 wsipx->sa_socket=uipx->sipx_port;
936 /* fall through */
937 case 13:
938 case 12:
939 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
940 /* fall through */
941 case 11:
942 case 10:
943 case 9:
944 case 8:
945 case 7:
946 case 6:
947 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
948 /* fall through */
949 case 5:
950 case 4:
951 case 3:
952 case 2:
Michael C. Maggiof3b01aa2002-01-15 20:26:28 +0000953 wsipx->sa_family=WS_AF_IPX;
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000954 /* fall through */
955 case 1:
956 case 0:
957 /* way too small */
Francois Gougete6ebf422002-01-21 17:59:38 +0000958 break;
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000959 }
960 }
961 break;
962#endif
963
964 default:
965 /* No conversion needed */
966 memcpy(wsaddr,uaddr,*wsaddrlen);
Francois Gouget85498212002-01-10 18:18:43 +0000967 if (*wsaddrlen<uaddrlen) {
968 res=-1;
969 } else {
970 *wsaddrlen=uaddrlen;
971 res=0;
972 }
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000973 }
974 return res;
975}
976
977/* to be called to free the memory allocated by ws_sockaddr_ws2u or
978 * ws_sockaddr_alloc
979 */
Francois Gouget27202312001-11-14 21:26:23 +0000980inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
Francois Gouget76f6ffa2001-10-08 20:36:03 +0000981{
982 if (uaddr!=NULL && uaddr!=(const struct sockaddr*)wsaddr)
983 free((void*)uaddr);
984}
985
Martin Wilckaf16c982002-04-25 21:34:24 +0000986/**************************************************************************
987 * Functions for handling overlapped I/O
988 **************************************************************************/
989
990static DWORD ws2_async_get_status (const struct async_private *ovp)
991{
992 return ((ws2_async*) ovp)->overlapped->Internal;
993}
994
995static VOID ws2_async_set_status (struct async_private *ovp, const DWORD status)
996{
997 ((ws2_async*) ovp)->overlapped->Internal = status;
998}
999
1000static DWORD ws2_async_get_count (const struct async_private *ovp)
1001{
1002 return ((ws2_async*) ovp)->overlapped->InternalHigh;
1003}
1004
1005static void ws2_async_cleanup ( struct async_private *ap )
1006{
1007 struct ws2_async *as = (struct ws2_async*) ap;
1008
1009 TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->overlapped );
1010 if ( !as->user_overlapped )
1011 {
1012 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
1013 WSACloseEvent ( as->overlapped->hEvent );
1014 HeapFree ( GetProcessHeap(), 0, as->overlapped );
1015 }
1016
1017 if ( as->iovec )
1018 HeapFree ( GetProcessHeap(), 0, as->iovec );
1019
1020 HeapFree ( GetProcessHeap(), 0, as );
1021}
1022
1023static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
1024{
1025 ws2_async* as = (ws2_async*) data;
1026
1027 TRACE ("data: %p\n", as);
1028
1029 as->completion_func ( NtStatusToWSAError (as->overlapped->Internal),
1030 as->overlapped->InternalHigh,
1031 as->user_overlapped,
1032 as->flags );
1033 ws2_async_cleanup ( &as->async );
1034}
1035
1036/***********************************************************************
1037 * WS2_make_async (INTERNAL)
1038 */
1039
1040static void WS2_async_recv (async_private *as);
1041static void WS2_async_send (async_private *as);
1042
1043inline static struct ws2_async*
1044WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferCount,
1045 LPDWORD lpFlags, struct WS_sockaddr *addr,
1046 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
1047 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1048{
1049 struct ws2_async *wsa = HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async ) );
1050
1051 TRACE ( "wsa %p\n", wsa );
1052
1053 if (!wsa)
1054 return NULL;
1055
1056 wsa->async.ops = ( lpCompletionRoutine ? &ws2_async_ops : &ws2_nocomp_async_ops );
1057 wsa->async.handle = (HANDLE) s;
1058 wsa->async.fd = fd;
1059 wsa->async.type = type;
1060 switch (type)
1061 {
1062 case ASYNC_TYPE_READ:
1063 wsa->flags = *lpFlags;
1064 wsa->async.func = WS2_async_recv;
1065 wsa->addrlen.ptr = addrlen;
1066 break;
1067 case ASYNC_TYPE_WRITE:
1068 wsa->flags = 0;
1069 wsa->async.func = WS2_async_send;
1070 wsa->addrlen.val = *addrlen;
1071 break;
1072 default:
1073 ERR ("Invalid async type: %d\n", type);
1074 }
1075 wsa->user_overlapped = lpOverlapped;
1076 wsa->completion_func = lpCompletionRoutine;
1077 wsa->iovec = iovec;
1078 wsa->n_iovecs = dwBufferCount;
1079 wsa->addr = addr;
1080
1081 if ( lpOverlapped )
1082 {
1083 wsa->overlapped = lpOverlapped;
1084 wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
1085 }
1086 else
1087 {
1088 wsa->overlapped = HeapAlloc ( GetProcessHeap(), 0,
1089 sizeof (WSAOVERLAPPED) );
1090 if ( !wsa->overlapped )
1091 goto error;
1092 wsa->async.event = wsa->overlapped->hEvent = INVALID_HANDLE_VALUE;
1093 }
1094
1095 wsa->overlapped->InternalHigh = 0;
1096 TRACE ( "wsa %p, ops %p, h %d, ev %d, fd %d, func %p, ov %p, uov %p, cfunc %p\n",
1097 wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
1098 wsa->overlapped, wsa->user_overlapped, wsa->completion_func );
1099
1100 return wsa;
1101
1102error:
1103 TRACE ("Error\n");
1104 HeapFree ( GetProcessHeap(), 0, wsa );
1105 return NULL;
1106}
1107
1108/***********************************************************************
1109 * WS2_recv (INTERNAL)
1110 *
1111 * Work horse for both synchronous and asynchronous recv() operations.
1112 */
1113static int WS2_recv ( int fd, struct iovec* iov, int count,
1114 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1115 LPDWORD lpFlags )
1116{
1117 struct msghdr hdr;
1118 int n;
1119 TRACE ( "fd %d, iovec %p, count %d addr %p, len %p, flags %lx\n",
1120 fd, iov, count, lpFrom, lpFromlen, *lpFlags);
1121
1122 hdr.msg_name = NULL;
1123
1124 if ( lpFrom )
1125 {
1126#if DEBUG_SOCKADDR
1127 dump_sockaddr (lpFrom);
1128#endif
1129
1130 hdr.msg_namelen = *lpFromlen;
1131 hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
1132 if ( !hdr.msg_name )
1133 {
1134 WSASetLastError ( WSAEFAULT );
1135 n = -1;
1136 goto out;
1137 }
1138 }
1139 else
1140 hdr.msg_namelen = 0;
1141
1142 hdr.msg_iov = iov;
1143 hdr.msg_iovlen = count;
Alexandre Julliardd8d313d2002-05-16 23:12:03 +00001144#ifdef HAVE_MSGHDR_ACCRIGHTS
1145 hdr.msg_accrights = NULL;
1146 hdr.msg_accrightslen = 0;
1147#else
Martin Wilckaf16c982002-04-25 21:34:24 +00001148 hdr.msg_control = NULL;
1149 hdr.msg_controllen = 0;
1150 hdr.msg_flags = 0;
Alexandre Julliardd8d313d2002-05-16 23:12:03 +00001151#endif
Martin Wilckaf16c982002-04-25 21:34:24 +00001152
1153 if ( (n = recvmsg (fd, &hdr, *lpFlags)) == -1 )
1154 {
1155 TRACE ( "recvmsg error %d\n", errno);
1156 goto out;
1157 }
1158
1159 if ( lpFrom &&
1160 ws_sockaddr_u2ws ( hdr.msg_name, hdr.msg_namelen,
1161 lpFrom, lpFromlen ) != 0 )
1162 {
1163 /* The from buffer was too small, but we read the data
1164 * anyway. Is that really bad?
1165 */
1166 WSASetLastError ( WSAEFAULT );
1167 WARN ( "Address buffer too small\n" );
1168 }
1169
1170out:
1171
1172 ws_sockaddr_free ( hdr.msg_name, lpFrom );
1173 TRACE ("-> %d\n", n);
1174 return n;
1175}
1176
1177/***********************************************************************
1178 * WS2_async_recv (INTERNAL)
1179 *
1180 * Handler for overlapped recv() operations.
1181 */
1182static void WS2_async_recv ( async_private *as )
1183{
1184 ws2_async* wsa = (ws2_async*) as;
1185 int result, err;
1186
1187 TRACE ( "async %p\n", wsa );
1188
1189 if ( wsa->overlapped->Internal != STATUS_PENDING )
1190 {
1191 TRACE ( "status: %ld\n", wsa->overlapped->Internal );
1192 return;
1193 }
1194
1195 result = WS2_recv ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1196 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1197
1198 if (result >= 0)
1199 {
1200 wsa->overlapped->Internal = STATUS_SUCCESS;
1201 wsa->overlapped->InternalHigh = result;
1202 TRACE ( "received %d bytes\n", result );
1203 _enable_event ( (SOCKET) wsa->async.handle, FD_READ, 0, 0 );
1204 return;
1205 }
1206
1207 err = wsaErrno ();
1208 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1209 {
1210 wsa->overlapped->Internal = STATUS_PENDING;
1211 _enable_event ( (SOCKET) wsa->async.handle, FD_READ, 0, 0 );
1212 TRACE ( "still pending\n" );
1213 }
1214 else
1215 {
1216 wsa->overlapped->Internal = err;
1217 TRACE ( "Error: %x\n", err );
1218 }
1219}
1220
1221/***********************************************************************
1222 * WS2_send (INTERNAL)
1223 *
1224 * Work horse for both synchronous and asynchronous send() operations.
1225 */
1226static int WS2_send ( int fd, struct iovec* iov, int count,
1227 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1228{
1229 struct msghdr hdr;
1230 int n = -1;
1231 TRACE ( "fd %d, iovec %p, count %d addr %p, len %d, flags %lx\n",
1232 fd, iov, count, to, tolen, dwFlags);
1233
1234 hdr.msg_name = NULL;
1235
1236 if ( to )
1237 {
1238#if DEBUG_SOCKADDR
1239 dump_sockaddr (to);
1240#endif
1241 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
1242 if ( !hdr.msg_name )
1243 {
1244 WSASetLastError ( WSAEFAULT );
1245 goto out;
1246 }
1247 }
1248 else
1249 hdr.msg_namelen = 0;
1250
1251 hdr.msg_iov = iov;
1252 hdr.msg_iovlen = count;
Alexandre Julliardd8d313d2002-05-16 23:12:03 +00001253#ifdef HAVE_MSGHDR_ACCRIGHTS
1254 hdr.msg_accrights = NULL;
1255 hdr.msg_accrightslen = 0;
1256#else
Martin Wilckaf16c982002-04-25 21:34:24 +00001257 hdr.msg_control = NULL;
1258 hdr.msg_controllen = 0;
1259 hdr.msg_flags = 0;
Alexandre Julliardd8d313d2002-05-16 23:12:03 +00001260#endif
Martin Wilckaf16c982002-04-25 21:34:24 +00001261
1262 n = sendmsg (fd, &hdr, dwFlags);
1263
1264out:
1265 ws_sockaddr_free ( hdr.msg_name, to );
1266 return n;
1267}
1268
1269/***********************************************************************
1270 * WS2_async_send (INTERNAL)
1271 *
1272 * Handler for overlapped send() operations.
1273 */
1274static void WS2_async_send ( async_private *as )
1275{
1276 ws2_async* wsa = (ws2_async*) as;
1277 int result, err;
1278
1279 TRACE ( "async %p\n", wsa );
1280
1281 if ( wsa->overlapped->Internal != STATUS_PENDING )
1282 {
1283 TRACE ( "status: %ld\n", wsa->overlapped->Internal );
1284 return;
1285 }
1286
1287 result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1288 wsa->addr, wsa->addrlen.val, wsa->flags );
1289
1290 if (result >= 0)
1291 {
1292 wsa->overlapped->Internal = STATUS_SUCCESS;
1293 wsa->overlapped->InternalHigh = result;
1294 TRACE ( "sent %d bytes\n", result );
1295 _enable_event ( (SOCKET) wsa->async.handle, FD_WRITE, 0, 0 );
1296 return;
1297 }
1298
1299 err = wsaErrno ();
1300 if ( err == WSAEINTR )
1301 {
1302 wsa->overlapped->Internal = STATUS_PENDING;
1303 _enable_event ( (SOCKET) wsa->async.handle, FD_WRITE, 0, 0 );
1304 TRACE ( "still pending\n" );
1305 }
1306 else
1307 {
1308 /* We set the status to a winsock error code and check for that
1309 later in NtStatusToWSAError () */
1310 wsa->overlapped->Internal = err;
1311 TRACE ( "Error: %x\n", err );
1312 }
1313}
1314
1315/***********************************************************************
1316 * WS2_async_shutdown (INTERNAL)
1317 *
1318 * Handler for shutdown() operations on overlapped sockets.
1319 */
1320static void WS2_async_shutdown ( async_private *as )
1321{
1322 ws2_async* wsa = (ws2_async*) as;
1323 int err = 1;
1324
1325 TRACE ( "async %p %d\n", wsa, wsa->async.type );
1326 switch ( wsa->async.type )
1327 {
1328 case ASYNC_TYPE_READ:
1329 err = shutdown ( wsa->async.fd, 0 );
1330 break;
1331 case ASYNC_TYPE_WRITE:
1332 err = shutdown ( wsa->async.fd, 1 );
1333 break;
1334 default:
1335 ERR ("invalid type: %d\n", wsa->async.type );
1336 }
1337
1338 if ( err )
1339 wsa->overlapped->Internal = wsaErrno ();
1340 else
1341 wsa->overlapped->Internal = STATUS_SUCCESS;
1342}
1343
1344/***********************************************************************
1345 * WS2_register_async_shutdown (INTERNAL)
1346 *
1347 * Helper function for WS_shutdown() on overlapped sockets.
1348 */
1349static int WS2_register_async_shutdown ( SOCKET s, int fd, int type )
1350{
1351 struct ws2_async *wsa;
1352 int ret, err = WSAEFAULT;
1353 DWORD dwflags = 0;
1354 int len = 0;
1355 LPWSAOVERLAPPED ovl = HeapAlloc (GetProcessHeap(), 0, sizeof ( WSAOVERLAPPED ));
1356
1357 TRACE ("s %d fd %d type %d\n", s, fd, type);
1358 if (!ovl)
1359 goto out;
1360
1361 ovl->hEvent = WSACreateEvent ();
1362 if ( ovl->hEvent == WSA_INVALID_EVENT )
1363 goto out_free;
1364
1365 wsa = WS2_make_async ( s, fd, type, NULL, 0,
1366 &dwflags, NULL, &len, ovl, NULL );
1367 if ( !wsa )
1368 goto out_close;
1369
1370 /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
1371 wsa->user_overlapped = NULL;
1372 wsa->async.func = WS2_async_shutdown;
1373 if ( (ret = register_new_async ( &wsa->async )) )
1374 {
1375 err = NtStatusToWSAError ( ret );
1376 ws2_async_cleanup ( &wsa->async );
1377 goto out;
1378 }
1379 return 0;
1380
1381out_close:
1382 WSACloseEvent ( ovl->hEvent );
1383out_free:
1384 HeapFree ( GetProcessHeap(), 0, ovl );
1385out:
1386 return err;
1387}
1388
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001389/***********************************************************************
1390 * accept (WS2_32.1)
1391 */
Francois Gouget27202312001-11-14 21:26:23 +00001392SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001393 int *addrlen32)
1394{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001395 int fd = _get_sock_fd(s);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001396
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001397 TRACE("socket %04x\n", (UINT16)s );
1398 if (fd != -1)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001399 {
Alexandre Julliard92643002000-08-31 01:59:51 +00001400 SOCKET as;
Ove Kaavenf45608f1999-10-23 16:53:34 +00001401 if (_is_blocking(s))
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001402 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001403 /* block here */
Ove Kaavenf45608f1999-10-23 16:53:34 +00001404 do_block(fd, 5);
Ove Kaavenf45608f1999-10-23 16:53:34 +00001405 _sync_sock_state(s); /* let wineserver notice connection */
1406 /* retrieve any error codes from it */
1407 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1408 /* FIXME: care about the error? */
1409 }
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001410 close(fd);
Alexandre Julliard67a74992001-02-27 02:09:16 +00001411 SERVER_START_REQ( accept_socket )
Alexandre Julliard92643002000-08-31 01:59:51 +00001412 {
Alexandre Julliard92643002000-08-31 01:59:51 +00001413 req->lhandle = s;
1414 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1415 req->inherit = TRUE;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00001416 set_error( wine_server_call( req ) );
1417 as = (SOCKET)reply->handle;
Alexandre Julliard92643002000-08-31 01:59:51 +00001418 }
1419 SERVER_END_REQ;
Alexandre Julliard8081e5a2001-01-05 04:08:07 +00001420 if (as)
Ove Kaavenf45608f1999-10-23 16:53:34 +00001421 {
Paul Rupe8111f042001-11-30 23:12:13 +00001422 WS_getpeername(as, addr, addrlen32);
Ove Kaavencb98a6e2000-03-26 18:21:16 +00001423 return as;
Ove Kaavenf45608f1999-10-23 16:53:34 +00001424 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001425 }
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001426 else
1427 {
1428 SetLastError(WSAENOTSOCK);
1429 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001430 return INVALID_SOCKET;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001431}
1432
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001433/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001434 * accept (WINSOCK.1)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001435 */
Francois Gouget27202312001-11-14 21:26:23 +00001436SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct WS_sockaddr* addr,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001437 INT16* addrlen16 )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001438{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001439 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
Francois Gouget27202312001-11-14 21:26:23 +00001440 SOCKET retSocket = WS_accept( s, addr, &addrlen32 );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001441 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001442 return (SOCKET16)retSocket;
1443}
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001444
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001445/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001446 * bind (WS2_32.2)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001447 */
Francois Gouget27202312001-11-14 21:26:23 +00001448int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001449{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001450 int fd = _get_sock_fd(s);
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001451 int res;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001452
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001453 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001454#if DEBUG_SOCKADDR
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001455 dump_sockaddr(name);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001456#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001457
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001458 res=SOCKET_ERROR;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001459 if (fd != -1)
Jesper Skov5c3e4571998-11-01 19:27:22 +00001460 {
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001461 if (!name || !SUPPORTED_PF(name->sa_family))
Jesper Skov5c3e4571998-11-01 19:27:22 +00001462 {
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001463 SetLastError(WSAEAFNOSUPPORT);
1464 }
1465 else
1466 {
1467 const struct sockaddr* uaddr;
1468 int uaddrlen;
1469
1470 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1471 if (uaddr == NULL)
1472 {
1473 SetLastError(WSAEFAULT);
1474 }
1475 else
1476 {
1477 if (bind(fd, uaddr, uaddrlen) < 0)
1478 {
1479 int loc_errno = errno;
1480 WARN("\tfailure - errno = %i\n", errno);
1481 errno = loc_errno;
1482 switch (errno)
1483 {
1484 case EBADF:
1485 SetLastError(WSAENOTSOCK);
1486 break;
1487 case EADDRNOTAVAIL:
1488 SetLastError(WSAEINVAL);
1489 break;
1490 default:
1491 SetLastError(wsaErrno());
1492 break;
1493 }
1494 }
1495 else
1496 {
1497 res=0; /* success */
1498 }
1499 ws_sockaddr_free(uaddr,name);
1500 }
1501 }
1502 close(fd);
Jesper Skov5c3e4571998-11-01 19:27:22 +00001503 }
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001504 else
1505 {
1506 SetLastError(WSAENOTSOCK);
1507 }
1508 return res;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001509}
1510
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001511/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001512 * bind (WINSOCK.2)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001513 */
Francois Gouget27202312001-11-14 21:26:23 +00001514INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001515{
Francois Gouget27202312001-11-14 21:26:23 +00001516 return (INT16)WS_bind( s, name, namelen );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001517}
1518
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001519/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001520 * closesocket (WS2_32.3)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001521 */
Francois Gouget27202312001-11-14 21:26:23 +00001522int WINAPI WS_closesocket(SOCKET s)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001523{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001524 TRACE("socket %08x\n", s);
1525 if (CloseHandle(s)) return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001526 return SOCKET_ERROR;
1527}
1528
1529/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001530 * closesocket (WINSOCK.3)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001531 */
1532INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
1533{
Francois Gouget27202312001-11-14 21:26:23 +00001534 return (INT16)WS_closesocket(s);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001535}
1536
1537/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001538 * connect (WS2_32.4)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001539 */
Francois Gouget27202312001-11-14 21:26:23 +00001540int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001541{
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001542 int fd = _get_sock_fd(s);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001543
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001544 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001545#if DEBUG_SOCKADDR
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001546 dump_sockaddr(name);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001547#endif
1548
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001549 if (fd != -1)
Stephen Langasek12392cd1998-11-14 16:47:09 +00001550 {
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001551 const struct sockaddr* uaddr;
1552 int uaddrlen;
1553
1554 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1555 if (uaddr == NULL)
1556 {
1557 SetLastError(WSAEFAULT);
1558 }
1559 else
1560 {
1561 int rc;
1562
1563 rc=connect(fd, uaddr, uaddrlen);
1564 ws_sockaddr_free(uaddr,name);
1565 if (rc == 0)
1566 goto connect_success;
1567 }
1568
1569 if (errno == EINPROGRESS)
1570 {
1571 /* tell wineserver that a connection is in progress */
1572 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1573 FD_CONNECT|FD_READ|FD_WRITE,
1574 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1575 if (_is_blocking(s))
1576 {
1577 int result;
1578 /* block here */
1579 do_block(fd, 7);
1580 _sync_sock_state(s); /* let wineserver notice connection */
1581 /* retrieve any error codes from it */
1582 result = _get_sock_error(s, FD_CONNECT_BIT);
1583 if (result)
1584 SetLastError(result);
1585 else
1586 {
1587 goto connect_success;
1588 }
1589 }
1590 else
1591 {
1592 SetLastError(WSAEWOULDBLOCK);
1593 }
1594 }
1595 else
1596 {
1597 SetLastError(wsaErrno());
1598 }
1599 close(fd);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001600 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00001601 else
1602 {
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001603 SetLastError(WSAENOTSOCK);
Ove Kaavenf45608f1999-10-23 16:53:34 +00001604 }
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001605 return SOCKET_ERROR;
1606
Ove Kaavenf45608f1999-10-23 16:53:34 +00001607connect_success:
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001608 close(fd);
Ove Kaavenf45608f1999-10-23 16:53:34 +00001609 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001610 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1611 FD_CONNECT|FD_WINE_LISTENING);
1612 return 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001613}
1614
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001615/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001616 * connect (WINSOCK.4)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001617 */
Francois Gouget27202312001-11-14 21:26:23 +00001618INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001619{
Francois Gouget27202312001-11-14 21:26:23 +00001620 return (INT16)WS_connect( s, name, namelen );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001621}
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001622
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001623/***********************************************************************
Martin Wilckd15bf1c2002-04-23 22:03:42 +00001624 * WSAConnect (WS2_32.30)
1625 */
1626int WINAPI WSAConnect ( SOCKET s, const struct WS_sockaddr* name, int namelen,
1627 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1628 LPQOS lpSQOS, LPQOS lpGQOS )
1629{
1630 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1631 FIXME ("unsupported parameters!\n");
1632 return WS_connect ( s, name, namelen );
1633}
1634
1635
1636/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001637 * getpeername (WS2_32.5)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001638 */
Francois Gouget27202312001-11-14 21:26:23 +00001639int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001640{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001641 int fd = _get_sock_fd(s);
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001642 int res;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001643
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001644 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1645
1646 res=SOCKET_ERROR;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001647 if (fd != -1)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001648 {
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001649 struct sockaddr* uaddr;
1650 int uaddrlen;
1651
1652 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1653 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1654 {
1655 SetLastError(wsaErrno());
1656 }
1657 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1658 {
1659 /* The buffer was too small */
1660 SetLastError(WSAEFAULT);
1661 }
1662 else
1663 {
1664 res=0;
1665 }
1666 ws_sockaddr_free(uaddr,name);
1667 close(fd);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001668 }
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001669 else
1670 {
1671 SetLastError(WSAENOTSOCK);
1672 }
1673 return res;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001674}
1675
1676/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001677 * getpeername (WINSOCK.5)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001678 */
Francois Gouget27202312001-11-14 21:26:23 +00001679INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct WS_sockaddr *name,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001680 INT16 *namelen16)
1681{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001682 INT namelen32 = *namelen16;
Francois Gouget27202312001-11-14 21:26:23 +00001683 INT retVal = WS_getpeername( s, name, &namelen32 );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001684
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001685#if DEBUG_SOCKADDR
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001686 dump_sockaddr(name);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001687#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001688
1689 *namelen16 = namelen32;
1690 return (INT16)retVal;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001691}
1692
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001693/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001694 * getsockname (WS2_32.6)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001695 */
Francois Gouget27202312001-11-14 21:26:23 +00001696int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001697{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001698 int fd = _get_sock_fd(s);
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001699 int res;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001700
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001701 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1702
1703 res=SOCKET_ERROR;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001704 if (fd != -1)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001705 {
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001706 struct sockaddr* uaddr;
1707 int uaddrlen;
1708
1709 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1710 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1711 {
1712 SetLastError(wsaErrno());
1713 }
1714 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1715 {
1716 /* The buffer was too small */
1717 SetLastError(WSAEFAULT);
1718 }
1719 else
1720 {
1721 res=0;
1722 }
1723 close(fd);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001724 }
Francois Gouget76f6ffa2001-10-08 20:36:03 +00001725 else
1726 {
1727 SetLastError(WSAENOTSOCK);
1728 }
1729 return res;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001730}
1731
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001732/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001733 * getsockname (WINSOCK.6)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001734 */
Francois Gouget27202312001-11-14 21:26:23 +00001735INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct WS_sockaddr *name,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001736 INT16 *namelen16)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001737{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001738 INT retVal;
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001739
1740 if( namelen16 )
1741 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001742 INT namelen32 = *namelen16;
Francois Gouget27202312001-11-14 21:26:23 +00001743 retVal = WS_getsockname( s, name, &namelen32 );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001744 *namelen16 = namelen32;
1745
1746#if DEBUG_SOCKADDR
1747 dump_sockaddr(name);
1748#endif
1749
1750 }
1751 else retVal = SOCKET_ERROR;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001752 return (INT16)retVal;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001753}
1754
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001755
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001756/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001757 * getsockopt (WS2_32.7)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001758 */
Francois Gouget27202312001-11-14 21:26:23 +00001759INT WINAPI WS_getsockopt(SOCKET s, INT level,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001760 INT optname, char *optval, INT *optlen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001761{
Paul Rupe99ed3422001-12-14 22:48:38 +00001762 int fd;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001763
Paul Rupe99ed3422001-12-14 22:48:38 +00001764 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1765 (int) optname, (int) optval, (int) *optlen);
1766 /* SO_OPENTYPE does not require a valid socket handle. */
1767 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1768 {
1769 if (!optlen || *optlen < sizeof(int) || !optval)
1770 {
1771 SetLastError(WSAEFAULT);
1772 return SOCKET_ERROR;
1773 }
Martin Wilckcf518bc2002-04-27 01:05:35 +00001774 *(int *)optval = (int)TlsGetValue( opentype_tls_index );
Paul Rupe99ed3422001-12-14 22:48:38 +00001775 *optlen = sizeof(int);
Martin Wilckcf518bc2002-04-27 01:05:35 +00001776 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
Paul Rupe99ed3422001-12-14 22:48:38 +00001777 return 0;
1778 }
1779
1780 fd = _get_sock_fd(s);
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001781 if (fd != -1)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001782 {
John Gilmore5180d562000-09-16 20:51:40 +00001783 if (!convert_sockopt(&level, &optname)) {
1784 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1785 } else {
1786 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1787 {
1788 close(fd);
1789 return 0;
1790 }
1791 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
Ove Kaavenf45608f1999-10-23 16:53:34 +00001792 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00001793 close(fd);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001794 }
1795 return SOCKET_ERROR;
1796}
1797
Francois Gouget27202312001-11-14 21:26:23 +00001798
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001799/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001800 * getsockopt (WINSOCK.7)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001801 */
1802INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1803 INT16 optname, char *optval, INT16 *optlen)
1804{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001805 INT optlen32;
1806 INT *p = &optlen32;
1807 INT retVal;
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001808 if( optlen ) optlen32 = *optlen; else p = NULL;
Francois Gouget27202312001-11-14 21:26:23 +00001809 retVal = WS_getsockopt( s, (UINT16)level, optname, optval, p );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001810 if( optlen ) *optlen = optlen32;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001811 return (INT16)retVal;
1812}
1813
Francois Gouget27202312001-11-14 21:26:23 +00001814
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001815/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001816 * htonl (WINSOCK.8)
1817 * htonl (WS2_32.8)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001818 */
Francois Gouget27202312001-11-14 21:26:23 +00001819u_long WINAPI WS_htonl(u_long hostlong)
1820{
1821 return htonl(hostlong);
1822}
1823
1824
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001825/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001826 * htons (WINSOCK.9)
1827 * htons (WS2_32.9)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001828 */
Francois Gouget27202312001-11-14 21:26:23 +00001829u_short WINAPI WS_htons(u_short hostshort)
1830{
1831 return htons(hostshort);
1832}
1833
1834
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001835/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001836 * inet_addr (WINSOCK.10)
1837 * inet_addr (WS2_32.11)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001838 */
Francois Gouget27202312001-11-14 21:26:23 +00001839u_long WINAPI WS_inet_addr(const char *cp)
1840{
1841 return inet_addr(cp);
1842}
1843
1844
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001845/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001846 * ntohl (WINSOCK.14)
1847 * ntohl (WS2_32.14)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001848 */
Francois Gouget27202312001-11-14 21:26:23 +00001849u_long WINAPI WS_ntohl(u_long netlong)
1850{
1851 return ntohl(netlong);
1852}
1853
1854
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001855/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001856 * ntohs (WINSOCK.15)
1857 * ntohs (WS2_32.15)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001858 */
Francois Gouget27202312001-11-14 21:26:23 +00001859u_short WINAPI WS_ntohs(u_short netshort)
1860{
1861 return ntohs(netshort);
1862}
1863
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001864
1865/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001866 * inet_ntoa (WS2_32.12)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001867 */
Francois Gouget27202312001-11-14 21:26:23 +00001868char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001869{
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001870 /* use "buffer for dummies" here because some applications have
1871 * propensity to decode addresses in ws_hostent structure without
1872 * saving them first...
1873 */
Alexandre Julliard85129792001-12-24 20:30:24 +00001874 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1875
Francois Gouget27202312001-11-14 21:26:23 +00001876 char* s = inet_ntoa(*((struct in_addr*)&in));
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001877 if( s )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001878 {
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001879 strcpy(dbuffer, s);
1880 return dbuffer;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001881 }
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001882 SetLastError(wsaErrno());
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001883 return NULL;
1884}
1885
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00001886/***********************************************************************
1887 * inet_ntoa (WINSOCK.11)
1888 */
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001889SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1890{
Alexandre Julliard85129792001-12-24 20:30:24 +00001891 char* retVal;
1892 if (!(retVal = WS_inet_ntoa(*((struct WS_in_addr*)&in)))) return 0;
1893 if (!dbuffer_seg) dbuffer_seg = MapLS( retVal );
1894 return dbuffer_seg;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001895}
1896
James Hathewayc9d25822000-07-23 19:28:24 +00001897
1898/**********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +00001899 * WSAIoctl (WS2_32.50)
James Hathewayc9d25822000-07-23 19:28:24 +00001900 *
1901 *
1902 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1903 */
1904INT WINAPI WSAIoctl (SOCKET s,
1905 DWORD dwIoControlCode,
1906 LPVOID lpvInBuffer,
1907 DWORD cbInBuffer,
1908 LPVOID lpbOutBuffer,
1909 DWORD cbOutBuffer,
1910 LPDWORD lpcbBytesReturned,
1911 LPWSAOVERLAPPED lpOverlapped,
1912 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1913{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001914 int fd = _get_sock_fd(s);
James Hathewayc9d25822000-07-23 19:28:24 +00001915
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00001916 if (fd != -1)
James Hathewayc9d25822000-07-23 19:28:24 +00001917 {
James Hathewayc9d25822000-07-23 19:28:24 +00001918 switch( dwIoControlCode )
1919 {
1920 case SIO_GET_INTERFACE_LIST:
1921 {
1922 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1923 int i, numInt;
1924 struct ifreq ifInfo;
1925 char ifName[512];
1926
1927
1928 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1929
1930 numInt = WSAIOCTL_GetInterfaceCount();
1931 if (numInt < 0)
1932 {
1933 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1934 close(fd);
1935 WSASetLastError(WSAEINVAL);
1936 return (SOCKET_ERROR);
1937 }
1938
1939 for (i=0; i<numInt; i++)
1940 {
1941 if (!WSAIOCTL_GetInterfaceName(i, ifName))
1942 {
1943 ERR ("Error parsing /proc filesystem!\n");
1944 close(fd);
1945 WSASetLastError(WSAEINVAL);
1946 return (SOCKET_ERROR);
1947 }
1948
1949 ifInfo.ifr_addr.sa_family = AF_INET;
1950
1951 /* IP Address */
1952 strcpy (ifInfo.ifr_name, ifName);
1953 if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
1954 {
1955 ERR ("Error obtaining IP address\n");
1956 close(fd);
1957 WSASetLastError(WSAEINVAL);
1958 return (SOCKET_ERROR);
1959 }
1960 else
1961 {
Francois Gouget27202312001-11-14 21:26:23 +00001962 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_addr;
James Hathewayc9d25822000-07-23 19:28:24 +00001963
1964 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1965 intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
Francois Gouget27202312001-11-14 21:26:23 +00001966 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
James Hathewayc9d25822000-07-23 19:28:24 +00001967 }
1968
1969 /* Broadcast Address */
1970 strcpy (ifInfo.ifr_name, ifName);
1971 if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1972 {
1973 ERR ("Error obtaining Broadcast IP address\n");
1974 close(fd);
1975 WSASetLastError(WSAEINVAL);
1976 return (SOCKET_ERROR);
1977 }
1978 else
1979 {
Francois Gouget27202312001-11-14 21:26:23 +00001980 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_broadaddr;
James Hathewayc9d25822000-07-23 19:28:24 +00001981
1982 intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
1983 intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
Francois Gouget27202312001-11-14 21:26:23 +00001984 intArray->iiBroadcastAddress.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
James Hathewayc9d25822000-07-23 19:28:24 +00001985 }
1986
1987 /* Subnet Mask */
1988 strcpy (ifInfo.ifr_name, ifName);
1989 if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
1990 {
1991 ERR ("Error obtaining Subnet IP address\n");
1992 close(fd);
1993 WSASetLastError(WSAEINVAL);
1994 return (SOCKET_ERROR);
1995 }
1996 else
1997 {
James Hathewaybf3e2e9f2000-07-25 17:45:50 +00001998 /* Trying to avoid some compile problems across platforms.
1999 (Linux, FreeBSD, Solaris...) */
2000 #ifndef ifr_netmask
2001 #ifndef ifr_addr
2002 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2003 intArray->iiNetmask.AddressIn.sin_port = 0;
Francois Gouget27202312001-11-14 21:26:23 +00002004 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = 0;
James Hathewaybf3e2e9f2000-07-25 17:45:50 +00002005 ERR ("Unable to determine Netmask on your platform!\n");
2006 #else
Francois Gouget27202312001-11-14 21:26:23 +00002007 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_addr;
James Hathewayc9d25822000-07-23 19:28:24 +00002008
James Hathewaybf3e2e9f2000-07-25 17:45:50 +00002009 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2010 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
Francois Gouget27202312001-11-14 21:26:23 +00002011 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
James Hathewaybf3e2e9f2000-07-25 17:45:50 +00002012 #endif
2013 #else
Francois Gouget27202312001-11-14 21:26:23 +00002014 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_netmask;
James Hathewaybf3e2e9f2000-07-25 17:45:50 +00002015
2016 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2017 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
Francois Gouget27202312001-11-14 21:26:23 +00002018 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
James Hathewaybf3e2e9f2000-07-25 17:45:50 +00002019 #endif
James Hathewayc9d25822000-07-23 19:28:24 +00002020 }
2021
2022 /* Socket Status Flags */
2023 strcpy(ifInfo.ifr_name, ifName);
2024 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
2025 {
2026 ERR ("Error obtaining status flags for socket!\n");
2027 close(fd);
2028 WSASetLastError(WSAEINVAL);
2029 return (SOCKET_ERROR);
2030 }
2031 else
2032 {
2033 /* FIXME - Is this the right flag to use? */
2034 intArray->iiFlags = ifInfo.ifr_flags;
2035 }
2036 intArray++; /* Prepare for another interface */
2037 }
2038
2039 /* Calculate the size of the array being returned */
2040 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2041 break;
2042 }
2043
2044 default:
2045 {
2046 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2047 close(fd);
2048 WSASetLastError(WSAEOPNOTSUPP);
2049 return (SOCKET_ERROR);
2050 }
2051 }
2052
2053 /* Function executed with no errors */
2054 close(fd);
2055 return (0);
2056 }
2057 else
2058 {
2059 WSASetLastError(WSAENOTSOCK);
2060 return (SOCKET_ERROR);
2061 }
2062}
2063
2064
2065/*
2066 Helper function for WSAIoctl - Get count of the number of interfaces
2067 by parsing /proc filesystem.
2068*/
2069int WSAIOCTL_GetInterfaceCount(void)
2070{
2071 FILE *procfs;
2072 char buf[512]; /* Size doesn't matter, something big */
2073 int intcnt=0;
2074
2075
2076 /* Open /proc filesystem file for network devices */
2077 procfs = fopen(PROCFS_NETDEV_FILE, "r");
2078 if (!procfs)
2079 {
2080 /* If we can't open the file, return an error */
2081 return (-1);
2082 }
2083
2084 /* Omit first two lines, they are only headers */
2085 fgets(buf, sizeof buf, procfs);
2086 fgets(buf, sizeof buf, procfs);
2087
2088 while (fgets(buf, sizeof buf, procfs))
2089 {
2090 /* Each line in the file represents a network interface */
2091 intcnt++;
2092 }
2093
2094 fclose(procfs);
2095 return(intcnt);
2096}
2097
2098
2099/*
2100 Helper function for WSAIoctl - Get name of device from interface number
2101 by parsing /proc filesystem.
2102*/
2103int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
2104{
2105 FILE *procfs;
2106 char buf[512]; /* Size doesn't matter, something big */
2107 int i;
2108
2109 /* Open /proc filesystem file for network devices */
2110 procfs = fopen(PROCFS_NETDEV_FILE, "r");
2111 if (!procfs)
2112 {
2113 /* If we can't open the file, return an error */
2114 return (-1);
2115 }
2116
2117 /* Omit first two lines, they are only headers */
2118 fgets(buf, sizeof(buf), procfs);
2119 fgets(buf, sizeof(buf), procfs);
2120
2121 for (i=0; i<intNumber; i++)
2122 {
2123 /* Skip the lines that don't interest us. */
2124 fgets(buf, sizeof(buf), procfs);
2125 }
2126 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
2127
2128
2129 /* Parse out the line, grabbing only the name of the device
2130 to the intName variable
2131
2132 The Line comes in like this: (we only care about the device name)
2133 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
2134 */
2135 i=0;
2136 while (isspace(buf[i])) /* Skip initial space(s) */
2137 {
2138 i++;
2139 }
2140
2141 while (buf[i])
2142 {
2143 if (isspace(buf[i]))
2144 {
2145 break;
2146 }
2147
2148 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
2149 {
2150 /* This interface could be an alias... */
2151 int hold = i;
2152 char *dotname = intName;
2153 *intName++ = buf[i++];
2154
2155 while (isdigit(buf[i]))
2156 {
2157 *intName++ = buf[i++];
2158 }
2159
2160 if (buf[i] != ':')
2161 {
2162 /* ... It wasn't, so back up */
2163 i = hold;
2164 intName = dotname;
2165 }
2166
2167 if (buf[i] == '\0')
2168 {
2169 fclose(procfs);
2170 return(FALSE);
2171 }
2172
2173 i++;
2174 break;
2175 }
2176
2177 *intName++ = buf[i++];
2178 }
2179 *intName++ = '\0';
2180
2181 fclose(procfs);
2182 return(TRUE);
2183 }
2184
2185
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002186/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002187 * ioctlsocket (WS2_32.10)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002188 */
Francois Gouget27202312001-11-14 21:26:23 +00002189int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002190{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002191 int fd = _get_sock_fd(s);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002192
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002193 TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
2194 if (fd != -1)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002195 {
2196 long newcmd = cmd;
2197
2198 switch( cmd )
2199 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002200 case WS_FIONREAD:
2201 newcmd=FIONREAD;
2202 break;
2203
2204 case WS_FIONBIO:
2205 newcmd=FIONBIO;
Ove Kaavenf45608f1999-10-23 16:53:34 +00002206 if( _get_sock_mask(s) )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002207 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002208 /* AsyncSelect()'ed sockets are always nonblocking */
Ove Kaavend0c3e192000-02-14 19:50:57 +00002209 if (*argp) {
2210 close(fd);
2211 return 0;
2212 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002213 SetLastError(WSAEINVAL);
Ove Kaavenf45608f1999-10-23 16:53:34 +00002214 close(fd);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002215 return SOCKET_ERROR;
2216 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00002217 close(fd);
2218 if (*argp)
Francois Gouget126e6b82001-08-24 19:14:56 +00002219 _enable_event(s, 0, FD_WINE_NONBLOCKING, 0);
Ove Kaavenf45608f1999-10-23 16:53:34 +00002220 else
Francois Gouget126e6b82001-08-24 19:14:56 +00002221 _enable_event(s, 0, 0, FD_WINE_NONBLOCKING);
Ove Kaavenf45608f1999-10-23 16:53:34 +00002222 return 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002223
2224 case WS_SIOCATMARK:
2225 newcmd=SIOCATMARK;
2226 break;
2227
Francois Gouget27202312001-11-14 21:26:23 +00002228 case WS__IOW('f',125,u_long):
Alexandre Julliard61fece01999-06-26 19:09:08 +00002229 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002230 SetLastError(WSAEINVAL);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002231 return SOCKET_ERROR;
James Hatheway4bed8262001-01-17 20:19:14 +00002232
2233 case SIOCGIFBRDADDR:
2234 case SIOCGIFNETMASK:
2235 case SIOCGIFADDR:
2236 /* These don't need any special handling. They are used by
2237 WsControl, and are here to suppress an unecessary warning. */
2238 break;
2239
2240
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002241 default:
2242 /* Netscape tries hard to use bogus ioctl 0x667e */
Patrik Stridvallb8684a21999-07-31 17:32:05 +00002243 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002244 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00002245 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2246 {
2247 close(fd);
2248 return 0;
2249 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002250 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
Ove Kaavenf45608f1999-10-23 16:53:34 +00002251 close(fd);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002252 }
2253 return SOCKET_ERROR;
2254}
2255
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002256/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002257 * ioctlsocket (WINSOCK.12)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002258 */
Patrik Stridvallb8684a21999-07-31 17:32:05 +00002259INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002260{
Francois Gouget27202312001-11-14 21:26:23 +00002261 return (INT16)WS_ioctlsocket( s, cmd, argp );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002262}
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002263
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002264
2265/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002266 * listen (WS2_32.13)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002267 */
Francois Gouget27202312001-11-14 21:26:23 +00002268int WINAPI WS_listen(SOCKET s, int backlog)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002269{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002270 int fd = _get_sock_fd(s);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002271
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002272 TRACE("socket %04x, backlog %d\n", s, backlog);
2273 if (fd != -1)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002274 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00002275 if (listen(fd, backlog) == 0)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002276 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00002277 close(fd);
2278 _enable_event(s, FD_ACCEPT,
Francois Gouget126e6b82001-08-24 19:14:56 +00002279 FD_WINE_LISTENING,
2280 FD_CONNECT|FD_WINE_CONNECTED);
Alexandre Julliard17216f51997-10-12 16:30:17 +00002281 return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002282 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002283 SetLastError(wsaErrno());
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002284 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002285 else SetLastError(WSAENOTSOCK);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002286 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002287}
2288
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002289/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002290 * listen (WINSOCK.13)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002291 */
2292INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002293{
Francois Gouget27202312001-11-14 21:26:23 +00002294 return (INT16)WS_listen( s, backlog );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002295}
2296
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002297
2298/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002299 * recv (WS2_32.16)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002300 */
Francois Gouget27202312001-11-14 21:26:23 +00002301int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002302{
Martin Wilck58854432002-04-05 21:22:55 +00002303 DWORD n, dwFlags = flags;
2304 WSABUF wsabuf = { len, buf };
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002305
Martin Wilck58854432002-04-05 21:22:55 +00002306 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2307 return SOCKET_ERROR;
2308 else
2309 return n;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002310}
2311
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002312/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002313 * recv (WINSOCK.16)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002314 */
2315INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2316{
Francois Gouget27202312001-11-14 21:26:23 +00002317 return (INT16)WS_recv( s, buf, len, flags );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002318}
2319
2320
2321/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002322 * recvfrom (WS2_32.17)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002323 */
Francois Gouget27202312001-11-14 21:26:23 +00002324int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2325 struct WS_sockaddr *from, int *fromlen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002326{
Martin Wilck58854432002-04-05 21:22:55 +00002327 DWORD n, dwFlags = flags;
2328 WSABUF wsabuf = { len, buf };
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002329
Martin Wilck58854432002-04-05 21:22:55 +00002330 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2331 return SOCKET_ERROR;
Francois Gouget76f6ffa2001-10-08 20:36:03 +00002332 else
Martin Wilck58854432002-04-05 21:22:55 +00002333 return n;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002334}
2335
2336/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002337 * recvfrom (WINSOCK.17)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002338 */
2339INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
Francois Gouget27202312001-11-14 21:26:23 +00002340 struct WS_sockaddr *from, INT16 *fromlen16)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002341{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002342 INT fromlen32;
2343 INT *p = &fromlen32;
2344 INT retVal;
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00002345
2346 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
Francois Gouget27202312001-11-14 21:26:23 +00002347 retVal = WS_recvfrom( s, buf, len, flags, from, p );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00002348 if( fromlen16 ) *fromlen16 = fromlen32;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002349 return (INT16)retVal;
2350}
2351
2352/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002353 * __ws_select
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002354 */
Francois Gouget27202312001-11-14 21:26:23 +00002355static int __ws_select(BOOL b32,
Francois Gougetd97fe262001-09-14 00:19:52 +00002356 void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
Francois Gouget27202312001-11-14 21:26:23 +00002357 const struct WS_timeval *ws_timeout)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002358{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002359 int highfd = 0;
2360 fd_set readfds, writefds, exceptfds;
2361 fd_set *p_read, *p_write, *p_except;
2362 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
Gerard Patel03313742001-11-05 23:53:16 +00002363 struct timeval timeout, *timeoutaddr = NULL;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002364
Francois Gouget27202312001-11-14 21:26:23 +00002365 TRACE("read %p, write %p, excp %p timeout %p\n",
2366 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002367
2368 p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
2369 p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
2370 p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
Gerard Patel03313742001-11-05 23:53:16 +00002371 if (ws_timeout)
2372 {
2373 timeoutaddr = &timeout;
2374 timeout.tv_sec=ws_timeout->tv_sec;
2375 timeout.tv_usec=ws_timeout->tv_usec;
2376 }
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002377
Gerard Patel03313742001-11-05 23:53:16 +00002378 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00002379 {
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002380 fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
2381 fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002382
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002383 if (p_except && ws_exceptfds)
2384 {
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00002385#define wsfds16 ((ws_fd_set16*)ws_exceptfds)
Francois Gouget27202312001-11-14 21:26:23 +00002386#define wsfds32 ((WS_fd_set*)ws_exceptfds)
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002387 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00002388
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002389 for (i = j = 0; i < count; i++)
2390 {
2391 int fd = exceptfd[i];
2392 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
2393 {
2394 if( b32 )
2395 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
2396 else
2397 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
2398 }
2399 if( fd >= 0 ) close(fd);
2400 exceptfd[i] = -1;
2401 }
2402 if( b32 )
2403 wsfds32->fd_count = j;
2404 else
2405 wsfds16->fd_count = j;
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00002406#undef wsfds32
2407#undef wsfds16
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002408 }
2409 return highfd;
2410 }
2411 fd_set_unimport(ws_readfds, readfd, b32);
2412 fd_set_unimport(ws_writefds, writefd, b32);
2413 fd_set_unimport(ws_exceptfds, exceptfd, b32);
Francois Gouget27202312001-11-14 21:26:23 +00002414 if( ws_readfds ) ((WS_fd_set*)ws_readfds)->fd_count = 0;
2415 if( ws_writefds ) ((WS_fd_set*)ws_writefds)->fd_count = 0;
2416 if( ws_exceptfds ) ((WS_fd_set*)ws_exceptfds)->fd_count = 0;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00002417
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002418 if( highfd == 0 ) return 0;
2419 SetLastError(wsaErrno());
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00002420 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002421}
2422
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002423/***********************************************************************
2424 * select (WINSOCK.18)
2425 */
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00002426INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
2427 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
Francois Gouget27202312001-11-14 21:26:23 +00002428 struct WS_timeval* timeout)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00002429{
2430 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2431}
2432
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002433/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +00002434 * select (WS2_32.18)
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002435 */
Francois Gouget27202312001-11-14 21:26:23 +00002436int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2437 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2438 const struct WS_timeval* timeout)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002439{
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002440 /* struct timeval is the same for both 32- and 16-bit code */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002441 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002442}
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002443
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002444
2445/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002446 * send (WS2_32.19)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002447 */
Francois Gouget27202312001-11-14 21:26:23 +00002448int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002449{
Martin Wilck58854432002-04-05 21:22:55 +00002450 DWORD n;
2451 WSABUF wsabuf = { len, (char*) buf };
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002452
Martin Wilck58854432002-04-05 21:22:55 +00002453 if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2454 return SOCKET_ERROR;
2455 else
2456 return n;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002457}
2458
2459/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002460 * WSASend (WS2_32.72)
Peter Hunnisettde962af2001-04-10 21:22:34 +00002461 */
2462INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2463 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2464 LPWSAOVERLAPPED lpOverlapped,
2465 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2466{
Martin Wilck58854432002-04-05 21:22:55 +00002467 return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2468 NULL, 0, lpOverlapped, lpCompletionRoutine );
2469}
Peter Hunnisettde962af2001-04-10 21:22:34 +00002470
Martin Wilck58854432002-04-05 21:22:55 +00002471/***********************************************************************
2472 * WSASendTo (WS2_32.74)
2473 */
2474INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2475 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2476 const struct WS_sockaddr *to, int tolen,
2477 LPWSAOVERLAPPED lpOverlapped,
2478 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2479{
Martin Wilckaf16c982002-04-25 21:34:24 +00002480 int i, n, fd, err = WSAENOTSOCK, flags, ret;
Martin Wilck58854432002-04-05 21:22:55 +00002481 struct iovec* iovec;
Martin Wilckaf16c982002-04-25 21:34:24 +00002482 struct ws2_async *wsa;
Martin Wilckaba59472002-04-17 16:46:49 +00002483 enum fd_type type;
Peter Hunnisettde962af2001-04-10 21:22:34 +00002484
Martin Wilck58854432002-04-05 21:22:55 +00002485 TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2486 s, lpBuffers, dwBufferCount, dwFlags,
2487 to, tolen, lpOverlapped, lpCompletionRoutine);
Peter Hunnisettde962af2001-04-10 21:22:34 +00002488
Martin Wilckaf16c982002-04-25 21:34:24 +00002489 fd = _get_sock_fd_type( s, GENERIC_WRITE, &type, &flags );
2490 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
Peter Hunnisettde962af2001-04-10 21:22:34 +00002491
Martin Wilck58854432002-04-05 21:22:55 +00002492 if ( fd == -1 )
Martin Wilckaf16c982002-04-25 21:34:24 +00002493 {
2494 err = WSAGetLastError ();
Martin Wilck58854432002-04-05 21:22:55 +00002495 goto error;
Martin Wilckaf16c982002-04-25 21:34:24 +00002496 }
Peter Hunnisettde962af2001-04-10 21:22:34 +00002497
Martin Wilckff1f3202002-04-26 18:31:19 +00002498 iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
Martin Wilck58854432002-04-05 21:22:55 +00002499
2500 if ( !iovec )
Peter Hunnisettde962af2001-04-10 21:22:34 +00002501 {
Martin Wilckaf16c982002-04-25 21:34:24 +00002502 err = WSAEFAULT;
Martin Wilck58854432002-04-05 21:22:55 +00002503 goto err_close;
Peter Hunnisettde962af2001-04-10 21:22:34 +00002504 }
2505
Martin Wilck58854432002-04-05 21:22:55 +00002506 for ( i = 0; i < dwBufferCount; i++ )
2507 {
2508 iovec[i].iov_base = lpBuffers[i].buf;
2509 iovec[i].iov_len = lpBuffers[i].len;
2510 }
Peter Hunnisettde962af2001-04-10 21:22:34 +00002511
Martin Wilckaf16c982002-04-25 21:34:24 +00002512 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
Martin Wilck58854432002-04-05 21:22:55 +00002513 {
Martin Wilckaf16c982002-04-25 21:34:24 +00002514 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
2515 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2516 lpOverlapped, lpCompletionRoutine );
2517 if ( !wsa )
Martin Wilck58854432002-04-05 21:22:55 +00002518 {
2519 err = WSAEFAULT;
2520 goto err_free;
2521 }
Martin Wilckaf16c982002-04-25 21:34:24 +00002522
2523 if ( ( ret = register_new_async ( &wsa->async )) )
2524 {
2525 err = NtStatusToWSAError ( ret );
2526
2527 if ( !lpOverlapped )
2528 HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
2529 HeapFree ( GetProcessHeap(), 0, wsa );
2530 goto err_free;
2531 }
2532
2533 /* Try immediate completion */
2534 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
2535 {
2536 if ( WSAGetOverlappedResult ( (HANDLE) s, lpOverlapped,
2537 lpNumberOfBytesSent, FALSE, &dwFlags) )
2538 return 0;
2539
2540 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
2541 goto error;
2542 }
2543
2544 WSASetLastError ( WSA_IO_PENDING );
2545 return SOCKET_ERROR;
Martin Wilck58854432002-04-05 21:22:55 +00002546 }
Martin Wilck58854432002-04-05 21:22:55 +00002547
2548 if (_is_blocking(s))
2549 {
2550 /* FIXME: exceptfds? */
2551 do_block(fd, 2);
2552 }
2553
Martin Wilckaf16c982002-04-25 21:34:24 +00002554 n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2555 if ( n == -1 )
Martin Wilck58854432002-04-05 21:22:55 +00002556 {
2557 err = wsaErrno();
2558 if ( err == WSAEWOULDBLOCK )
2559 _enable_event (s, FD_WRITE, 0, 0);
2560 goto err_free;
2561 }
2562
Martin Wilckaf16c982002-04-25 21:34:24 +00002563 TRACE(" -> %i bytes\n", n);
Martin Wilck58854432002-04-05 21:22:55 +00002564 *lpNumberOfBytesSent = n;
2565
Martin Wilckaf16c982002-04-25 21:34:24 +00002566 HeapFree ( GetProcessHeap(), 0, iovec );
Martin Wilck58854432002-04-05 21:22:55 +00002567 close ( fd );
Martin Wilck58854432002-04-05 21:22:55 +00002568 return 0;
2569
2570err_free:
Martin Wilckaf16c982002-04-25 21:34:24 +00002571 HeapFree ( GetProcessHeap(), 0, iovec );
Martin Wilck58854432002-04-05 21:22:55 +00002572
2573err_close:
2574 close ( fd );
2575
2576error:
2577 WARN (" -> ERROR %d\n", err);
Martin Wilckaf16c982002-04-25 21:34:24 +00002578 WSASetLastError (err);
Martin Wilck58854432002-04-05 21:22:55 +00002579 return SOCKET_ERROR;
Peter Hunnisettde962af2001-04-10 21:22:34 +00002580}
2581
2582/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002583 * send (WINSOCK.19)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002584 */
2585INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2586{
Francois Gouget27202312001-11-14 21:26:23 +00002587 return WS_send( s, buf, len, flags );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002588}
2589
2590/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002591 * sendto (WS2_32.20)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002592 */
Francois Gouget27202312001-11-14 21:26:23 +00002593int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2594 const struct WS_sockaddr *to, int tolen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002595{
Martin Wilck58854432002-04-05 21:22:55 +00002596 DWORD n;
2597 WSABUF wsabuf = { len, (char*) buf };
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002598
Martin Wilck58854432002-04-05 21:22:55 +00002599 if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2600 return SOCKET_ERROR;
Francois Gouget76f6ffa2001-10-08 20:36:03 +00002601 else
Martin Wilck58854432002-04-05 21:22:55 +00002602 return n;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002603}
2604
2605/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002606 * sendto (WINSOCK.20)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002607 */
2608INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
Francois Gouget27202312001-11-14 21:26:23 +00002609 struct WS_sockaddr *to, INT16 tolen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002610{
Francois Gouget27202312001-11-14 21:26:23 +00002611 return (INT16)WS_sendto( s, buf, len, flags, to, tolen );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002612}
2613
2614/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002615 * setsockopt (WS2_32.21)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002616 */
Francois Gouget27202312001-11-14 21:26:23 +00002617int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2618 const char *optval, int optlen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002619{
Paul Rupe99ed3422001-12-14 22:48:38 +00002620 int fd;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002621
Paul Rupe99ed3422001-12-14 22:48:38 +00002622 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
2623 (int) optname, (int) optval, optlen);
2624 /* SO_OPENTYPE does not require a valid socket handle. */
2625 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2626 {
2627 if (optlen < sizeof(int) || !optval)
2628 {
2629 SetLastError(WSAEFAULT);
2630 return SOCKET_ERROR;
2631 }
Martin Wilckcf518bc2002-04-27 01:05:35 +00002632 TlsSetValue( opentype_tls_index, (LPVOID)*(int *)optval );
2633 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
Paul Rupe99ed3422001-12-14 22:48:38 +00002634 return 0;
2635 }
2636
2637 fd = _get_sock_fd(s);
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002638 if (fd != -1)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002639 {
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00002640 struct linger linger;
Rein Klazes5d3f7a62000-03-07 12:23:51 +00002641 int woptval;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00002642
Marcus Meissner3c379dd2000-11-26 22:36:38 +00002643 /* Is a privileged and useless operation, so we don't. */
2644 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
2645 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2646 return 0;
2647 }
2648
Rein Klazes9dd32502000-10-24 21:25:21 +00002649 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
John Gilmore5180d562000-09-16 20:51:40 +00002650 /* This is unique to WinSock and takes special conversion */
Rein Klazes20c68be2000-03-04 19:09:16 +00002651 linger.l_onoff = *((int*)optval) ? 0: 1;
2652 linger.l_linger = 0;
2653 optname=SO_LINGER;
2654 optval = (char*)&linger;
2655 optlen = sizeof(struct linger);
Rein Klazes9dd32502000-10-24 21:25:21 +00002656 level = SOL_SOCKET;
Rein Klazes20c68be2000-03-04 19:09:16 +00002657 }else{
John Gilmore5180d562000-09-16 20:51:40 +00002658 if (!convert_sockopt(&level, &optname)) {
2659 SetLastError(WSAENOPROTOOPT);
2660 close(fd);
2661 return SOCKET_ERROR;
2662 }
Rein Klazes9dd32502000-10-24 21:25:21 +00002663 if (optname == SO_LINGER && optval) {
2664 /* yes, uses unsigned short in both win16/win32 */
2665 linger.l_onoff = ((UINT16*)optval)[0];
2666 linger.l_linger = ((UINT16*)optval)[1];
2667 /* FIXME: what is documented behavior if SO_LINGER optval
2668 is null?? */
2669 optval = (char*)&linger;
Rein Klazese2a55be2002-01-29 17:06:11 +00002670 optlen = sizeof(struct linger);
Rein Klazes9dd32502000-10-24 21:25:21 +00002671 } else if (optlen < sizeof(int)){
2672 woptval= *((INT16 *) optval);
2673 optval= (char*) &woptval;
2674 optlen=sizeof(int);
2675 }
John Gilmore5180d562000-09-16 20:51:40 +00002676 }
Rein Klazes81f77712000-10-13 17:05:35 +00002677 if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2678 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2679 close( fd);
2680 return 0;
2681 }
2682
Ove Kaavenf45608f1999-10-23 16:53:34 +00002683 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2684 {
2685 close(fd);
2686 return 0;
2687 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002688 SetLastError(wsaErrno());
Ove Kaavenf45608f1999-10-23 16:53:34 +00002689 close(fd);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002690 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002691 else SetLastError(WSAENOTSOCK);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002692 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002693}
2694
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002695/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002696 * setsockopt (WINSOCK.21)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002697 */
2698INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2699 char *optval, INT16 optlen)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002700{
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00002701 if( !optval ) return SOCKET_ERROR;
Francois Gouget27202312001-11-14 21:26:23 +00002702 return (INT16)WS_setsockopt( s, (UINT16)level, optname, optval, optlen );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002703}
2704
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002705
2706/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002707 * shutdown (WS2_32.22)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002708 */
Francois Gouget27202312001-11-14 21:26:23 +00002709int WINAPI WS_shutdown(SOCKET s, int how)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002710{
Martin Wilckaf16c982002-04-25 21:34:24 +00002711 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2712 enum fd_type type;
2713 unsigned int clear_flags = 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002714
Martin Wilckaf16c982002-04-25 21:34:24 +00002715 fd = _get_sock_fd_type ( s, 0, &type, &flags );
2716 TRACE("socket %04x, how %i %d %d \n", s, how, type, flags );
2717
2718 if (fd == -1)
2719 return SOCKET_ERROR;
2720
2721 switch( how )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002722 {
Martin Wilckaf16c982002-04-25 21:34:24 +00002723 case 0: /* drop receives */
2724 clear_flags |= FD_READ;
2725 break;
2726 case 1: /* drop sends */
2727 clear_flags |= FD_WRITE;
2728 break;
2729 case 2: /* drop all */
2730 clear_flags |= FD_READ|FD_WRITE;
2731 default:
2732 clear_flags |= FD_WINE_CONNECTED|FD_WINE_LISTENING;
2733 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002734
Martin Wilckaf16c982002-04-25 21:34:24 +00002735 if ( flags & FD_FLAG_OVERLAPPED ) {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002736
Martin Wilckaf16c982002-04-25 21:34:24 +00002737 switch ( how )
2738 {
2739 case SD_RECEIVE:
2740 fd0 = fd;
2741 break;
2742 case SD_SEND:
2743 fd1 = fd;
2744 break;
2745 case SD_BOTH:
2746 default:
2747 fd0 = fd;
2748 fd1 = _get_sock_fd ( s );
2749 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002750
Martin Wilckaf16c982002-04-25 21:34:24 +00002751 if ( fd0 != -1 )
2752 {
2753 err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
2754 if ( err )
2755 {
2756 close ( fd0 );
2757 goto error;
2758 }
2759 }
2760 if ( fd1 != -1 )
2761 {
2762 err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
2763 if ( err )
2764 {
2765 close ( fd1 );
2766 goto error;
2767 }
2768 }
2769 }
2770 else /* non-overlapped mode */
2771 {
2772 if ( shutdown( fd, how ) )
2773 {
2774 err = wsaErrno ();
2775 close ( fd );
2776 goto error;
2777 }
2778 close(fd);
2779 }
2780
2781 _enable_event( s, 0, 0, clear_flags );
2782 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2783 return 0;
2784
2785error:
2786 _enable_event( s, 0, 0, clear_flags );
2787 WSASetLastError ( err );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002788 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002789}
2790
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002791/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002792 * shutdown (WINSOCK.22)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002793 */
2794INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2795{
Francois Gouget27202312001-11-14 21:26:23 +00002796 return (INT16)WS_shutdown( s, how );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002797}
2798
2799
2800/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002801 * socket (WS2_32.23)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002802 */
Francois Gouget27202312001-11-14 21:26:23 +00002803SOCKET WINAPI WS_socket(int af, int type, int protocol)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002804{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002805 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002806
Martin Wilckcf518bc2002-04-27 01:05:35 +00002807 return WSASocketA ( af, type, protocol, NULL, 0,
2808 (TlsGetValue(opentype_tls_index) ? 0 : WSA_FLAG_OVERLAPPED) );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002809}
2810
2811/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002812 * socket (WINSOCK.23)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002813 */
2814SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2815{
Francois Gouget27202312001-11-14 21:26:23 +00002816 return (SOCKET16)WS_socket( af, type, protocol );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002817}
2818
2819
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002820/* ----------------------------------- DNS services
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002821 *
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002822 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
Alexandre Julliard491502b1997-11-01 19:08:16 +00002823 * Also, we have to use wsock32 stubs to convert structures and
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00002824 * error codes from Unix to WSA, hence there is no direct mapping in
2825 * the relay32/wsock32.spec.
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002826 */
2827
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002828
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002829/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002830 * __ws_gethostbyaddr
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002831 */
Andreas Mohrae509412000-08-03 22:19:09 +00002832static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002833{
Rein Klazesff7a61f2000-09-24 19:41:57 +00002834 WIN_hostent *retval = NULL;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002835
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002836 struct hostent* host;
Rein Klazesff7a61f2000-09-24 19:41:57 +00002837#if HAVE_LINUX_GETHOSTBYNAME_R_6
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002838 char *extrabuf;
2839 int ebufsize=1024;
2840 struct hostent hostentry;
2841 int locerr=ENOBUFS;
2842 host = NULL;
2843 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2844 while(extrabuf) {
2845 int res = gethostbyaddr_r(addr, len, type,
2846 &hostentry, extrabuf, ebufsize, &host, &locerr);
2847 if( res != ERANGE) break;
2848 ebufsize *=2;
2849 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002850 }
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002851 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2852#else
2853 EnterCriticalSection( &csWSgetXXXbyYYY );
2854 host = gethostbyaddr(addr, len, type);
2855 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2856#endif
2857 if( host != NULL )
2858 {
2859 if( WS_dup_he(host, dup_flag) )
2860 retval = he_buffer;
2861 else
2862 SetLastError(WSAENOBUFS);
2863 }
2864#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2865 HeapFree(GetProcessHeap(),0,extrabuf);
2866#else
2867 LeaveCriticalSection( &csWSgetXXXbyYYY );
2868#endif
Rein Klazesff7a61f2000-09-24 19:41:57 +00002869 return retval;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002870}
2871
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002872/***********************************************************************
2873 * gethostbyaddr (WINSOCK.51)
2874 */
Alexandre Julliard491502b1997-11-01 19:08:16 +00002875SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2876{
Alexandre Julliard85129792001-12-24 20:30:24 +00002877 TRACE("ptr %p, len %d, type %d\n", addr, len, type);
2878 if (!__ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR )) return 0;
2879 return he_buffer_seg;
Alexandre Julliard491502b1997-11-01 19:08:16 +00002880}
2881
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002882/***********************************************************************
2883 * gethostbyaddr (WS2_32.51)
2884 */
Francois Gouget27202312001-11-14 21:26:23 +00002885struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len,
2886 int type)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002887{
Alexandre Julliard61fece01999-06-26 19:09:08 +00002888 TRACE("ptr %08x, len %d, type %d\n",
Alexandre Julliard491502b1997-11-01 19:08:16 +00002889 (unsigned) addr, len, type);
2890 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2891}
2892
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002893/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002894 * __ws_gethostbyname
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002895 */
Andreas Mohrae509412000-08-03 22:19:09 +00002896static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002897{
Rein Klazesff7a61f2000-09-24 19:41:57 +00002898 WIN_hostent *retval = NULL;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002899 struct hostent* host;
Rein Klazesff7a61f2000-09-24 19:41:57 +00002900#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002901 char *extrabuf;
2902 int ebufsize=1024;
2903 struct hostent hostentry;
2904 int locerr = ENOBUFS;
2905 host = NULL;
2906 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2907 while(extrabuf) {
2908 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2909 if( res != ERANGE) break;
2910 ebufsize *=2;
2911 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002912 }
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002913 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2914#else
2915 EnterCriticalSection( &csWSgetXXXbyYYY );
2916 host = gethostbyname(name);
2917 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2918#endif
2919 if( host != NULL )
2920 {
2921 if( WS_dup_he(host, dup_flag) )
2922 retval = he_buffer;
2923 else SetLastError(WSAENOBUFS);
2924 }
2925#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2926 HeapFree(GetProcessHeap(),0,extrabuf);
2927#else
2928 LeaveCriticalSection( &csWSgetXXXbyYYY );
2929#endif
Rein Klazesff7a61f2000-09-24 19:41:57 +00002930 return retval;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002931}
2932
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002933/***********************************************************************
2934 * gethostbyname (WINSOCK.52)
2935 */
Alexandre Julliard491502b1997-11-01 19:08:16 +00002936SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2937{
Alexandre Julliard85129792001-12-24 20:30:24 +00002938 TRACE( "%s\n", debugstr_a(name) );
2939 if (!__ws_gethostbyname( name, WS_DUP_SEGPTR )) return 0;
2940 return he_buffer_seg;
Alexandre Julliard491502b1997-11-01 19:08:16 +00002941}
2942
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002943/***********************************************************************
2944 * gethostbyname (WS2_32.52)
2945 */
Francois Gouget27202312001-11-14 21:26:23 +00002946struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002947{
Alexandre Julliard85129792001-12-24 20:30:24 +00002948 TRACE( "%s\n", debugstr_a(name) );
Alexandre Julliard491502b1997-11-01 19:08:16 +00002949 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2950}
2951
2952
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002953/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002954 * __ws_getprotobyname
Alexandre Julliard491502b1997-11-01 19:08:16 +00002955 */
Andreas Mohrae509412000-08-03 22:19:09 +00002956static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002957{
Rein Klazesff7a61f2000-09-24 19:41:57 +00002958 WIN_protoent* retval = NULL;
Alexandre Julliard491502b1997-11-01 19:08:16 +00002959
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002960 struct protoent* proto;
2961 EnterCriticalSection( &csWSgetXXXbyYYY );
2962 if( (proto = getprotobyname(name)) != NULL )
Alexandre Julliard491502b1997-11-01 19:08:16 +00002963 {
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00002964 if( WS_dup_pe(proto, dup_flag) )
2965 retval = pe_buffer;
2966 else SetLastError(WSAENOBUFS);
2967 }
2968 else {
2969 MESSAGE("protocol %s not found; You might want to add "
2970 "this to /etc/protocols\n", debugstr_a(name) );
2971 SetLastError(WSANO_DATA);
2972 }
2973 LeaveCriticalSection( &csWSgetXXXbyYYY );
Rein Klazesff7a61f2000-09-24 19:41:57 +00002974 return retval;
Alexandre Julliard491502b1997-11-01 19:08:16 +00002975}
2976
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002977/***********************************************************************
2978 * getprotobyname (WINSOCK.53)
2979 */
Alexandre Julliard491502b1997-11-01 19:08:16 +00002980SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2981{
Alexandre Julliard85129792001-12-24 20:30:24 +00002982 TRACE( "%s\n", debugstr_a(name) );
2983 if (!__ws_getprotobyname(name, WS_DUP_SEGPTR)) return 0;
2984 return pe_buffer_seg;
Alexandre Julliard491502b1997-11-01 19:08:16 +00002985}
2986
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002987/***********************************************************************
2988 * getprotobyname (WS2_32.53)
2989 */
Francois Gouget27202312001-11-14 21:26:23 +00002990struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002991{
Alexandre Julliard85129792001-12-24 20:30:24 +00002992 TRACE( "%s\n", debugstr_a(name) );
Alexandre Julliard491502b1997-11-01 19:08:16 +00002993 return __ws_getprotobyname(name, WS_DUP_LINEAR);
2994}
2995
2996
2997/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00002998 * __ws_getprotobynumber
Alexandre Julliard491502b1997-11-01 19:08:16 +00002999 */
Andreas Mohrae509412000-08-03 22:19:09 +00003000static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
Alexandre Julliard491502b1997-11-01 19:08:16 +00003001{
Rein Klazesff7a61f2000-09-24 19:41:57 +00003002 WIN_protoent* retval = NULL;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003003 struct protoent* proto;
3004 EnterCriticalSection( &csWSgetXXXbyYYY );
3005 if( (proto = getprotobynumber(number)) != NULL )
Alexandre Julliard491502b1997-11-01 19:08:16 +00003006 {
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003007 if( WS_dup_pe(proto, dup_flag) )
3008 retval = pe_buffer;
3009 else SetLastError(WSAENOBUFS);
3010 }
3011 else {
3012 MESSAGE("protocol number %d not found; You might want to add "
3013 "this to /etc/protocols\n", number );
3014 SetLastError(WSANO_DATA);
3015 }
3016 LeaveCriticalSection( &csWSgetXXXbyYYY );
Rein Klazesff7a61f2000-09-24 19:41:57 +00003017 return retval;
Alexandre Julliard491502b1997-11-01 19:08:16 +00003018}
3019
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003020/***********************************************************************
3021 * getprotobynumber (WINSOCK.54)
3022 */
Alexandre Julliard491502b1997-11-01 19:08:16 +00003023SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
3024{
Alexandre Julliard61fece01999-06-26 19:09:08 +00003025 TRACE("%i\n", number);
Alexandre Julliard85129792001-12-24 20:30:24 +00003026 if (!__ws_getprotobynumber(number, WS_DUP_SEGPTR)) return 0;
3027 return pe_buffer_seg;
Alexandre Julliard491502b1997-11-01 19:08:16 +00003028}
3029
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003030/***********************************************************************
3031 * getprotobynumber (WS2_32.54)
3032 */
Francois Gouget27202312001-11-14 21:26:23 +00003033struct WS_protoent* WINAPI WS_getprotobynumber(int number)
Alexandre Julliard491502b1997-11-01 19:08:16 +00003034{
Alexandre Julliard61fece01999-06-26 19:09:08 +00003035 TRACE("%i\n", number);
Alexandre Julliard491502b1997-11-01 19:08:16 +00003036 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
3037}
3038
3039
3040/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003041 * __ws_getservbyname
Alexandre Julliard491502b1997-11-01 19:08:16 +00003042 */
Andreas Mohrae509412000-08-03 22:19:09 +00003043static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
Alexandre Julliard491502b1997-11-01 19:08:16 +00003044{
Rein Klazesff7a61f2000-09-24 19:41:57 +00003045 WIN_servent* retval = NULL;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003046 struct servent* serv;
3047 int i = wsi_strtolo( name, proto );
Alexandre Julliard491502b1997-11-01 19:08:16 +00003048
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003049 if( i ) {
3050 EnterCriticalSection( &csWSgetXXXbyYYY );
3051 serv = getservbyname(local_buffer,
3052 proto ? (local_buffer + i) : NULL);
3053 if( serv != NULL )
3054 {
3055 if( WS_dup_se(serv, dup_flag) )
3056 retval = se_buffer;
3057 else SetLastError(WSAENOBUFS);
3058 }
3059 else {
3060 MESSAGE("service %s protocol %s not found; You might want to add "
3061 "this to /etc/services\n", debugstr_a(local_buffer),
3062 proto ? debugstr_a(local_buffer+i):"*");
3063 SetLastError(WSANO_DATA);
3064 }
3065 LeaveCriticalSection( &csWSgetXXXbyYYY );
3066 }
3067 else SetLastError(WSAENOBUFS);
Rein Klazesff7a61f2000-09-24 19:41:57 +00003068 return retval;
Alexandre Julliard491502b1997-11-01 19:08:16 +00003069}
3070
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003071/***********************************************************************
3072 * getservbyname (WINSOCK.55)
3073 */
Alexandre Julliard491502b1997-11-01 19:08:16 +00003074SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
3075{
Alexandre Julliard85129792001-12-24 20:30:24 +00003076 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3077 if (!__ws_getservbyname(name, proto, WS_DUP_SEGPTR)) return 0;
3078 return se_buffer_seg;
Alexandre Julliard491502b1997-11-01 19:08:16 +00003079}
3080
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003081/***********************************************************************
3082 * getservbyname (WS2_32.55)
3083 */
Francois Gouget27202312001-11-14 21:26:23 +00003084struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
Alexandre Julliard491502b1997-11-01 19:08:16 +00003085{
Alexandre Julliard85129792001-12-24 20:30:24 +00003086 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
Alexandre Julliard491502b1997-11-01 19:08:16 +00003087 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
3088}
3089
3090
3091/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003092 * __ws_getservbyport
Alexandre Julliard491502b1997-11-01 19:08:16 +00003093 */
Andreas Mohrae509412000-08-03 22:19:09 +00003094static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
Alexandre Julliard491502b1997-11-01 19:08:16 +00003095{
Rein Klazesff7a61f2000-09-24 19:41:57 +00003096 WIN_servent* retval = NULL;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003097 struct servent* serv;
3098 if (!proto || wsi_strtolo( proto, NULL )) {
3099 EnterCriticalSection( &csWSgetXXXbyYYY );
3100 if( (serv = getservbyport(port, (proto) ? local_buffer : NULL)) != NULL ) {
3101 if( WS_dup_se(serv, dup_flag) )
3102 retval = se_buffer;
3103 else SetLastError(WSAENOBUFS);
3104 }
3105 else {
3106 MESSAGE("service on port %lu protocol %s not found; You might want to add "
3107 "this to /etc/services\n", (unsigned long)ntohl(port),
3108 proto ? debugstr_a(local_buffer) : "*");
3109 SetLastError(WSANO_DATA);
3110 }
3111 LeaveCriticalSection( &csWSgetXXXbyYYY );
3112 }
3113 else SetLastError(WSAENOBUFS);
Rein Klazesff7a61f2000-09-24 19:41:57 +00003114 return retval;
Alexandre Julliard491502b1997-11-01 19:08:16 +00003115}
3116
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003117/***********************************************************************
3118 * getservbyport (WINSOCK.56)
3119 */
Alexandre Julliard491502b1997-11-01 19:08:16 +00003120SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
3121{
Alexandre Julliard85129792001-12-24 20:30:24 +00003122 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3123 if (!__ws_getservbyport(port, proto, WS_DUP_SEGPTR)) return 0;
3124 return se_buffer_seg;
Alexandre Julliard491502b1997-11-01 19:08:16 +00003125}
3126
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003127/***********************************************************************
3128 * getservbyport (WS2_32.56)
3129 */
Francois Gouget27202312001-11-14 21:26:23 +00003130struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
Alexandre Julliard491502b1997-11-01 19:08:16 +00003131{
Alexandre Julliard85129792001-12-24 20:30:24 +00003132 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
Alexandre Julliard491502b1997-11-01 19:08:16 +00003133 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
3134}
3135
3136
3137/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003138 * gethostname (WS2_32.57)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003139 */
Francois Gouget27202312001-11-14 21:26:23 +00003140int WINAPI WS_gethostname(char *name, int namelen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003141{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003142 TRACE("name %p, len %d\n", name, namelen);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003143
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003144 if (gethostname(name, namelen) == 0)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003145 {
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003146 TRACE("<- '%s'\n", name);
3147 return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003148 }
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003149 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
Andreas Mohrdacdb9c2001-02-14 00:29:16 +00003150 TRACE("<- ERROR !\n");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003151 return SOCKET_ERROR;
3152}
3153
3154/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003155 * gethostname (WINSOCK.57)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003156 */
3157INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
3158{
Francois Gouget27202312001-11-14 21:26:23 +00003159 return (INT16)WS_gethostname(name, namelen);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003160}
3161
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003162
3163/* ------------------------------------- Windows sockets extensions -- *
3164 * *
3165 * ------------------------------------------------------------------- */
Ove Kaavenf45608f1999-10-23 16:53:34 +00003166
Patrik Stridvallb167d4b2000-06-23 15:47:36 +00003167/***********************************************************************
Patrik Stridvall8b216b32001-06-19 18:20:47 +00003168 * WSAEnumNetworkEvents (WS2_32.36)
Patrik Stridvallb167d4b2000-06-23 15:47:36 +00003169 */
Ove Kaavenf45608f1999-10-23 16:53:34 +00003170int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
3171{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003172 int ret;
Ove Kaavenf45608f1999-10-23 16:53:34 +00003173
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003174 TRACE("%08x, hEvent %08x, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
3175
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00003176 SERVER_START_REQ( get_socket_event )
Ove Kaavenf45608f1999-10-23 16:53:34 +00003177 {
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003178 req->handle = s;
3179 req->service = TRUE;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003180 req->c_event = hEvent;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00003181 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
3182 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
Ove Kaavenf45608f1999-10-23 16:53:34 +00003183 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00003184 SERVER_END_REQ;
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003185 if (!ret) return 0;
3186 SetLastError(WSAEINVAL);
3187 return SOCKET_ERROR;
Ove Kaavenf45608f1999-10-23 16:53:34 +00003188}
3189
Patrik Stridvallb167d4b2000-06-23 15:47:36 +00003190/***********************************************************************
Patrik Stridvall8b216b32001-06-19 18:20:47 +00003191 * WSAEventSelect (WS2_32.39)
Patrik Stridvallb167d4b2000-06-23 15:47:36 +00003192 */
Ove Kaavenf45608f1999-10-23 16:53:34 +00003193int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
3194{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003195 int ret;
Ove Kaavenf45608f1999-10-23 16:53:34 +00003196
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003197 TRACE("%08x, hEvent %08x, event %08x\n", s, hEvent, (unsigned)lEvent );
3198
Alexandre Julliard67a74992001-02-27 02:09:16 +00003199 SERVER_START_REQ( set_socket_event )
Ove Kaavenf45608f1999-10-23 16:53:34 +00003200 {
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003201 req->handle = s;
3202 req->mask = lEvent;
3203 req->event = hEvent;
Alexandre Julliard81f2a732002-03-23 20:43:52 +00003204 req->window = 0;
3205 req->msg = 0;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +00003206 ret = wine_server_call( req );
Ove Kaavenf45608f1999-10-23 16:53:34 +00003207 }
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003208 SERVER_END_REQ;
3209 if (!ret) return 0;
3210 SetLastError(WSAEINVAL);
3211 return SOCKET_ERROR;
Ove Kaavenf45608f1999-10-23 16:53:34 +00003212}
3213
Martin Wilckaf16c982002-04-25 21:34:24 +00003214/**********************************************************************
3215 * WSAGetOverlappedResult (WS2_32.40)
3216 */
3217BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
3218 LPDWORD lpcbTransfer, BOOL fWait,
3219 LPDWORD lpdwFlags )
3220{
3221 DWORD r;
3222
3223 TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
3224 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
3225
3226 if ( !(lpOverlapped && lpOverlapped->hEvent) )
3227 {
3228 ERR ( "Invalid pointer\n" );
3229 WSASetLastError (WSA_INVALID_PARAMETER);
3230 return FALSE;
3231 }
3232
3233 do {
3234 r = WaitForSingleObjectEx (lpOverlapped->hEvent, fWait ? INFINITE : 0, TRUE);
3235 } while (r == STATUS_USER_APC);
3236
3237 if ( lpcbTransfer )
3238 *lpcbTransfer = lpOverlapped->InternalHigh;
3239
3240 if ( lpdwFlags )
3241 *lpdwFlags = lpOverlapped->Offset;
3242
3243 if ( r == WAIT_OBJECT_0 )
3244 return TRUE;
3245
3246 WSASetLastError ( lpOverlapped->Internal == STATUS_PENDING ?
3247 WSA_IO_INCOMPLETE : NtStatusToWSAError ( lpOverlapped->Internal ) );
3248 return FALSE;
3249}
3250
3251
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003252/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003253 * WSAAsyncSelect (WS2_32.101)
3254 */
Patrik Stridvallb8684a21999-07-31 17:32:05 +00003255INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003256{
Alexandre Julliard81f2a732002-03-23 20:43:52 +00003257 int ret;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003258
Alexandre Julliard81f2a732002-03-23 20:43:52 +00003259 TRACE("%x, hWnd %x, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3260
3261 SERVER_START_REQ( set_socket_event )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003262 {
Alexandre Julliard81f2a732002-03-23 20:43:52 +00003263 req->handle = s;
3264 req->mask = lEvent;
3265 req->event = 0;
3266 req->window = hWnd;
3267 req->msg = uMsg;
3268 ret = wine_server_call( req );
3269 }
3270 SERVER_END_REQ;
3271 if (!ret) return 0;
3272 SetLastError(WSAEINVAL);
3273 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003274}
3275
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003276/***********************************************************************
3277 * WSAAsyncSelect (WINSOCK.101)
3278 */
Patrik Stridvallb8684a21999-07-31 17:32:05 +00003279INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00003280{
Alexandre Julliarda3960291999-02-26 11:11:13 +00003281 return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00003282}
3283
Moses DeJonge0a3ba51999-11-23 22:29:00 +00003284/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003285 * WSARecvEx (WINSOCK.1107)
Moses DeJonge0a3ba51999-11-23 22:29:00 +00003286 *
3287 * See description for WSARecvEx()
3288 */
Francois Gouget27202312001-11-14 21:26:23 +00003289INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags)
3290{
Moses DeJonge0a3ba51999-11-23 22:29:00 +00003291 FIXME("(WSARecvEx16) partial packet return value not set \n");
3292
3293 return WINSOCK_recv16(s, buf, len, *flags);
3294}
3295
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003296
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003297/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003298 * WSACreateEvent (WS2_32.31)
James Hatheway829405a2000-06-18 17:23:17 +00003299 *
3300 */
3301WSAEVENT WINAPI WSACreateEvent(void)
3302{
3303 /* Create a manual-reset event, with initial state: unsignealed */
3304 TRACE("\n");
3305
3306 return CreateEventA(NULL, TRUE, FALSE, NULL);
3307}
3308
3309/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003310 * WSACloseEvent (WS2_32.29)
James Hatheway829405a2000-06-18 17:23:17 +00003311 *
3312 */
3313BOOL WINAPI WSACloseEvent(WSAEVENT event)
3314{
3315 TRACE ("event=0x%x\n", event);
3316
3317 return CloseHandle(event);
3318}
3319
3320/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003321 * WSASocketA (WS2_32.78)
James Hatheway829405a2000-06-18 17:23:17 +00003322 *
3323 */
3324SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3325 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3326 GROUP g, DWORD dwFlags)
3327{
Martin Wilck65b7e642002-01-09 21:17:16 +00003328 SOCKET ret;
3329
James Hatheway829405a2000-06-18 17:23:17 +00003330 /*
3331 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
Martin Wilck65b7e642002-01-09 21:17:16 +00003332 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
James Hatheway829405a2000-06-18 17:23:17 +00003333 */
Martin Wilck65b7e642002-01-09 21:17:16 +00003334
James Hatheway829405a2000-06-18 17:23:17 +00003335 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3336 af, type, protocol, lpProtocolInfo, g, dwFlags );
3337
Martin Wilck65b7e642002-01-09 21:17:16 +00003338 /* check the socket family */
3339 switch(af)
3340 {
3341#ifdef HAVE_IPX
3342 case WS_AF_IPX: af = AF_IPX;
3343#endif
3344 case AF_INET:
3345 case AF_UNSPEC:
3346 break;
3347 default:
3348 SetLastError(WSAEAFNOSUPPORT);
3349 return INVALID_SOCKET;
3350 }
3351
3352 /* check the socket type */
3353 switch(type)
3354 {
3355 case WS_SOCK_STREAM:
3356 type=SOCK_STREAM;
3357 break;
3358 case WS_SOCK_DGRAM:
3359 type=SOCK_DGRAM;
3360 break;
3361 case WS_SOCK_RAW:
3362 type=SOCK_RAW;
3363 break;
3364 default:
3365 SetLastError(WSAESOCKTNOSUPPORT);
3366 return INVALID_SOCKET;
3367 }
3368
3369 /* check the protocol type */
3370 if ( protocol < 0 ) /* don't support negative values */
3371 {
3372 SetLastError(WSAEPROTONOSUPPORT);
3373 return INVALID_SOCKET;
3374 }
3375
3376 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3377 switch(protocol)
3378 {
3379 case IPPROTO_TCP:
3380 if (type == SOCK_STREAM) { af = AF_INET; break; }
3381 case IPPROTO_UDP:
3382 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3383 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3384 }
3385
3386 SERVER_START_REQ( create_socket )
3387 {
3388 req->family = af;
3389 req->type = type;
3390 req->protocol = protocol;
3391 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3392 req->flags = dwFlags;
3393 req->inherit = TRUE;
3394 set_error( wine_server_call( req ) );
3395 ret = (SOCKET)reply->handle;
3396 }
3397 SERVER_END_REQ;
3398 if (ret)
3399 {
3400 TRACE("\tcreated %04x\n", ret );
3401 return ret;
3402 }
3403
3404 if (GetLastError() == WSAEACCES) /* raw socket denied */
3405 {
3406 if (type == SOCK_RAW)
3407 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3408 else
3409 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3410 SetLastError(WSAESOCKTNOSUPPORT);
3411 }
3412
3413 WARN("\t\tfailed!\n");
3414 return INVALID_SOCKET;
James Hatheway829405a2000-06-18 17:23:17 +00003415}
3416
3417
3418/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003419 * __WSAFDIsSet (WINSOCK.151)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003420 */
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00003421INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003422{
3423 int i = set->fd_count;
3424
Alexandre Julliard61fece01999-06-26 19:09:08 +00003425 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003426
3427 while (i--)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003428 if (set->fd_array[i] == s) return 1;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003429 return 0;
3430}
3431
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003432/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003433 * __WSAFDIsSet (WS2_32.151)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003434 */
Francois Gouget27202312001-11-14 21:26:23 +00003435int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003436{
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00003437 int i = set->fd_count;
3438
Alexandre Julliard61fece01999-06-26 19:09:08 +00003439 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00003440
3441 while (i--)
3442 if (set->fd_array[i] == s) return 1;
3443 return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003444}
3445
3446/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003447 * WSAIsBlocking (WINSOCK.114)
3448 * WSAIsBlocking (WS2_32.114)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003449 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003450BOOL WINAPI WSAIsBlocking(void)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003451{
3452 /* By default WinSock should set all its sockets to non-blocking mode
3453 * and poll in PeekMessage loop when processing "blocking" ones. This
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00003454 * function is supposed to tell if the program is in this loop. Our
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003455 * blocking calls are truly blocking so we always return FALSE.
3456 *
3457 * Note: It is allowed to call this function without prior WSAStartup().
3458 */
3459
Alexandre Julliard61fece01999-06-26 19:09:08 +00003460 TRACE("\n");
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003461 return FALSE;
3462}
3463
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003464/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003465 * WSACancelBlockingCall (WINSOCK.113)
3466 * WSACancelBlockingCall (WS2_32.113)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003467 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003468INT WINAPI WSACancelBlockingCall(void)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003469{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003470 TRACE("\n");
3471 return 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003472}
3473
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003474
3475/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003476 * WSASetBlockingHook (WINSOCK.109)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003477 */
3478FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003479{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003480 FARPROC16 prev = (FARPROC16)blocking_hook;
3481 blocking_hook = (FARPROC)lpBlockFunc;
3482 TRACE("hook %p\n", lpBlockFunc);
3483 return prev;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003484}
3485
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00003486
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003487/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +00003488 * WSASetBlockingHook (WS2_32.109)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003489 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003490FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003491{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003492 FARPROC prev = blocking_hook;
3493 blocking_hook = lpBlockFunc;
3494 TRACE("hook %p\n", lpBlockFunc);
3495 return prev;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00003496}
3497
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003498
3499/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +00003500 * WSAUnhookBlockingHook (WINSOCK.110)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003501 */
3502INT16 WINAPI WSAUnhookBlockingHook16(void)
3503{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003504 blocking_hook = NULL;
3505 return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003506}
3507
3508
3509/***********************************************************************
Patrik Stridvall044855c2001-07-11 18:56:41 +00003510 * WSAUnhookBlockingHook (WS2_32.110)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003511 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003512INT WINAPI WSAUnhookBlockingHook(void)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003513{
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003514 blocking_hook = NULL;
3515 return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003516}
3517
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00003518
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003519/* ----------------------------------- end of API stuff */
3520
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00003521/* ----------------------------------- helper functions -
3522 *
3523 * TODO: Merge WS_dup_..() stuff into one function that
3524 * would operate with a generic structure containing internal
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00003525 * pointers (via a template of some kind).
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00003526 */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003527
3528static int list_size(char** l, int item_size)
3529{
3530 int i,j = 0;
3531 if(l)
3532 { for(i=0;l[i];i++)
3533 j += (item_size) ? item_size : strlen(l[i]) + 1;
3534 j += (i + 1) * sizeof(char*); }
3535 return j;
3536}
3537
3538static int list_dup(char** l_src, char* ref, char* base, int item_size)
3539{
3540 /* base is either either equal to ref or 0 or SEGPTR */
3541
3542 char* p = ref;
3543 char** l_to = (char**)ref;
3544 int i,j,k;
3545
3546 for(j=0;l_src[j];j++) ;
3547 p += (j + 1) * sizeof(char*);
3548 for(i=0;i<j;i++)
3549 { l_to[i] = base + (p - ref);
3550 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3551 memcpy(p, l_src[i], k); p += k; }
3552 l_to[i] = NULL;
3553 return (p - ref);
3554}
3555
3556/* ----- hostent */
3557
3558static int hostent_size(struct hostent* p_he)
3559{
3560 int size = 0;
3561 if( p_he )
3562 { size = sizeof(struct hostent);
3563 size += strlen(p_he->h_name) + 1;
3564 size += list_size(p_he->h_aliases, 0);
3565 size += list_size(p_he->h_addr_list, p_he->h_length ); }
3566 return size;
3567}
3568
Andreas Mohrae509412000-08-03 22:19:09 +00003569/* duplicate hostent entry
3570 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3571 * Dito for protoent and servent.
3572 */
Alexandre Julliard85129792001-12-24 20:30:24 +00003573static int WS_dup_he(struct hostent* p_he, int flag)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003574{
Andreas Mohrae509412000-08-03 22:19:09 +00003575 /* Convert hostent structure into ws_hostent so that the data fits
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003576 * into local_buffer. Internal pointers can be linear, SEGPTR, or
3577 * relative to local_buffer depending on "flag" value. Returns size
3578 * of the data copied.
Andreas Mohrae509412000-08-03 22:19:09 +00003579 */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003580
Andreas Mohrae509412000-08-03 22:19:09 +00003581 int size = hostent_size(p_he);
3582 if( size )
3583 {
3584 char *p_name,*p_aliases,*p_addr,*p_base,*p;
3585 char *p_to;
3586 struct ws_hostent16 *p_to16;
Francois Gouget27202312001-11-14 21:26:23 +00003587 struct WS_hostent *p_to32;
Alexandre Julliard767e6f61998-08-09 12:47:43 +00003588
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003589 check_buffer_he(size);
3590 p_to = he_buffer;
3591 p_to16 = he_buffer;
3592 p_to32 = he_buffer;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003593
Andreas Mohrae509412000-08-03 22:19:09 +00003594 p = p_to;
Alexandre Julliard85129792001-12-24 20:30:24 +00003595 p_base = (flag & WS_DUP_SEGPTR) ? (char*)he_buffer_seg : he_buffer;
Andreas Mohrae509412000-08-03 22:19:09 +00003596 p += (flag & WS_DUP_SEGPTR) ?
Francois Gouget27202312001-11-14 21:26:23 +00003597 sizeof(struct ws_hostent16) : sizeof(struct WS_hostent);
Andreas Mohrae509412000-08-03 22:19:09 +00003598 p_name = p;
3599 strcpy(p, p_he->h_name); p += strlen(p) + 1;
3600 p_aliases = p;
3601 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3602 p_addr = p;
3603 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
Alexandre Julliardb1bac321996-12-15 19:45:59 +00003604
Andreas Mohrae509412000-08-03 22:19:09 +00003605 if (flag & WS_DUP_SEGPTR) /* Win16 */
3606 {
3607 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
3608 p_to16->h_length = (INT16)p_he->h_length;
3609 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3610 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3611 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3612 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3613 }
3614 else /* Win32 */
3615 {
3616 p_to32->h_addrtype = p_he->h_addrtype;
3617 p_to32->h_length = p_he->h_length;
3618 p_to32->h_name = (p_base + (p_name - p_to));
3619 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3620 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
Francois Gouget27202312001-11-14 21:26:23 +00003621 size += (sizeof(struct WS_hostent) - sizeof(struct hostent));
Andreas Mohrae509412000-08-03 22:19:09 +00003622 }
3623 }
3624 return size;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003625}
3626
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003627/* ----- protoent */
3628
3629static int protoent_size(struct protoent* p_pe)
3630{
3631 int size = 0;
3632 if( p_pe )
3633 { size = sizeof(struct protoent);
3634 size += strlen(p_pe->p_name) + 1;
3635 size += list_size(p_pe->p_aliases, 0); }
3636 return size;
3637}
3638
Alexandre Julliard85129792001-12-24 20:30:24 +00003639static int WS_dup_pe(struct protoent* p_pe, int flag)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003640{
Andreas Mohrae509412000-08-03 22:19:09 +00003641 int size = protoent_size(p_pe);
3642 if( size )
3643 {
3644 char *p_to;
3645 struct ws_protoent16 *p_to16;
Francois Gouget27202312001-11-14 21:26:23 +00003646 struct WS_protoent *p_to32;
Andreas Mohrae509412000-08-03 22:19:09 +00003647 char *p_name,*p_aliases,*p_base,*p;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003648
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003649 check_buffer_pe(size);
3650 p_to = pe_buffer;
3651 p_to16 = pe_buffer;
3652 p_to32 = pe_buffer;
Andreas Mohrae509412000-08-03 22:19:09 +00003653 p = p_to;
Alexandre Julliard85129792001-12-24 20:30:24 +00003654 p_base = (flag & WS_DUP_SEGPTR) ? (char*)pe_buffer_seg : pe_buffer;
Andreas Mohrae509412000-08-03 22:19:09 +00003655 p += (flag & WS_DUP_SEGPTR) ?
Francois Gouget27202312001-11-14 21:26:23 +00003656 sizeof(struct ws_protoent16) : sizeof(struct WS_protoent);
Andreas Mohrae509412000-08-03 22:19:09 +00003657 p_name = p;
3658 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3659 p_aliases = p;
3660 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00003661
Andreas Mohrae509412000-08-03 22:19:09 +00003662 if (flag & WS_DUP_SEGPTR) /* Win16 */
3663 {
3664 p_to16->p_proto = (INT16)p_pe->p_proto;
3665 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3666 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3667 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3668 }
3669 else /* Win32 */
3670 {
3671 p_to32->p_proto = p_pe->p_proto;
3672 p_to32->p_name = (p_base) + (p_name - p_to);
3673 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
Francois Gouget27202312001-11-14 21:26:23 +00003674 size += (sizeof(struct WS_protoent) - sizeof(struct protoent));
Andreas Mohrae509412000-08-03 22:19:09 +00003675 }
3676 }
3677 return size;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003678}
3679
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003680/* ----- servent */
3681
3682static int servent_size(struct servent* p_se)
3683{
3684 int size = 0;
3685 if( p_se )
3686 { size += sizeof(struct servent);
3687 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3688 size += list_size(p_se->s_aliases, 0); }
3689 return size;
3690}
3691
Alexandre Julliard85129792001-12-24 20:30:24 +00003692static int WS_dup_se(struct servent* p_se, int flag)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003693{
Andreas Mohrae509412000-08-03 22:19:09 +00003694 int size = servent_size(p_se);
3695 if( size )
3696 {
3697 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3698 char *p_to;
3699 struct ws_servent16 *p_to16;
Francois Gouget27202312001-11-14 21:26:23 +00003700 struct WS_servent *p_to32;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003701
Alexandre Julliard641c7ae2001-02-20 01:57:13 +00003702 check_buffer_se(size);
3703 p_to = se_buffer;
3704 p_to16 = se_buffer;
3705 p_to32 = se_buffer;
Andreas Mohrae509412000-08-03 22:19:09 +00003706 p = p_to;
Alexandre Julliard85129792001-12-24 20:30:24 +00003707 p_base = (flag & WS_DUP_SEGPTR) ? (char*)se_buffer_seg : se_buffer;
Andreas Mohrae509412000-08-03 22:19:09 +00003708 p += (flag & WS_DUP_SEGPTR) ?
Francois Gouget27202312001-11-14 21:26:23 +00003709 sizeof(struct ws_servent16) : sizeof(struct WS_servent);
Andreas Mohrae509412000-08-03 22:19:09 +00003710 p_name = p;
3711 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3712 p_proto = p;
3713 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3714 p_aliases = p;
3715 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003716
Andreas Mohrae509412000-08-03 22:19:09 +00003717 if (flag & WS_DUP_SEGPTR) /* Win16 */
3718 {
3719 p_to16->s_port = (INT16)p_se->s_port;
3720 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3721 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3722 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3723 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3724 }
3725 else /* Win32 */
3726 {
3727 p_to32->s_port = p_se->s_port;
3728 p_to32->s_name = (p_base + (p_name - p_to));
3729 p_to32->s_proto = (p_base + (p_proto - p_to));
3730 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
Francois Gouget27202312001-11-14 21:26:23 +00003731 size += (sizeof(struct WS_servent) - sizeof(struct servent));
Andreas Mohrae509412000-08-03 22:19:09 +00003732 }
3733 }
3734 return size;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003735}
3736
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003737/* ----------------------------------- error handling */
3738
3739UINT16 wsaErrno(void)
3740{
3741 int loc_errno = errno;
Alexandre Julliard61fece01999-06-26 19:09:08 +00003742 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003743
3744 switch(loc_errno)
3745 {
3746 case EINTR: return WSAEINTR;
3747 case EBADF: return WSAEBADF;
Ove Kaavenf45608f1999-10-23 16:53:34 +00003748 case EPERM:
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003749 case EACCES: return WSAEACCES;
3750 case EFAULT: return WSAEFAULT;
3751 case EINVAL: return WSAEINVAL;
3752 case EMFILE: return WSAEMFILE;
3753 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3754 case EINPROGRESS: return WSAEINPROGRESS;
3755 case EALREADY: return WSAEALREADY;
3756 case ENOTSOCK: return WSAENOTSOCK;
3757 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3758 case EMSGSIZE: return WSAEMSGSIZE;
3759 case EPROTOTYPE: return WSAEPROTOTYPE;
3760 case ENOPROTOOPT: return WSAENOPROTOOPT;
3761 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3762 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3763 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3764 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3765 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3766 case EADDRINUSE: return WSAEADDRINUSE;
3767 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3768 case ENETDOWN: return WSAENETDOWN;
3769 case ENETUNREACH: return WSAENETUNREACH;
3770 case ENETRESET: return WSAENETRESET;
3771 case ECONNABORTED: return WSAECONNABORTED;
Alexandre Julliard54c27111998-03-29 19:44:57 +00003772 case EPIPE:
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003773 case ECONNRESET: return WSAECONNRESET;
3774 case ENOBUFS: return WSAENOBUFS;
3775 case EISCONN: return WSAEISCONN;
3776 case ENOTCONN: return WSAENOTCONN;
3777 case ESHUTDOWN: return WSAESHUTDOWN;
3778 case ETOOMANYREFS: return WSAETOOMANYREFS;
3779 case ETIMEDOUT: return WSAETIMEDOUT;
3780 case ECONNREFUSED: return WSAECONNREFUSED;
3781 case ELOOP: return WSAELOOP;
3782 case ENAMETOOLONG: return WSAENAMETOOLONG;
3783 case EHOSTDOWN: return WSAEHOSTDOWN;
3784 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3785 case ENOTEMPTY: return WSAENOTEMPTY;
3786#ifdef EPROCLIM
3787 case EPROCLIM: return WSAEPROCLIM;
3788#endif
3789#ifdef EUSERS
3790 case EUSERS: return WSAEUSERS;
3791#endif
3792#ifdef EDQUOT
3793 case EDQUOT: return WSAEDQUOT;
3794#endif
Alexandre Julliard349a9531997-02-02 19:01:52 +00003795#ifdef ESTALE
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003796 case ESTALE: return WSAESTALE;
Alexandre Julliard349a9531997-02-02 19:01:52 +00003797#endif
3798#ifdef EREMOTE
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003799 case EREMOTE: return WSAEREMOTE;
Alexandre Julliard349a9531997-02-02 19:01:52 +00003800#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003801
3802 /* just in case we ever get here and there are no problems */
3803 case 0: return 0;
3804 default:
Alexandre Julliard61fece01999-06-26 19:09:08 +00003805 WARN("Unknown errno %d!\n", loc_errno);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003806 return WSAEOPNOTSUPP;
3807 }
3808}
3809
Rein Klazesff7a61f2000-09-24 19:41:57 +00003810UINT16 wsaHerrno(int loc_errno)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003811{
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003812
Alexandre Julliard61fece01999-06-26 19:09:08 +00003813 WARN("h_errno %d.\n", loc_errno);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003814
3815 switch(loc_errno)
3816 {
3817 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3818 case TRY_AGAIN: return WSATRY_AGAIN;
3819 case NO_RECOVERY: return WSANO_RECOVERY;
3820 case NO_DATA: return WSANO_DATA;
Rein Klazesff7a61f2000-09-24 19:41:57 +00003821 case ENOBUFS: return WSAENOBUFS;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003822
3823 case 0: return 0;
3824 default:
Alexandre Julliard61fece01999-06-26 19:09:08 +00003825 WARN("Unknown h_errno %d!\n", loc_errno);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003826 return WSAEOPNOTSUPP;
3827 }
3828}
Peter Hunnisett77368762001-07-10 19:09:59 +00003829
3830
3831/***********************************************************************
Martin Wilck58854432002-04-05 21:22:55 +00003832 * WSARecv (WS2_32.67)
3833 */
3834int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3835 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3836 LPWSAOVERLAPPED lpOverlapped,
3837 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3838{
3839 return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3840 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3841}
3842
3843/***********************************************************************
Patrik Stridvalle9782fa2001-07-12 22:33:51 +00003844 * WSARecvFrom (WS2_32.69)
Peter Hunnisett77368762001-07-10 19:09:59 +00003845 */
3846INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
Francois Gouget27202312001-11-14 21:26:23 +00003847 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
Peter Hunnisett77368762001-07-10 19:09:59 +00003848 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3849 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
Martin Wilck58854432002-04-05 21:22:55 +00003850
Peter Hunnisett77368762001-07-10 19:09:59 +00003851{
Martin Wilckaf16c982002-04-25 21:34:24 +00003852 int i, n, fd, err = WSAENOTSOCK, flags, ret;
Martin Wilck58854432002-04-05 21:22:55 +00003853 struct iovec* iovec;
Martin Wilckaf16c982002-04-25 21:34:24 +00003854 struct ws2_async *wsa;
Martin Wilckaba59472002-04-17 16:46:49 +00003855 enum fd_type type;
Peter Hunnisett77368762001-07-10 19:09:59 +00003856
Martin Wilck58854432002-04-05 21:22:55 +00003857 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3858 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3859 (lpFromlen ? *lpFromlen : -1L),
3860 lpOverlapped, lpCompletionRoutine);
Peter Hunnisett77368762001-07-10 19:09:59 +00003861
Martin Wilckaf16c982002-04-25 21:34:24 +00003862 fd = _get_sock_fd_type( s, GENERIC_READ, &type, &flags );
3863 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
Martin Wilck58854432002-04-05 21:22:55 +00003864
3865 if (fd == -1)
Peter Hunnisett77368762001-07-10 19:09:59 +00003866 {
Martin Wilckaf16c982002-04-25 21:34:24 +00003867 err = WSAGetLastError ();
Martin Wilck58854432002-04-05 21:22:55 +00003868 goto error;
Peter Hunnisett77368762001-07-10 19:09:59 +00003869 }
3870
Martin Wilckaf16c982002-04-25 21:34:24 +00003871 iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
Martin Wilck58854432002-04-05 21:22:55 +00003872 if ( !iovec )
3873 {
Martin Wilckaf16c982002-04-25 21:34:24 +00003874 err = WSAEFAULT;
Martin Wilck58854432002-04-05 21:22:55 +00003875 goto err_close;
3876 }
Peter Hunnisett77368762001-07-10 19:09:59 +00003877
Martin Wilck58854432002-04-05 21:22:55 +00003878 for (i = 0; i < dwBufferCount; i++)
3879 {
3880 iovec[i].iov_base = lpBuffers[i].buf;
3881 iovec[i].iov_len = lpBuffers[i].len;
3882 }
3883
Martin Wilckaf16c982002-04-25 21:34:24 +00003884 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
Martin Wilck58854432002-04-05 21:22:55 +00003885 {
Martin Wilckaf16c982002-04-25 21:34:24 +00003886 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
3887 lpFlags, lpFrom, lpFromlen,
3888 lpOverlapped, lpCompletionRoutine );
Martin Wilck58854432002-04-05 21:22:55 +00003889
Martin Wilckaf16c982002-04-25 21:34:24 +00003890 if ( !wsa )
3891 {
3892 err = WSAEFAULT;
3893 goto err_free;
3894 }
3895
3896 if ( ( ret = register_new_async ( &wsa->async )) )
3897 {
3898 err = NtStatusToWSAError ( ret );
3899
3900 if ( !lpOverlapped )
3901 HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
3902 HeapFree ( GetProcessHeap(), 0, wsa );
3903 goto err_free;
3904 }
3905
3906 /* Try immediate completion */
3907 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
3908 {
3909 if ( WSAGetOverlappedResult ( (HANDLE) s, lpOverlapped,
3910 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3911 return 0;
3912
3913 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
3914 goto error;
3915 }
3916
3917 WSASetLastError ( WSA_IO_PENDING );
3918 return SOCKET_ERROR;
Martin Wilck58854432002-04-05 21:22:55 +00003919 }
Martin Wilck58854432002-04-05 21:22:55 +00003920
Martin Wilckaf16c982002-04-25 21:34:24 +00003921 if ( _is_blocking(s) )
Martin Wilck58854432002-04-05 21:22:55 +00003922 {
3923 /* block here */
3924 /* FIXME: OOB and exceptfds? */
3925 do_block(fd, 1);
3926 }
3927
Martin Wilckaf16c982002-04-25 21:34:24 +00003928 n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3929 if ( n == -1 )
Martin Wilck58854432002-04-05 21:22:55 +00003930 {
3931 err = wsaErrno();
3932 goto err_free;
3933 }
3934
Martin Wilckaf16c982002-04-25 21:34:24 +00003935 TRACE(" -> %i bytes\n", n);
3936 *lpNumberOfBytesRecvd = n;
Martin Wilck58854432002-04-05 21:22:55 +00003937
Martin Wilckaf16c982002-04-25 21:34:24 +00003938 HeapFree (GetProcessHeap(), 0, iovec);
Martin Wilck58854432002-04-05 21:22:55 +00003939 close(fd);
3940 _enable_event(s, FD_READ, 0, 0);
3941
3942 return 0;
3943
3944err_free:
Martin Wilckaf16c982002-04-25 21:34:24 +00003945 HeapFree (GetProcessHeap(), 0, iovec);
Martin Wilck58854432002-04-05 21:22:55 +00003946
3947err_close:
3948 close (fd);
3949
3950error:
3951 WARN(" -> ERROR %d\n", err);
Martin Wilckaf16c982002-04-25 21:34:24 +00003952 WSASetLastError ( err );
Martin Wilck58854432002-04-05 21:22:55 +00003953 return SOCKET_ERROR;
Peter Hunnisett77368762001-07-10 19:09:59 +00003954}
Andreas Mohrab968452001-10-02 17:46:59 +00003955
Andreas Mohrab968452001-10-02 17:46:59 +00003956/***********************************************************************
3957 * WSCInstallProvider (WS2_32.88)
3958 */
3959INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
3960 LPCWSTR lpszProviderDllPath,
3961 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
3962 DWORD dwNumberOfEntries,
3963 LPINT lpErrno )
3964{
3965 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
3966 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
3967 dwNumberOfEntries, lpErrno);
3968 *lpErrno = 0;
3969 return 0;
3970}
3971
3972
3973/***********************************************************************
3974 * WSCDeinstallProvider (WS2_32.83)
3975 */
3976INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
3977{
3978 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
3979 *lpErrno = 0;
3980 return 0;
3981}
Daniel Walker40491ec2002-01-14 18:33:44 +00003982
3983
Patrik Stridvall9ff202e2002-01-18 18:57:43 +00003984/***********************************************************************
3985 * WSAAccept (WS2_32.26)
3986 */
Daniel Walker40491ec2002-01-14 18:33:44 +00003987SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
3988 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
3989{
3990
3991 int ret = 0, size = 0;
3992 WSABUF CallerId, CallerData, CalleeId, CalleeData;
3993 /* QOS SQOS, GQOS; */
3994 GROUP g;
3995 SOCKET cs;
Francois Gougetf8850242002-01-29 02:55:24 +00003996 SOCKADDR src_addr, dst_addr;
Daniel Walker40491ec2002-01-14 18:33:44 +00003997
Martin Wilckd15bf1c2002-04-23 22:03:42 +00003998 TRACE("Socket %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
Daniel Walker40491ec2002-01-14 18:33:44 +00003999 s, addr, addrlen, lpfnCondition, dwCallbackData);
4000
4001
Francois Gougetf8850242002-01-29 02:55:24 +00004002 size = sizeof(src_addr);
4003 cs = WS_accept(s, &src_addr, &size);
Daniel Walker40491ec2002-01-14 18:33:44 +00004004
4005 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
4006
Francois Gougetf8850242002-01-29 02:55:24 +00004007 CallerId.buf = (char *)&src_addr;
4008 CallerId.len = sizeof(src_addr);
Daniel Walker40491ec2002-01-14 18:33:44 +00004009
4010 CallerData.buf = NULL;
4011 CallerData.len = (ULONG)NULL;
4012
Francois Gougetf8850242002-01-29 02:55:24 +00004013 WS_getsockname(cs, &dst_addr, &size);
Daniel Walker40491ec2002-01-14 18:33:44 +00004014
Francois Gougetf8850242002-01-29 02:55:24 +00004015 CalleeId.buf = (char *)&dst_addr;
4016 CalleeId.len = sizeof(dst_addr);
Daniel Walker40491ec2002-01-14 18:33:44 +00004017
4018
4019 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
4020 &CalleeId, &CalleeData, &g, dwCallbackData);
4021
4022 switch (ret)
4023 {
4024 case CF_ACCEPT:
4025 if (addr && addrlen)
Francois Gougetf8850242002-01-29 02:55:24 +00004026 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
Daniel Walker40491ec2002-01-14 18:33:44 +00004027 return cs;
4028 case CF_DEFER:
Martin Wilckd15bf1c2002-04-23 22:03:42 +00004029 SERVER_START_REQ ( set_socket_deferred )
4030 {
4031 req->handle = s;
4032 req->deferred = cs;
4033 if ( !wine_server_call_err ( req ) )
4034 {
4035 SetLastError ( WSATRY_AGAIN );
4036 CloseHandle ( cs );
4037 }
4038 }
4039 SERVER_END_REQ;
Daniel Walker40491ec2002-01-14 18:33:44 +00004040 return SOCKET_ERROR;
4041 case CF_REJECT:
4042 WS_closesocket(cs);
4043 SetLastError(WSAECONNREFUSED);
4044 return SOCKET_ERROR;
4045 default:
4046 FIXME("Unknown return type from Condition function\n");
4047 SetLastError(WSAENOTSOCK);
4048 return SOCKET_ERROR;
4049 }
4050
4051 SetLastError(WSAENOTSOCK);
4052 return SOCKET_ERROR;
4053}
4054
Mike McCormackee779552002-04-03 20:04:50 +00004055/***********************************************************************
4056 * WSAEnumProtocolsA (WS2_32.37)
4057 */
Stefan Leichterf25efa02002-04-11 17:34:46 +00004058int WINAPI WSAEnumProtocolsA(LPINT lpiProtocols, LPWSAPROTOCOL_INFOA lpProtocolBuffer, LPDWORD lpdwBufferLength)
Mike McCormackee779552002-04-03 20:04:50 +00004059{
4060 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4061 return 0;
4062}
4063
4064/***********************************************************************
4065 * WSAEnumProtocolsW (WS2_32.38)
4066 */
Stefan Leichterf25efa02002-04-11 17:34:46 +00004067int WINAPI WSAEnumProtocolsW(LPINT lpiProtocols, LPWSAPROTOCOL_INFOW lpProtocolBuffer, LPDWORD lpdwBufferLength)
Mike McCormackee779552002-04-03 20:04:50 +00004068{
4069 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4070 return 0;
4071}
4072
4073