blob: f49c2d06294795b4af3506094c7595778260ac40 [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 Julliard670cdc41997-08-24 16:00:30 +00005 * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
Alexandre Julliard23946ad1997-06-16 17:43:53 +00006 *
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00007 * NOTE: If you make any changes to fix a particular app, make sure
8 * they don't break something else like Netscape or telnet and ftp
9 * clients and servers (www.winsite.com got a lot of those).
10 *
Andreas Mohrae509412000-08-03 22:19:09 +000011 * NOTE 2: Many winsock structs such as servent, hostent, protoent, ...
12 * are used with 1-byte alignment for Win16 programs and 4-byte alignment
13 * for Win32 programs in winsock.h. winsock2.h uses forced 4-byte alignment.
14 * So we have non-forced (just as MSDN) ws_XXXXent (winsock.h), 4-byte forced
15 * ws_XXXXent32 (winsock2.h) and 1-byte forced ws_XXXXent16 (winsock16.h).
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000016 */
17
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000018#include "config.h"
19
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000020#include <string.h>
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000021#include <sys/types.h>
Patrik Stridvall2c928351999-10-31 02:07:54 +000022#ifdef HAVE_SYS_IPC_H
23# include <sys/ipc.h>
24#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000025#include <sys/ioctl.h>
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000026#ifdef HAVE_SYS_FILIO_H
27# include <sys/filio.h>
28#endif
Patrik Stridvall2c928351999-10-31 02:07:54 +000029#ifdef HAVE_SYS_SOCKIO_H
30# include <sys/sockio.h>
31#endif
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000032
Alexandre Julliard01d63461997-01-20 19:43:45 +000033#if defined(__EMX__)
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000034# include <sys/so_ioctl.h>
Alexandre Julliard01d63461997-01-20 19:43:45 +000035#endif
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000036
37#ifdef HAVE_SYS_PARAM_H
38# include <sys/param.h>
39#endif
40
Patrik Stridvall2c928351999-10-31 02:07:54 +000041#ifdef HAVE_SYS_MSG_H
42# include <sys/msg.h>
43#endif
44#ifdef HAVE_SYS_WAIT_H
45# include <sys/wait.h>
46#endif
47#ifdef HAVE_SYS_SOCKET_H
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000048#include <sys/socket.h>
Patrik Stridvall2c928351999-10-31 02:07:54 +000049#endif
50#ifdef HAVE_NETINET_IN_H
51# include <netinet/in.h>
52#endif
53#ifdef HAVE_NETINET_TCP_H
54# include <netinet/tcp.h>
55#endif
56#ifdef HAVE_ARPA_INET_H
57# include <arpa/inet.h>
58#endif
Alexandre Julliard60ce85c1998-02-01 18:33:27 +000059#include <ctype.h>
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000060#include <fcntl.h>
61#include <errno.h>
Howard Abrams13277481999-07-10 13:16:29 +000062#ifdef HAVE_SYS_ERRNO_H
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000063#include <sys/errno.h>
Howard Abrams13277481999-07-10 13:16:29 +000064#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000065#include <netdb.h>
66#include <unistd.h>
Michael Vekslerca1bc861999-01-01 18:57:33 +000067#include <stdlib.h>
Marcus Meissner664c2721999-02-28 11:23:44 +000068#ifdef HAVE_ARPA_NAMESER_H
69# include <arpa/nameser.h>
70#endif
Marcus Meissner3b092841999-02-20 16:46:39 +000071#ifdef HAVE_RESOLV_H
72# include <resolv.h>
73#endif
James Hathewayc9d25822000-07-23 19:28:24 +000074#ifdef HAVE_NET_IF_H
75# include <net/if.h>
76#endif
Alexandre Julliard83f52d12000-09-26 22:20:14 +000077#ifdef HAVE_IPX_GNU
78# include <netipx/ipx.h>
79# define HAVE_IPX
80#endif
81#ifdef HAVE_IPX_LINUX
82# include <asm/types.h>
83# include <linux/ipx.h>
84# define HAVE_IPX
85#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000086
Marcus Meissner04c3e1d1999-02-19 10:37:02 +000087#include "wine/winbase16.h"
Patrik Stridvall6cc47d42000-03-08 18:26:56 +000088#include "wingdi.h"
89#include "winuser.h"
Ove Kaavenf45608f1999-10-23 16:53:34 +000090#include "winsock2.h"
Andreas Mohrae509412000-08-03 22:19:09 +000091#include "wine/winsock16.h"
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000092#include "winnt.h"
93#include "heap.h"
Alexandre Julliard670cdc41997-08-24 16:00:30 +000094#include "task.h"
Patrik Stridvallb9010211999-11-13 22:23:35 +000095#include "wine/port.h"
Ove Kaavenf45608f1999-10-23 16:53:34 +000096#include "services.h"
97#include "server.h"
Alexandre Julliard92643002000-08-31 01:59:51 +000098#include "file.h"
Alexandre Julliard61fece01999-06-26 19:09:08 +000099#include "debugtools.h"
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000100
James Hathewayc9d25822000-07-23 19:28:24 +0000101
Alexandre Julliard5ab9d862000-08-09 22:35:05 +0000102DEFAULT_DEBUG_CHANNEL(winsock);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +0000103
Rein Klazesff7a61f2000-09-24 19:41:57 +0000104/* critical section to protect some non-rentrant net function */
105extern CRITICAL_SECTION csWSgetXXXbyYYY;
106
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000107#define DEBUG_SOCKADDR 0
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000108#define dump_sockaddr(a) \
Alexandre Julliard61fece01999-06-26 19:09:08 +0000109 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000110 ((struct sockaddr_in *)a)->sin_family, \
111 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
112 ntohs(((struct sockaddr_in *)a)->sin_port))
113
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000114/* ----------------------------------- internal data */
115
Ove Kaavenf45608f1999-10-23 16:53:34 +0000116/* ws_... struct conversion flags */
117
118#define WS_DUP_LINEAR 0x0001
119#define WS_DUP_NATIVE 0x0000 /* not used anymore */
120#define WS_DUP_OFFSET 0x0002 /* internal pointers are offsets */
121#define WS_DUP_SEGPTR 0x0004 /* internal pointers are SEGPTRs */
122 /* by default, internal pointers are linear */
123typedef struct /* WSAAsyncSelect() control struct */
124{
125 HANDLE service, event, sock;
126 HWND hWnd;
127 UINT uMsg;
Ove Kaavencb98a6e2000-03-26 18:21:16 +0000128 LONG lEvent;
129 struct _WSINFO *pwsi;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000130} ws_select_info;
131
132#define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
133#define WS_MAX_UDP_DATAGRAM 1024
134
Ove Kaavencb98a6e2000-03-26 18:21:16 +0000135#define WS_ACCEPT_QUEUE 6
136
Ove Kaavenf45608f1999-10-23 16:53:34 +0000137#define WSI_BLOCKINGCALL 0x00000001 /* per-thread info flags */
138#define WSI_BLOCKINGHOOK 0x00000002 /* 32-bit callback */
139
James Hathewayc9d25822000-07-23 19:28:24 +0000140#define PROCFS_NETDEV_FILE "/proc/net/dev" /* Points to the file in the /proc fs
141 that lists the network devices.
142 Do we need an #ifdef LINUX for this? */
143
Ove Kaavenf45608f1999-10-23 16:53:34 +0000144typedef struct _WSINFO
145{
146 DWORD dwThisProcess;
147 struct _WSINFO *lpNextIData;
148
149 unsigned flags;
150 INT16 num_startup; /* reference counter */
151 INT16 num_async_rq;
152 INT16 last_free; /* entry in the socket table */
153 UINT16 buflen;
154 char* buffer; /* allocated from SEGPTR heap */
Andreas Mohrae509412000-08-03 22:19:09 +0000155 void *he; /* typecast for Win16/32 ws_hostent */
Ove Kaavenf45608f1999-10-23 16:53:34 +0000156 int helen;
Andreas Mohrae509412000-08-03 22:19:09 +0000157 void *se; /* typecast for Win16/32 ws_servent */
Ove Kaavenf45608f1999-10-23 16:53:34 +0000158 int selen;
Andreas Mohrae509412000-08-03 22:19:09 +0000159 void *pe; /* typecast for Win16/32 ws_protoent */
Ove Kaavenf45608f1999-10-23 16:53:34 +0000160 int pelen;
161 char* dbuffer; /* buffer for dummies (32 bytes) */
162
163 DWORD blocking_hook;
Ove Kaavencb98a6e2000-03-26 18:21:16 +0000164
165 volatile HANDLE accept_old[WS_ACCEPT_QUEUE], accept_new[WS_ACCEPT_QUEUE];
Ove Kaavenf45608f1999-10-23 16:53:34 +0000166} WSINFO, *LPWSINFO;
167
168/* function prototypes */
169int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag);
170int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag);
171int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag);
172
Andreas Mohrae509412000-08-03 22:19:09 +0000173typedef void WIN_hostent;
174typedef void WIN_protoent;
175typedef void WIN_servent;
176
James Hathewayc9d25822000-07-23 19:28:24 +0000177int WSAIOCTL_GetInterfaceCount(void);
178int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
179
Ove Kaavenf45608f1999-10-23 16:53:34 +0000180UINT16 wsaErrno(void);
Rein Klazesff7a61f2000-09-24 19:41:57 +0000181UINT16 wsaHerrno(int errnr);
Ove Kaavenf45608f1999-10-23 16:53:34 +0000182
Alexandre Julliarda3960291999-02-26 11:11:13 +0000183static HANDLE _WSHeap = 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000184
185#define WS_ALLOC(size) \
186 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
187#define WS_FREE(ptr) \
188 HeapFree(_WSHeap, 0, (ptr) )
189
Alexandre Julliarda3960291999-02-26 11:11:13 +0000190static INT _ws_sock_ops[] =
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000191 { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
192 WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
John Gilmore5180d562000-09-16 20:51:40 +0000193 WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE,
Marcus Meissner751dc4c1999-03-24 14:53:55 +0000194#ifdef SO_RCVTIMEO
195 WS_SO_RCVTIMEO,
196#endif
John Gilmore5180d562000-09-16 20:51:40 +0000197#ifdef SO_SNDTIMEO
198 WS_SO_SNDTIMEO,
199#endif
Marcus Meissner751dc4c1999-03-24 14:53:55 +0000200 0 };
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000201static int _px_sock_ops[] =
202 { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
203 SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
Marcus Meissner751dc4c1999-03-24 14:53:55 +0000204#ifdef SO_RCVTIMEO
205 SO_RCVTIMEO,
206#endif
John Gilmore5180d562000-09-16 20:51:40 +0000207#ifdef SO_SNDTIMEO
208 SO_SNDTIMEO,
209#endif
Marcus Meissner751dc4c1999-03-24 14:53:55 +0000210 };
Marcus Meissner5eaf7751999-03-09 17:31:42 +0000211
212static INT _ws_tcp_ops[] = {
213#ifdef TCP_NODELAY
214 WS_TCP_NODELAY,
215#endif
216 0
217};
218static int _px_tcp_ops[] = {
219#ifdef TCP_NODELAY
220 TCP_NODELAY,
221#endif
222 0
223};
224
Alexandre Julliardcb1fc732000-01-24 21:58:06 +0000225/* we need a special routine to handle WSA* errors */
226static inline int sock_server_call( enum request req )
227{
228 unsigned int res = server_call_noerr( req );
229 if (res)
230 {
231 /* do not map WSA errors */
232 if ((res < WSABASEERR) || (res >= 0x10000000)) res = RtlNtStatusToDosError(res);
233 SetLastError( res );
234 }
235 return res;
236}
237
Ove Kaavenf45608f1999-10-23 16:53:34 +0000238static int _check_ws(LPWSINFO pwsi, SOCKET s);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000239static char* _check_buffer(LPWSINFO pwsi, int size);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000240
Ove Kaavenf45608f1999-10-23 16:53:34 +0000241static int _get_sock_fd(SOCKET s)
Marcus Meissnerbdb6bec1999-04-10 16:58:55 +0000242{
Alexandre Julliard92643002000-08-31 01:59:51 +0000243 int fd = FILE_GetUnixHandle( s, GENERIC_READ );
Ove Kaavenf45608f1999-10-23 16:53:34 +0000244 if (fd == -1)
245 FIXME("handle %d is not a socket (GLE %ld)\n",s,GetLastError());
246 return fd;
Marcus Meissnerbdb6bec1999-04-10 16:58:55 +0000247}
248
Ove Kaavenf45608f1999-10-23 16:53:34 +0000249static void _enable_event(SOCKET s, unsigned int event,
250 unsigned int sstate, unsigned int cstate)
251{
Alexandre Julliard92643002000-08-31 01:59:51 +0000252 SERVER_START_REQ
253 {
254 struct enable_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
255
256 req->handle = s;
257 req->mask = event;
258 req->sstate = sstate;
259 req->cstate = cstate;
260 sock_server_call( REQ_ENABLE_SOCKET_EVENT );
261 }
262 SERVER_END_REQ;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000263}
264
265static int _is_blocking(SOCKET s)
266{
Alexandre Julliard92643002000-08-31 01:59:51 +0000267 int ret;
268 SERVER_START_REQ
269 {
270 struct get_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
271
272 req->handle = s;
273 req->service = FALSE;
274 req->s_event = 0;
275 req->c_event = 0;
276 sock_server_call( REQ_GET_SOCKET_EVENT );
277 ret = (req->state & WS_FD_NONBLOCKING) == 0;
278 }
279 SERVER_END_REQ;
280 return ret;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000281}
282
283static unsigned int _get_sock_mask(SOCKET s)
284{
Alexandre Julliard92643002000-08-31 01:59:51 +0000285 unsigned int ret;
286 SERVER_START_REQ
287 {
288 struct get_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
289
290 req->handle = s;
291 req->service = FALSE;
292 req->s_event = 0;
293 req->c_event = 0;
294 sock_server_call( REQ_GET_SOCKET_EVENT );
295 ret = req->mask;
296 }
297 SERVER_END_REQ;
298 return ret;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000299}
300
301static void _sync_sock_state(SOCKET s)
302{
303 /* do a dummy wineserver request in order to let
304 the wineserver run through its select loop once */
305 (void)_is_blocking(s);
306}
307
308static int _get_sock_error(SOCKET s, unsigned int bit)
309{
Alexandre Julliard92643002000-08-31 01:59:51 +0000310 int ret;
311 SERVER_START_REQ
312 {
313 struct get_socket_event_request *req = server_alloc_req( sizeof(*req),
314 FD_MAX_EVENTS*sizeof(int) );
315 req->handle = s;
316 req->service = FALSE;
317 req->s_event = 0;
318 req->c_event = 0;
319 sock_server_call( REQ_GET_SOCKET_EVENT );
320 ret = *((int *)server_data_ptr(req) + bit);
321 }
322 SERVER_END_REQ;
323 return ret;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000324}
325
326static LPWSINFO lpFirstIData = NULL;
327
328static LPWSINFO WINSOCK_GetIData(void)
329{
330 DWORD pid = GetCurrentProcessId();
331 LPWSINFO iData;
332
333 for (iData = lpFirstIData; iData; iData = iData->lpNextIData) {
334 if (iData->dwThisProcess == pid)
335 break;
336 }
337 return iData;
338}
339
340static BOOL WINSOCK_CreateIData(void)
341{
342 LPWSINFO iData;
343
344 iData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WSINFO));
345 if (!iData)
346 return FALSE;
347 iData->dwThisProcess = GetCurrentProcessId();
348 iData->lpNextIData = lpFirstIData;
349 lpFirstIData = iData;
350 return TRUE;
351}
352
353static void WINSOCK_DeleteIData(void)
354{
355 LPWSINFO iData = WINSOCK_GetIData();
356 LPWSINFO* ppid;
357 if (iData) {
358 for (ppid = &lpFirstIData; *ppid; ppid = &(*ppid)->lpNextIData) {
359 if (*ppid == iData) {
360 *ppid = iData->lpNextIData;
361 break;
362 }
363 }
364
365 if( iData->flags & WSI_BLOCKINGCALL )
366 TRACE("\tinside blocking call!\n");
367
368 /* delete scratch buffers */
369
370 if( iData->buffer ) SEGPTR_FREE(iData->buffer);
371 if( iData->dbuffer ) SEGPTR_FREE(iData->dbuffer);
372
373 HeapFree(GetProcessHeap(), 0, iData);
374 }
375}
376
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000377/***********************************************************************
378 * WSOCK32_LibMain (WSOCK32.init)
379 */
Ove Kaavenf45608f1999-10-23 16:53:34 +0000380BOOL WINAPI WSOCK32_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
381{
382 TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
383 switch (fdwReason) {
384 case DLL_PROCESS_DETACH:
385 WINSOCK_DeleteIData();
386 break;
387 }
388 return TRUE;
389}
390
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000391/***********************************************************************
392 * WINSOCK_LibMain (WINSOCK.init)
393 */
Ove Kaavenf45608f1999-10-23 16:53:34 +0000394BOOL WINAPI WINSOCK_LibMain(DWORD fdwReason, HINSTANCE hInstDLL, WORD ds,
395 WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
396{
397 TRACE("0x%x 0x%lx\n", hInstDLL, fdwReason);
398 switch (fdwReason) {
399 case DLL_PROCESS_DETACH:
400 WINSOCK_DeleteIData();
401 break;
402 }
403 return TRUE;
404}
405
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000406/***********************************************************************
407 * convert_sockopt()
408 *
409 * Converts socket flags from Windows format.
John Gilmore5180d562000-09-16 20:51:40 +0000410 * Return 1 if converted, 0 if not (error).
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000411 */
John Gilmore5180d562000-09-16 20:51:40 +0000412static int convert_sockopt(INT *level, INT *optname)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000413{
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000414 int i;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000415 switch (*level)
416 {
417 case WS_SOL_SOCKET:
418 *level = SOL_SOCKET;
419 for(i=0; _ws_sock_ops[i]; i++)
420 if( _ws_sock_ops[i] == *optname ) break;
John Gilmore5180d562000-09-16 20:51:40 +0000421 if( _ws_sock_ops[i] ) {
422 *optname = _px_sock_ops[i];
423 return 1;
424 }
425 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000426 break;
427 case WS_IPPROTO_TCP:
Marcus Meissner5eaf7751999-03-09 17:31:42 +0000428 *level = IPPROTO_TCP;
429 for(i=0; _ws_tcp_ops[i]; i++)
430 if ( _ws_tcp_ops[i] == *optname ) break;
John Gilmore5180d562000-09-16 20:51:40 +0000431 if( _ws_tcp_ops[i] ) {
432 *optname = _px_tcp_ops[i];
433 return 1;
434 }
435 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
Marcus Meissner5eaf7751999-03-09 17:31:42 +0000436 break;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000437 }
John Gilmore5180d562000-09-16 20:51:40 +0000438 return 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000439}
440
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000441/* ----------------------------------- Per-thread info (or per-process?) */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000442
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000443static int wsi_strtolo(LPWSINFO pwsi, const char* name, const char* opt)
444{
445 /* Stuff a lowercase copy of the string into the local buffer */
446
447 int i = strlen(name) + 2;
448 char* p = _check_buffer(pwsi, i + ((opt)?strlen(opt):0));
449
450 if( p )
451 {
452 do *p++ = tolower(*name); while(*name++);
453 i = (p - (char*)(pwsi->buffer));
454 if( opt ) do *p++ = tolower(*opt); while(*opt++);
455 return i;
456 }
457 return 0;
458}
459
Ove Kaavenf45608f1999-10-23 16:53:34 +0000460static fd_set* fd_set_import( fd_set* fds, LPWSINFO pwsi, void* wsfds, int* highfd, int lfd[], BOOL b32 )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000461{
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000462 /* translate Winsock fd set into local fd set */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000463
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000464 if( wsfds )
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000465 {
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000466#define wsfds16 ((ws_fd_set16*)wsfds)
467#define wsfds32 ((ws_fd_set32*)wsfds)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000468 int i, count;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000469
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000470 FD_ZERO(fds);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000471 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
472
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000473 for( i = 0; i < count; i++ )
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000474 {
Ove Kaavenf45608f1999-10-23 16:53:34 +0000475 int s = (b32) ? wsfds32->fd_array[i]
476 : wsfds16->fd_array[i];
477 if( _check_ws(pwsi, s) )
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000478 {
Ove Kaavenf45608f1999-10-23 16:53:34 +0000479 int fd = _get_sock_fd(s);
480 lfd[ i ] = fd;
481 if( fd > *highfd ) *highfd = fd;
482 FD_SET(fd, fds);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000483 }
Ove Kaavenf45608f1999-10-23 16:53:34 +0000484 else lfd[ i ] = -1;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000485 }
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000486#undef wsfds32
487#undef wsfds16
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000488 return fds;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000489 }
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000490 return NULL;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000491}
492
Patrik Stridvall896889f1999-05-08 12:50:36 +0000493inline static int sock_error_p(int s)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000494{
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000495 unsigned int optval, optlen;
496
497 optlen = sizeof(optval);
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000498 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
Alexandre Julliard61fece01999-06-26 19:09:08 +0000499 if (optval) WARN("\t[%i] error: %d\n", s, optval);
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000500 return optval != 0;
501}
502
Ove Kaavenf45608f1999-10-23 16:53:34 +0000503static int fd_set_export( LPWSINFO pwsi, fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000504{
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000505 int num_err = 0;
506
507 /* translate local fd set into Winsock fd set, adding
508 * errors to exceptfds (only if app requested it) */
509
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000510 if( wsfds )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000511 {
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000512#define wsfds16 ((ws_fd_set16*)wsfds)
513#define wsfds32 ((ws_fd_set32*)wsfds)
514 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000515
516 for( i = 0, j = 0; i < count; i++ )
517 {
Ove Kaavenf45608f1999-10-23 16:53:34 +0000518 if( lfd[i] >= 0 )
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000519 {
Ove Kaavenf45608f1999-10-23 16:53:34 +0000520 int fd = lfd[i];
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000521 if( FD_ISSET(fd, fds) )
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000522 {
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000523 if ( exceptfds && sock_error_p(fd) )
524 {
525 FD_SET(fd, exceptfds);
526 num_err++;
527 }
528 else if( b32 )
529 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
530 else
531 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000532 }
Ove Kaavenf45608f1999-10-23 16:53:34 +0000533 close(fd);
534 lfd[i] = -1;
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000535 }
536 }
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000537
538 if( b32 ) wsfds32->fd_count = j;
539 else wsfds16->fd_count = j;
540
Alexandre Julliard61fece01999-06-26 19:09:08 +0000541 TRACE("\n");
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000542#undef wsfds32
543#undef wsfds16
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000544 }
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000545 return num_err;
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000546}
547
Ove Kaavenf45608f1999-10-23 16:53:34 +0000548static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000549{
Ove Kaavenf45608f1999-10-23 16:53:34 +0000550 if ( wsfds )
551 {
552#define wsfds16 ((ws_fd_set16*)wsfds)
553#define wsfds32 ((ws_fd_set32*)wsfds)
554 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
555
556 for( i = 0; i < count; i++ )
557 if ( lfd[i] >= 0 )
558 close(lfd[i]);
559
560 TRACE("\n");
561#undef wsfds32
562#undef wsfds16
563 }
564}
565
566static int do_block( int fd, int mask )
567{
568 fd_set fds[3];
569 int i, r;
570
571 FD_ZERO(&fds[0]);
572 FD_ZERO(&fds[1]);
573 FD_ZERO(&fds[2]);
574 for (i=0; i<3; i++)
575 if (mask & (1<<i))
576 FD_SET(fd, &fds[i]);
577 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
578 if (i <= 0) return -1;
579 r = 0;
580 for (i=0; i<3; i++)
581 if (FD_ISSET(fd, &fds[i]))
582 r |= 1<<i;
583 return r;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000584}
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000585
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000586void* __ws_memalloc( int size )
587{
588 return WS_ALLOC(size);
589}
Alexandre Julliard7e6ae4b1996-12-08 19:25:27 +0000590
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000591void __ws_memfree(void* ptr)
592{
593 WS_FREE(ptr);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000594}
595
Ulrich Weigand89fc6fd1999-05-24 08:13:02 +0000596
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000597/* ----------------------------------- API -----
598 *
599 * Init / cleanup / error checking.
600 */
601
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000602/***********************************************************************
603 * WSAStartup16() (WINSOCK.115)
604 *
605 * Create socket control struct, attach it to the global list and
606 * update a pointer in the task struct.
607 */
608INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA lpWSAData)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000609{
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000610 WSADATA WINSOCK_data = { 0x0101, 0x0101,
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000611 "WINE Sockets 1.1",
612 #ifdef linux
613 "Linux/i386",
614 #elif defined(__NetBSD__)
615 "NetBSD/i386",
616 #elif defined(sunos)
617 "SunOS",
618 #elif defined(__FreeBSD__)
619 "FreeBSD",
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000620 #elif defined(__OpenBSD__)
621 "OpenBSD/i386",
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000622 #else
623 "Unknown",
624 #endif
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000625 WS_MAX_SOCKETS_PER_PROCESS,
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000626 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000627 LPWSINFO pwsi;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000628
Alexandre Julliard61fece01999-06-26 19:09:08 +0000629 TRACE("verReq=%x\n", wVersionRequested);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000630
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000631 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
632 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000633
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000634 if (!lpWSAData) return WSAEINVAL;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000635
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000636 /* initialize socket heap */
637
Ove Kaavenf45608f1999-10-23 16:53:34 +0000638 if( !_WSHeap )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000639 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000640 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
Ove Kaavenf45608f1999-10-23 16:53:34 +0000641 if( !_WSHeap )
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000642 {
Alexandre Julliard61fece01999-06-26 19:09:08 +0000643 ERR("Fatal: failed to create WinSock heap\n");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000644 return 0;
645 }
646 }
647 if( _WSHeap == 0 ) return WSASYSNOTREADY;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000648
Ove Kaavenf45608f1999-10-23 16:53:34 +0000649 pwsi = WINSOCK_GetIData();
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000650 if( pwsi == NULL )
651 {
Ove Kaavenf45608f1999-10-23 16:53:34 +0000652 WINSOCK_CreateIData();
653 pwsi = WINSOCK_GetIData();
654 if (!pwsi) return WSASYSNOTREADY;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000655 }
Marcus Meissner17d455b1999-09-29 12:10:44 +0000656 pwsi->num_startup++;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000657
658 /* return winsock information */
659
660 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
661
Alexandre Julliard61fece01999-06-26 19:09:08 +0000662 TRACE("succeeded\n");
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000663 return 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000664}
665
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000666/***********************************************************************
Alexandre Julliardc6075322000-07-09 11:19:35 +0000667 * WSAStartup() (WS2_32.115)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000668 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000669INT WINAPI WSAStartup(UINT wVersionRequested, LPWSADATA lpWSAData)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000670{
James Hatheway829405a2000-06-18 17:23:17 +0000671 WSADATA WINSOCK_data = { 0x0202, 0x0202,
672 "WINE Sockets 2.0",
673 #ifdef linux
674 "Linux/i386",
675 #elif defined(__NetBSD__)
676 "NetBSD/i386",
677 #elif defined(sunos)
678 "SunOS",
679 #elif defined(__FreeBSD__)
680 "FreeBSD",
681 #elif defined(__OpenBSD__)
682 "OpenBSD/i386",
683 #else
684 "Unknown",
685 #endif
686 WS_MAX_SOCKETS_PER_PROCESS,
687 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
688 LPWSINFO pwsi;
689
690 TRACE("verReq=%x\n", wVersionRequested);
691
Alexandre Julliardc6075322000-07-09 11:19:35 +0000692 if (LOBYTE(wVersionRequested) < 1)
James Hatheway829405a2000-06-18 17:23:17 +0000693 return WSAVERNOTSUPPORTED;
694
695 if (!lpWSAData) return WSAEINVAL;
696
697 /* initialize socket heap */
698
699 if( !_WSHeap )
700 {
701 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
702 if( !_WSHeap )
703 {
704 ERR("Fatal: failed to create WinSock heap\n");
705 return 0;
706 }
707 }
708 if( _WSHeap == 0 ) return WSASYSNOTREADY;
709
710 pwsi = WINSOCK_GetIData();
711 if( pwsi == NULL )
712 {
713 WINSOCK_CreateIData();
714 pwsi = WINSOCK_GetIData();
715 if (!pwsi) return WSASYSNOTREADY;
716 }
717 pwsi->num_startup++;
718
719 /* return winsock information */
720 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
721
Gerard Patel0b42d3c2000-07-10 10:57:46 +0000722 /* that's the whole of the negotiation for now */
723 lpWSAData->wVersion = wVersionRequested;
724
James Hatheway829405a2000-06-18 17:23:17 +0000725 TRACE("succeeded\n");
726 return 0;
727}
728
729
730/***********************************************************************
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000731 * WSACleanup() (WINSOCK.116)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000732 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000733INT WINAPI WSACleanup(void)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000734{
Ove Kaavenf45608f1999-10-23 16:53:34 +0000735 LPWSINFO pwsi = WINSOCK_GetIData();
736 if( pwsi ) {
737 if( --pwsi->num_startup > 0 ) return 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000738
Ove Kaavenf45608f1999-10-23 16:53:34 +0000739 WINSOCK_DeleteIData();
740 return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000741 }
Ove Kaaven4ff3b202000-03-04 19:29:42 +0000742 SetLastError(WSANOTINITIALISED);
Ove Kaavenf45608f1999-10-23 16:53:34 +0000743 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000744}
745
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000746
747/***********************************************************************
748 * WSAGetLastError() (WSOCK32.111)(WINSOCK.111)
749 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000750INT WINAPI WSAGetLastError(void)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000751{
Marcus Meissner01f3dc31999-05-12 10:34:03 +0000752 return GetLastError();
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000753}
754
755/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +0000756 * WSASetLastError() (WSOCK32.112)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000757 */
Marcus Meissner01f3dc31999-05-12 10:34:03 +0000758void WINAPI WSASetLastError(INT iError) {
759 SetLastError(iError);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000760}
761
762/***********************************************************************
763 * WSASetLastError16() (WINSOCK.112)
764 */
765void WINAPI WSASetLastError16(INT16 iError)
766{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000767 WSASetLastError(iError);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000768}
769
Ove Kaavenf45608f1999-10-23 16:53:34 +0000770int _check_ws(LPWSINFO pwsi, SOCKET s)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000771{
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000772 if( pwsi )
Jesper Skov5c3e4571998-11-01 19:27:22 +0000773 {
Ove Kaavenf45608f1999-10-23 16:53:34 +0000774 int fd;
Marcus Meissner01f3dc31999-05-12 10:34:03 +0000775 if( pwsi->flags & WSI_BLOCKINGCALL ) SetLastError(WSAEINPROGRESS);
Ove Kaavenf45608f1999-10-23 16:53:34 +0000776 if ( (fd = _get_sock_fd(s)) < 0 ) {
777 SetLastError(WSAENOTSOCK);
778 return 0;
779 }
780 /* FIXME: maybe check whether fd is really a socket? */
781 close( fd );
782 return 1;
Jesper Skov5c3e4571998-11-01 19:27:22 +0000783 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000784 return 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000785}
786
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000787char* _check_buffer(LPWSINFO pwsi, int size)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000788{
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000789 if( pwsi->buffer && pwsi->buflen >= size ) return pwsi->buffer;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000790 else SEGPTR_FREE(pwsi->buffer);
791
792 pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size));
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000793 return pwsi->buffer;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000794}
795
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000796struct ws_hostent* _check_buffer_he(LPWSINFO pwsi, int size)
797{
798 if( pwsi->he && pwsi->helen >= size ) return pwsi->he;
799 else SEGPTR_FREE(pwsi->he);
800
Andreas Mohrae509412000-08-03 22:19:09 +0000801 pwsi->he = SEGPTR_ALLOC((pwsi->helen = size));
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000802 return pwsi->he;
803}
804
Andreas Mohrae509412000-08-03 22:19:09 +0000805void* _check_buffer_se(LPWSINFO pwsi, int size)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000806{
807 if( pwsi->se && pwsi->selen >= size ) return pwsi->se;
808 else SEGPTR_FREE(pwsi->se);
809
Andreas Mohrae509412000-08-03 22:19:09 +0000810 pwsi->se = SEGPTR_ALLOC((pwsi->selen = size));
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000811 return pwsi->se;
812}
813
814struct ws_protoent* _check_buffer_pe(LPWSINFO pwsi, int size)
815{
816 if( pwsi->pe && pwsi->pelen >= size ) return pwsi->pe;
817 else SEGPTR_FREE(pwsi->pe);
818
Andreas Mohrae509412000-08-03 22:19:09 +0000819 pwsi->pe = SEGPTR_ALLOC((pwsi->pelen = size));
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000820 return pwsi->pe;
821}
822
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000823/* ----------------------------------- i/o APIs */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000824
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000825/***********************************************************************
826 * accept() (WSOCK32.1)
827 */
Ove Kaavencb98a6e2000-03-26 18:21:16 +0000828static void WSOCK32_async_accept(LPWSINFO pwsi, SOCKET s, SOCKET as)
829{
830 int q;
831 /* queue socket for WSAAsyncSelect */
832 for (q=0; q<WS_ACCEPT_QUEUE; q++)
833 if (InterlockedCompareExchange((PVOID*)&pwsi->accept_old[q], (PVOID)s, (PVOID)0) == (PVOID)0)
834 break;
835 if (q<WS_ACCEPT_QUEUE)
836 pwsi->accept_new[q] = as;
837 else
838 ERR("accept queue too small\n");
839 /* now signal our AsyncSelect handler */
840 _enable_event(s, WS_FD_SERVEVENT, 0, 0);
841}
842
Patrik Stridvallfcfacb92000-03-24 20:46:04 +0000843SOCKET WINAPI WSOCK32_accept(SOCKET s, struct sockaddr *addr,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000844 INT *addrlen32)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000845{
Ove Kaavenf45608f1999-10-23 16:53:34 +0000846 LPWSINFO pwsi = WINSOCK_GetIData();
Pavel Roskin94d99641998-12-26 11:52:51 +0000847#ifdef HAVE_IPX
Stephen Langasekdc163421998-11-08 15:42:40 +0000848 struct ws_sockaddr_ipx* addr2 = (struct ws_sockaddr_ipx *)addr;
849#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000850
Alexandre Julliard61fece01999-06-26 19:09:08 +0000851 TRACE("(%08x): socket %04x\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000852 (unsigned)pwsi, (UINT16)s );
Ove Kaavenf45608f1999-10-23 16:53:34 +0000853 if( _check_ws(pwsi, s) )
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000854 {
Alexandre Julliard92643002000-08-31 01:59:51 +0000855 SOCKET as;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000856 if (_is_blocking(s))
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000857 {
Ove Kaavenf45608f1999-10-23 16:53:34 +0000858 /* block here */
859 int fd = _get_sock_fd(s);
860 do_block(fd, 5);
861 close(fd);
862 _sync_sock_state(s); /* let wineserver notice connection */
863 /* retrieve any error codes from it */
864 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
865 /* FIXME: care about the error? */
866 }
Alexandre Julliard92643002000-08-31 01:59:51 +0000867 SERVER_START_REQ
868 {
869 struct accept_socket_request *req = server_alloc_req( sizeof(*req), 0 );
870
871 req->lhandle = s;
872 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
873 req->inherit = TRUE;
874 sock_server_call( REQ_ACCEPT_SOCKET );
875 as = req->handle;
876 }
877 SERVER_END_REQ;
Stephane Lussierec6f37b2000-09-01 01:21:42 +0000878 if( ((int)as) >= 0 )
Ove Kaavenf45608f1999-10-23 16:53:34 +0000879 {
Alexandre Julliarde0842da2000-03-28 13:19:21 +0000880 unsigned omask = _get_sock_mask( s );
Ove Kaavencb98a6e2000-03-26 18:21:16 +0000881 int fd = _get_sock_fd( as );
Ove Kaavenf45608f1999-10-23 16:53:34 +0000882 if( getpeername(fd, addr, addrlen32) != -1 )
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000883 {
Pavel Roskin94d99641998-12-26 11:52:51 +0000884#ifdef HAVE_IPX
Stephen Langasek12392cd1998-11-14 16:47:09 +0000885 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
886 addr = (struct sockaddr *)
887 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
888 memcpy(addr, addr2,
889 addrlen32 ? *addrlen32 : sizeof(*addr2));
Stephen Langasekdc163421998-11-08 15:42:40 +0000890 addr2->sipx_family = WS_AF_IPX;
891 addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
892 addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
893 memcpy(addr2->sipx_node,
894 ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
895 free(addr);
896 }
897#endif
Ove Kaavenf45608f1999-10-23 16:53:34 +0000898 } else SetLastError(wsaErrno());
899 close(fd);
Ove Kaavencb98a6e2000-03-26 18:21:16 +0000900 if (omask & WS_FD_SERVEVENT)
901 WSOCK32_async_accept(pwsi, s, as);
902 return as;
Ove Kaavenf45608f1999-10-23 16:53:34 +0000903 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000904 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000905 return INVALID_SOCKET;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000906}
907
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000908/***********************************************************************
909 * accept() (WINSOCK.1)
910 */
911SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
912 INT16* addrlen16 )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000913{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000914 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
Patrik Stridvallfcfacb92000-03-24 20:46:04 +0000915 SOCKET retSocket = WSOCK32_accept( s, addr, &addrlen32 );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000916 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000917 return (SOCKET16)retSocket;
918}
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000919
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000920/***********************************************************************
921 * bind() (WSOCK32.2)
922 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +0000923INT WINAPI WSOCK32_bind(SOCKET s, struct sockaddr *name, INT namelen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000924{
Ove Kaavenf45608f1999-10-23 16:53:34 +0000925 LPWSINFO pwsi = WINSOCK_GetIData();
Pavel Roskin94d99641998-12-26 11:52:51 +0000926#ifdef HAVE_IPX
Stephen Langasekdc163421998-11-08 15:42:40 +0000927 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
928#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000929
Alexandre Julliard61fece01999-06-26 19:09:08 +0000930 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000931 (unsigned)pwsi, s, (int) name, namelen);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000932#if DEBUG_SOCKADDR
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000933 dump_sockaddr(name);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000934#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000935
Ove Kaavenf45608f1999-10-23 16:53:34 +0000936 if ( _check_ws(pwsi, s) )
Jesper Skov5c3e4571998-11-01 19:27:22 +0000937 {
Ove Kaavenf45608f1999-10-23 16:53:34 +0000938 int fd = _get_sock_fd(s);
Stephen Langasek12392cd1998-11-14 16:47:09 +0000939 /* FIXME: what family does this really map to on the Unix side? */
940 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
941 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
Pavel Roskin94d99641998-12-26 11:52:51 +0000942#ifdef HAVE_IPX
Stephen Langasek12392cd1998-11-14 16:47:09 +0000943 else if (name &&
944 ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
Stephen Langasekdc163421998-11-08 15:42:40 +0000945 {
946 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
947 memset(name, '\0', sizeof(struct sockaddr_ipx));
948 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
949 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
950 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
951 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
952 name2->sipx_node, IPX_NODE_LEN);
953 namelen = sizeof(struct sockaddr_ipx);
954 }
955#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000956 if ( namelen >= sizeof(*name) )
Jesper Skov5c3e4571998-11-01 19:27:22 +0000957 {
Stephen Langasek12392cd1998-11-14 16:47:09 +0000958 if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET
Pavel Roskin94d99641998-12-26 11:52:51 +0000959#ifdef HAVE_IPX
Stephen Langasekdc163421998-11-08 15:42:40 +0000960 || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX
961#endif
Stephen Langasek12392cd1998-11-14 16:47:09 +0000962 ))
Jesper Skov5c3e4571998-11-01 19:27:22 +0000963 {
Ove Kaavenf45608f1999-10-23 16:53:34 +0000964 if ( bind(fd, name, namelen) < 0 )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000965 {
966 int loc_errno = errno;
Alexandre Julliard61fece01999-06-26 19:09:08 +0000967 WARN("\tfailure - errno = %i\n", errno);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000968 errno = loc_errno;
969 switch(errno)
970 {
Marcus Meissner01f3dc31999-05-12 10:34:03 +0000971 case EBADF: SetLastError(WSAENOTSOCK); break;
972 case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break;
973 default: SetLastError(wsaErrno());break;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000974 }
975 }
Stephen Langasek12392cd1998-11-14 16:47:09 +0000976 else {
Pavel Roskin94d99641998-12-26 11:52:51 +0000977#ifdef HAVE_IPX
Stephen Langasek12392cd1998-11-14 16:47:09 +0000978 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
979 free(name);
980#endif
Ove Kaavenf45608f1999-10-23 16:53:34 +0000981 close(fd);
Stephen Langasek12392cd1998-11-14 16:47:09 +0000982 return 0; /* success */
983 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +0000984 } else SetLastError(WSAEAFNOSUPPORT);
985 } else SetLastError(WSAEFAULT);
Pavel Roskin94d99641998-12-26 11:52:51 +0000986#ifdef HAVE_IPX
Stephen Langasek12392cd1998-11-14 16:47:09 +0000987 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
988 free(name);
989#endif
Ove Kaavenf45608f1999-10-23 16:53:34 +0000990 close(fd);
Jesper Skov5c3e4571998-11-01 19:27:22 +0000991 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000992 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000993}
994
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000995/***********************************************************************
996 * bind() (WINSOCK.2)
997 */
998INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000999{
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001000 return (INT16)WSOCK32_bind( s, name, namelen );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001001}
1002
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001003/***********************************************************************
1004 * closesocket() (WSOCK32.3)
1005 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001006INT WINAPI WSOCK32_closesocket(SOCKET s)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001007{
Ove Kaavenf45608f1999-10-23 16:53:34 +00001008 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001009
Alexandre Julliard61fece01999-06-26 19:09:08 +00001010 TRACE("(%08x): socket %08x\n", (unsigned)pwsi, s);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001011
Ove Kaavenf45608f1999-10-23 16:53:34 +00001012 if( _check_ws(pwsi, s) )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001013 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001014 if( CloseHandle(s) )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001015 return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001016 }
1017 return SOCKET_ERROR;
1018}
1019
1020/***********************************************************************
1021 * closesocket() (WINSOCK.3)
1022 */
1023INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
1024{
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001025 return (INT16)WSOCK32_closesocket(s);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001026}
1027
1028/***********************************************************************
1029 * connect() (WSOCK32.4)
1030 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001031INT WINAPI WSOCK32_connect(SOCKET s, struct sockaddr *name, INT namelen)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001032{
Ove Kaavenf45608f1999-10-23 16:53:34 +00001033 LPWSINFO pwsi = WINSOCK_GetIData();
Pavel Roskin94d99641998-12-26 11:52:51 +00001034#ifdef HAVE_IPX
Stephen Langasekdc163421998-11-08 15:42:40 +00001035 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1036#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001037
Alexandre Julliard61fece01999-06-26 19:09:08 +00001038 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001039 (unsigned)pwsi, s, (int) name, namelen);
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001040#if DEBUG_SOCKADDR
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001041 dump_sockaddr(name);
1042#endif
1043
Ove Kaavenf45608f1999-10-23 16:53:34 +00001044 if( _check_ws(pwsi, s) )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001045 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001046 int fd = _get_sock_fd(s);
Stephen Langasek12392cd1998-11-14 16:47:09 +00001047 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
1048 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
Pavel Roskin94d99641998-12-26 11:52:51 +00001049#ifdef HAVE_IPX
Stephen Langasek12392cd1998-11-14 16:47:09 +00001050 else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
1051 {
Stephen Langasekdc163421998-11-08 15:42:40 +00001052 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1053 memset(name, '\0', sizeof(struct sockaddr_ipx));
1054 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
1055 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
1056 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
1057 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
1058 name2->sipx_node, IPX_NODE_LEN);
1059 namelen = sizeof(struct sockaddr_ipx);
1060 }
1061#endif
Ove Kaavenf45608f1999-10-23 16:53:34 +00001062 if (connect(fd, name, namelen) == 0) {
1063 close(fd);
1064 goto connect_success;
1065 }
1066 if (errno == EINPROGRESS)
1067 {
1068 /* tell wineserver that a connection is in progress */
1069 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1070 WS_FD_CONNECT|WS_FD_READ|WS_FD_WRITE,
1071 WS_FD_CONNECTED|WS_FD_LISTENING);
1072 if (_is_blocking(s))
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001073 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001074 int result;
1075 /* block here */
1076 do_block(fd, 6);
1077 _sync_sock_state(s); /* let wineserver notice connection */
1078 /* retrieve any error codes from it */
1079 result = _get_sock_error(s, FD_CONNECT_BIT);
1080 if (result)
1081 SetLastError(result);
1082 else {
1083 close(fd);
1084 goto connect_success;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001085 }
1086 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00001087 else SetLastError(WSAEWOULDBLOCK);
1088 close(fd);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001089 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00001090 else
1091 {
1092 SetLastError(wsaErrno());
1093 close(fd);
1094 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001095 }
Pavel Roskin94d99641998-12-26 11:52:51 +00001096#ifdef HAVE_IPX
Stephen Langasek12392cd1998-11-14 16:47:09 +00001097 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
Stephen Langasekdc163421998-11-08 15:42:40 +00001098 free(name);
1099#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001100 return SOCKET_ERROR;
Ove Kaavenf45608f1999-10-23 16:53:34 +00001101connect_success:
1102#ifdef HAVE_IPX
1103 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1104 free(name);
1105#endif
1106 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1107 WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE,
1108 WS_FD_CONNECT|WS_FD_LISTENING);
1109 return 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001110}
1111
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001112/***********************************************************************
1113 * connect() (WINSOCK.4)
1114 */
1115INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001116{
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001117 return (INT16)WSOCK32_connect( s, name, namelen );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001118}
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001119
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001120/***********************************************************************
1121 * getpeername() (WSOCK32.5)
1122 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001123INT WINAPI WSOCK32_getpeername(SOCKET s, struct sockaddr *name,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001124 INT *namelen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001125{
Ove Kaavenf45608f1999-10-23 16:53:34 +00001126 LPWSINFO pwsi = WINSOCK_GetIData();
Pavel Roskin94d99641998-12-26 11:52:51 +00001127#ifdef HAVE_IPX
Stephen Langasekdc163421998-11-08 15:42:40 +00001128 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1129#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001130
Alexandre Julliard61fece01999-06-26 19:09:08 +00001131 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001132 (unsigned)pwsi, s, (int) name, *namelen);
Ove Kaavenf45608f1999-10-23 16:53:34 +00001133 if( _check_ws(pwsi, s) )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001134 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001135 int fd = _get_sock_fd(s);
1136 if (getpeername(fd, name, namelen) == 0) {
Pavel Roskin94d99641998-12-26 11:52:51 +00001137#ifdef HAVE_IPX
Stephen Langasekdc163421998-11-08 15:42:40 +00001138 if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
Stephen Langasek12392cd1998-11-14 16:47:09 +00001139 name = (struct sockaddr *)
1140 malloc(namelen ? *namelen : sizeof(*name2));
1141 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
Stephen Langasekdc163421998-11-08 15:42:40 +00001142 name2->sipx_family = WS_AF_IPX;
1143 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1144 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1145 memcpy(name2->sipx_node,
1146 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1147 free(name);
1148 }
1149#endif
Ove Kaavenf45608f1999-10-23 16:53:34 +00001150 close(fd);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001151 return 0;
Stephen Langasekdc163421998-11-08 15:42:40 +00001152 }
David Luyer63682fd1999-09-22 15:09:22 +00001153 SetLastError(wsaErrno());
Ove Kaavenf45608f1999-10-23 16:53:34 +00001154 close(fd);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001155 }
1156 return SOCKET_ERROR;
1157}
1158
1159/***********************************************************************
1160 * getpeername() (WINSOCK.5)
1161 */
1162INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
1163 INT16 *namelen16)
1164{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001165 INT namelen32 = *namelen16;
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001166 INT retVal = WSOCK32_getpeername( s, name, &namelen32 );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001167
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001168#if DEBUG_SOCKADDR
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001169 dump_sockaddr(name);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001170#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001171
1172 *namelen16 = namelen32;
1173 return (INT16)retVal;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001174}
1175
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001176/***********************************************************************
1177 * getsockname() (WSOCK32.6)
1178 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001179INT WINAPI WSOCK32_getsockname(SOCKET s, struct sockaddr *name,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001180 INT *namelen)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001181{
Ove Kaavenf45608f1999-10-23 16:53:34 +00001182 LPWSINFO pwsi = WINSOCK_GetIData();
Pavel Roskin94d99641998-12-26 11:52:51 +00001183#ifdef HAVE_IPX
Stephen Langasekdc163421998-11-08 15:42:40 +00001184 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1185#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001186
Alexandre Julliard61fece01999-06-26 19:09:08 +00001187 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001188 (unsigned)pwsi, s, (int) name, (int) *namelen);
Ove Kaavenf45608f1999-10-23 16:53:34 +00001189 if( _check_ws(pwsi, s) )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001190 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001191 int fd = _get_sock_fd(s);
1192 if (getsockname(fd, name, namelen) == 0) {
Pavel Roskin94d99641998-12-26 11:52:51 +00001193#ifdef HAVE_IPX
Stephen Langasekdc163421998-11-08 15:42:40 +00001194 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) {
Stephen Langasek12392cd1998-11-14 16:47:09 +00001195 name = (struct sockaddr *)
1196 malloc(namelen ? *namelen : sizeof(*name2));
1197 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
Stephen Langasekdc163421998-11-08 15:42:40 +00001198 name2->sipx_family = WS_AF_IPX;
1199 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1200 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1201 memcpy(name2->sipx_node,
1202 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1203 free(name);
1204 }
1205#endif
Ove Kaavenf45608f1999-10-23 16:53:34 +00001206 close(fd);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001207 return 0;
Stephen Langasekdc163421998-11-08 15:42:40 +00001208 }
David Luyer63682fd1999-09-22 15:09:22 +00001209 SetLastError(wsaErrno());
Ove Kaavenf45608f1999-10-23 16:53:34 +00001210 close(fd);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001211 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001212 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001213}
1214
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001215/***********************************************************************
1216 * getsockname() (WINSOCK.6)
1217 */
1218INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
1219 INT16 *namelen16)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001220{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001221 INT retVal;
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001222
1223 if( namelen16 )
1224 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001225 INT namelen32 = *namelen16;
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001226 retVal = WSOCK32_getsockname( s, name, &namelen32 );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001227 *namelen16 = namelen32;
1228
1229#if DEBUG_SOCKADDR
1230 dump_sockaddr(name);
1231#endif
1232
1233 }
1234 else retVal = SOCKET_ERROR;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001235 return (INT16)retVal;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001236}
1237
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001238
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001239/***********************************************************************
1240 * getsockopt() (WSOCK32.7)
1241 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001242INT WINAPI WSOCK32_getsockopt(SOCKET s, INT level,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001243 INT optname, char *optval, INT *optlen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001244{
Ove Kaavenf45608f1999-10-23 16:53:34 +00001245 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001246
Rein Klazes81f77712000-10-13 17:05:35 +00001247 TRACE("(%08x): socket: %04x, opt 0x%x, ptr %8x, len %d\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001248 (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
Ove Kaavenf45608f1999-10-23 16:53:34 +00001249 if( _check_ws(pwsi, s) )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001250 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001251 int fd = _get_sock_fd(s);
John Gilmore5180d562000-09-16 20:51:40 +00001252 if (!convert_sockopt(&level, &optname)) {
1253 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1254 } else {
1255 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1256 {
1257 close(fd);
1258 return 0;
1259 }
1260 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
Ove Kaavenf45608f1999-10-23 16:53:34 +00001261 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00001262 close(fd);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001263 }
1264 return SOCKET_ERROR;
1265}
1266
1267/***********************************************************************
1268 * getsockopt() (WINSOCK.7)
1269 */
1270INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1271 INT16 optname, char *optval, INT16 *optlen)
1272{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001273 INT optlen32;
1274 INT *p = &optlen32;
1275 INT retVal;
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001276 if( optlen ) optlen32 = *optlen; else p = NULL;
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001277 retVal = WSOCK32_getsockopt( s, (UINT16)level, optname, optval, p );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001278 if( optlen ) *optlen = optlen32;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001279 return (INT16)retVal;
1280}
1281
1282/***********************************************************************
1283 * htonl() (WINSOCK.8)(WSOCK32.8)
1284 */
1285u_long WINAPI WINSOCK_htonl(u_long hostlong) { return( htonl(hostlong) ); }
1286/***********************************************************************
1287 * htons() (WINSOCK.9)(WSOCK32.9)
1288 */
1289u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
1290/***********************************************************************
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001291 * inet_addr() (WINSOCK.10)(WSOCK32.10)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001292 */
1293u_long WINAPI WINSOCK_inet_addr(char *cp) { return( inet_addr(cp) ); }
1294/***********************************************************************
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001295 * ntohl() (WINSOCK.14)(WSOCK32.14)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001296 */
1297u_long WINAPI WINSOCK_ntohl(u_long netlong) { return( ntohl(netlong) ); }
1298/***********************************************************************
1299 * ntohs() (WINSOCK.15)(WSOCK32.15)
1300 */
1301u_short WINAPI WINSOCK_ntohs(u_short netshort) { return( ntohs(netshort) ); }
1302
1303/***********************************************************************
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001304 * inet_ntoa() (WINSOCK.11)(WSOCK32.11)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001305 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001306char* WINAPI WSOCK32_inet_ntoa(struct in_addr in)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001307{
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001308 /* use "buffer for dummies" here because some applications have
1309 * propensity to decode addresses in ws_hostent structure without
1310 * saving them first...
1311 */
1312
Ove Kaavenf45608f1999-10-23 16:53:34 +00001313 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001314
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001315 if( pwsi )
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001316 {
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001317 char* s = inet_ntoa(in);
1318 if( s )
1319 {
Francois Gougetbaa9bf91999-12-27 05:24:06 +00001320 if( pwsi->dbuffer == NULL ) {
1321 /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1322 if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(16)) == NULL )
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001323 {
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001324 SetLastError(WSAENOBUFS);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001325 return NULL;
1326 }
Francois Gougetbaa9bf91999-12-27 05:24:06 +00001327 }
1328 strcpy(pwsi->dbuffer, s);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001329 return pwsi->dbuffer;
1330 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001331 SetLastError(wsaErrno());
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001332 }
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001333 return NULL;
1334}
1335
1336SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1337{
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001338 char* retVal = WSOCK32_inet_ntoa(in);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001339 return retVal ? SEGPTR_GET(retVal) : (SEGPTR)NULL;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001340}
1341
James Hathewayc9d25822000-07-23 19:28:24 +00001342
1343/**********************************************************************
1344 * WSAIoctl (WS2_32)
1345 *
1346 *
1347 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1348 */
1349INT WINAPI WSAIoctl (SOCKET s,
1350 DWORD dwIoControlCode,
1351 LPVOID lpvInBuffer,
1352 DWORD cbInBuffer,
1353 LPVOID lpbOutBuffer,
1354 DWORD cbOutBuffer,
1355 LPDWORD lpcbBytesReturned,
1356 LPWSAOVERLAPPED lpOverlapped,
1357 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1358{
1359 LPWSINFO pwsi = WINSOCK_GetIData();
1360
1361 if( _check_ws(pwsi, s) )
1362 {
1363 int fd = _get_sock_fd(s);
1364
1365 switch( dwIoControlCode )
1366 {
1367 case SIO_GET_INTERFACE_LIST:
1368 {
1369 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1370 int i, numInt;
1371 struct ifreq ifInfo;
1372 char ifName[512];
1373
1374
1375 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1376
1377 numInt = WSAIOCTL_GetInterfaceCount();
1378 if (numInt < 0)
1379 {
1380 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1381 close(fd);
1382 WSASetLastError(WSAEINVAL);
1383 return (SOCKET_ERROR);
1384 }
1385
1386 for (i=0; i<numInt; i++)
1387 {
1388 if (!WSAIOCTL_GetInterfaceName(i, ifName))
1389 {
1390 ERR ("Error parsing /proc filesystem!\n");
1391 close(fd);
1392 WSASetLastError(WSAEINVAL);
1393 return (SOCKET_ERROR);
1394 }
1395
1396 ifInfo.ifr_addr.sa_family = AF_INET;
1397
1398 /* IP Address */
1399 strcpy (ifInfo.ifr_name, ifName);
1400 if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
1401 {
1402 ERR ("Error obtaining IP address\n");
1403 close(fd);
1404 WSASetLastError(WSAEINVAL);
1405 return (SOCKET_ERROR);
1406 }
1407 else
1408 {
1409 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1410
1411 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1412 intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1413 intArray->iiAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1414 }
1415
1416 /* Broadcast Address */
1417 strcpy (ifInfo.ifr_name, ifName);
1418 if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1419 {
1420 ERR ("Error obtaining Broadcast IP address\n");
1421 close(fd);
1422 WSASetLastError(WSAEINVAL);
1423 return (SOCKET_ERROR);
1424 }
1425 else
1426 {
1427 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
1428
1429 intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
1430 intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
1431 intArray->iiBroadcastAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1432 }
1433
1434 /* Subnet Mask */
1435 strcpy (ifInfo.ifr_name, ifName);
1436 if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
1437 {
1438 ERR ("Error obtaining Subnet IP address\n");
1439 close(fd);
1440 WSASetLastError(WSAEINVAL);
1441 return (SOCKET_ERROR);
1442 }
1443 else
1444 {
James Hathewaybf3e2e9f2000-07-25 17:45:50 +00001445 /* Trying to avoid some compile problems across platforms.
1446 (Linux, FreeBSD, Solaris...) */
1447 #ifndef ifr_netmask
1448 #ifndef ifr_addr
1449 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1450 intArray->iiNetmask.AddressIn.sin_port = 0;
1451 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = 0;
1452 ERR ("Unable to determine Netmask on your platform!\n");
1453 #else
1454 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
James Hathewayc9d25822000-07-23 19:28:24 +00001455
James Hathewaybf3e2e9f2000-07-25 17:45:50 +00001456 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1457 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1458 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1459 #endif
1460 #else
1461 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
1462
1463 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1464 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1465 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1466 #endif
James Hathewayc9d25822000-07-23 19:28:24 +00001467 }
1468
1469 /* Socket Status Flags */
1470 strcpy(ifInfo.ifr_name, ifName);
1471 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1472 {
1473 ERR ("Error obtaining status flags for socket!\n");
1474 close(fd);
1475 WSASetLastError(WSAEINVAL);
1476 return (SOCKET_ERROR);
1477 }
1478 else
1479 {
1480 /* FIXME - Is this the right flag to use? */
1481 intArray->iiFlags = ifInfo.ifr_flags;
1482 }
1483 intArray++; /* Prepare for another interface */
1484 }
1485
1486 /* Calculate the size of the array being returned */
1487 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1488 break;
1489 }
1490
1491 default:
1492 {
1493 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1494 close(fd);
1495 WSASetLastError(WSAEOPNOTSUPP);
1496 return (SOCKET_ERROR);
1497 }
1498 }
1499
1500 /* Function executed with no errors */
1501 close(fd);
1502 return (0);
1503 }
1504 else
1505 {
1506 WSASetLastError(WSAENOTSOCK);
1507 return (SOCKET_ERROR);
1508 }
1509}
1510
1511
1512/*
1513 Helper function for WSAIoctl - Get count of the number of interfaces
1514 by parsing /proc filesystem.
1515*/
1516int WSAIOCTL_GetInterfaceCount(void)
1517{
1518 FILE *procfs;
1519 char buf[512]; /* Size doesn't matter, something big */
1520 int intcnt=0;
1521
1522
1523 /* Open /proc filesystem file for network devices */
1524 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1525 if (!procfs)
1526 {
1527 /* If we can't open the file, return an error */
1528 return (-1);
1529 }
1530
1531 /* Omit first two lines, they are only headers */
1532 fgets(buf, sizeof buf, procfs);
1533 fgets(buf, sizeof buf, procfs);
1534
1535 while (fgets(buf, sizeof buf, procfs))
1536 {
1537 /* Each line in the file represents a network interface */
1538 intcnt++;
1539 }
1540
1541 fclose(procfs);
1542 return(intcnt);
1543}
1544
1545
1546/*
1547 Helper function for WSAIoctl - Get name of device from interface number
1548 by parsing /proc filesystem.
1549*/
1550int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
1551{
1552 FILE *procfs;
1553 char buf[512]; /* Size doesn't matter, something big */
1554 int i;
1555
1556 /* Open /proc filesystem file for network devices */
1557 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1558 if (!procfs)
1559 {
1560 /* If we can't open the file, return an error */
1561 return (-1);
1562 }
1563
1564 /* Omit first two lines, they are only headers */
1565 fgets(buf, sizeof(buf), procfs);
1566 fgets(buf, sizeof(buf), procfs);
1567
1568 for (i=0; i<intNumber; i++)
1569 {
1570 /* Skip the lines that don't interest us. */
1571 fgets(buf, sizeof(buf), procfs);
1572 }
1573 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
1574
1575
1576 /* Parse out the line, grabbing only the name of the device
1577 to the intName variable
1578
1579 The Line comes in like this: (we only care about the device name)
1580 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
1581 */
1582 i=0;
1583 while (isspace(buf[i])) /* Skip initial space(s) */
1584 {
1585 i++;
1586 }
1587
1588 while (buf[i])
1589 {
1590 if (isspace(buf[i]))
1591 {
1592 break;
1593 }
1594
1595 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
1596 {
1597 /* This interface could be an alias... */
1598 int hold = i;
1599 char *dotname = intName;
1600 *intName++ = buf[i++];
1601
1602 while (isdigit(buf[i]))
1603 {
1604 *intName++ = buf[i++];
1605 }
1606
1607 if (buf[i] != ':')
1608 {
1609 /* ... It wasn't, so back up */
1610 i = hold;
1611 intName = dotname;
1612 }
1613
1614 if (buf[i] == '\0')
1615 {
1616 fclose(procfs);
1617 return(FALSE);
1618 }
1619
1620 i++;
1621 break;
1622 }
1623
1624 *intName++ = buf[i++];
1625 }
1626 *intName++ = '\0';
1627
1628 fclose(procfs);
1629 return(TRUE);
1630 }
1631
1632
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001633/***********************************************************************
1634 * ioctlsocket() (WSOCK32.12)
1635 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001636INT WINAPI WSOCK32_ioctlsocket(SOCKET s, LONG cmd, ULONG *argp)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001637{
Ove Kaavenf45608f1999-10-23 16:53:34 +00001638 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001639
Patrik Stridvallb8684a21999-07-31 17:32:05 +00001640 TRACE("(%08x): socket %04x, cmd %08lx, ptr %8x\n",
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001641 (unsigned)pwsi, s, cmd, (unsigned) argp);
Ove Kaavenf45608f1999-10-23 16:53:34 +00001642 if( _check_ws(pwsi, s) )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001643 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001644 int fd = _get_sock_fd(s);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001645 long newcmd = cmd;
1646
1647 switch( cmd )
1648 {
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001649 case WS_FIONREAD:
1650 newcmd=FIONREAD;
1651 break;
1652
1653 case WS_FIONBIO:
1654 newcmd=FIONBIO;
Ove Kaavenf45608f1999-10-23 16:53:34 +00001655 if( _get_sock_mask(s) )
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001656 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001657 /* AsyncSelect()'ed sockets are always nonblocking */
Ove Kaavend0c3e192000-02-14 19:50:57 +00001658 if (*argp) {
1659 close(fd);
1660 return 0;
1661 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001662 SetLastError(WSAEINVAL);
Ove Kaavenf45608f1999-10-23 16:53:34 +00001663 close(fd);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001664 return SOCKET_ERROR;
1665 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00001666 close(fd);
1667 if (*argp)
1668 _enable_event(s, 0, WS_FD_NONBLOCKING, 0);
1669 else
1670 _enable_event(s, 0, 0, WS_FD_NONBLOCKING);
1671 return 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001672
1673 case WS_SIOCATMARK:
1674 newcmd=SIOCATMARK;
1675 break;
1676
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001677 case WS_IOW('f',125,u_long):
Alexandre Julliard61fece01999-06-26 19:09:08 +00001678 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001679 SetLastError(WSAEINVAL);
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001680 return SOCKET_ERROR;
1681
1682 default:
1683 /* Netscape tries hard to use bogus ioctl 0x667e */
Patrik Stridvallb8684a21999-07-31 17:32:05 +00001684 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001685 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00001686 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1687 {
1688 close(fd);
1689 return 0;
1690 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001691 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
Ove Kaavenf45608f1999-10-23 16:53:34 +00001692 close(fd);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001693 }
1694 return SOCKET_ERROR;
1695}
1696
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001697/***********************************************************************
1698 * ioctlsocket() (WINSOCK.12)
1699 */
Patrik Stridvallb8684a21999-07-31 17:32:05 +00001700INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001701{
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001702 return (INT16)WSOCK32_ioctlsocket( s, cmd, argp );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001703}
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001704
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001705
1706/***********************************************************************
1707 * listen() (WSOCK32.13)
1708 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001709INT WINAPI WSOCK32_listen(SOCKET s, INT backlog)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001710{
Ove Kaavenf45608f1999-10-23 16:53:34 +00001711 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001712
Alexandre Julliard61fece01999-06-26 19:09:08 +00001713 TRACE("(%08x): socket %04x, backlog %d\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001714 (unsigned)pwsi, s, backlog);
Ove Kaavenf45608f1999-10-23 16:53:34 +00001715 if( _check_ws(pwsi, s) )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001716 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001717 int fd = _get_sock_fd(s);
1718 if (listen(fd, backlog) == 0)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001719 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001720 close(fd);
1721 _enable_event(s, FD_ACCEPT,
1722 WS_FD_LISTENING,
1723 WS_FD_CONNECT|WS_FD_CONNECTED);
Alexandre Julliard17216f51997-10-12 16:30:17 +00001724 return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001725 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001726 SetLastError(wsaErrno());
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001727 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001728 else SetLastError(WSAENOTSOCK);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001729 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001730}
1731
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001732/***********************************************************************
1733 * listen() (WINSOCK.13)
1734 */
1735INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001736{
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001737 return (INT16)WSOCK32_listen( s, backlog );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001738}
1739
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001740
1741/***********************************************************************
1742 * recv() (WSOCK32.16)
1743 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001744INT WINAPI WSOCK32_recv(SOCKET s, char *buf, INT len, INT flags)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001745{
Ove Kaavenf45608f1999-10-23 16:53:34 +00001746 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001747
Alexandre Julliard61fece01999-06-26 19:09:08 +00001748 TRACE("(%08x): socket %04x, buf %8x, len %d, "
Alexandre Julliarda11d7b11998-03-01 20:05:02 +00001749 "flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1750 len, flags);
Ove Kaavenf45608f1999-10-23 16:53:34 +00001751 if( _check_ws(pwsi, s) )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001752 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001753 int fd = _get_sock_fd(s);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001754 INT length;
Ove Kaavenf45608f1999-10-23 16:53:34 +00001755
1756 if (_is_blocking(s))
1757 {
1758 /* block here */
1759 /* FIXME: OOB and exceptfds? */
1760 do_block(fd, 1);
1761 }
1762 if ((length = recv(fd, buf, len, flags)) >= 0)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001763 {
Alexandre Julliard61fece01999-06-26 19:09:08 +00001764 TRACE(" -> %i bytes\n", length);
Alexandre Julliardb1bac321996-12-15 19:45:59 +00001765
Ove Kaavenf45608f1999-10-23 16:53:34 +00001766 close(fd);
1767 _enable_event(s, FD_READ, 0, 0);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001768 return length;
1769 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001770 SetLastError(wsaErrno());
Ove Kaavenf45608f1999-10-23 16:53:34 +00001771 close(fd);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001772 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001773 else SetLastError(WSAENOTSOCK);
Alexandre Julliard61fece01999-06-26 19:09:08 +00001774 WARN(" -> ERROR\n");
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001775 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001776}
1777
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001778/***********************************************************************
1779 * recv() (WINSOCK.16)
1780 */
1781INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1782{
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001783 return (INT16)WSOCK32_recv( s, buf, len, flags );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001784}
1785
1786
1787/***********************************************************************
1788 * recvfrom() (WSOCK32.17)
1789 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001790INT WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, INT flags,
Alexandre Julliarda3960291999-02-26 11:11:13 +00001791 struct sockaddr *from, INT *fromlen32)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001792{
Ove Kaavenf45608f1999-10-23 16:53:34 +00001793 LPWSINFO pwsi = WINSOCK_GetIData();
Pavel Roskin94d99641998-12-26 11:52:51 +00001794#ifdef HAVE_IPX
Stephen Langasekdc163421998-11-08 15:42:40 +00001795 struct ws_sockaddr_ipx* from2 = (struct ws_sockaddr_ipx *)from;
1796#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001797
Alexandre Julliard61fece01999-06-26 19:09:08 +00001798 TRACE("(%08x): socket %04x, ptr %08x, "
Alexandre Julliarda11d7b11998-03-01 20:05:02 +00001799 "len %d, flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1800 len, flags);
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001801#if DEBUG_SOCKADDR
1802 if( from ) dump_sockaddr(from);
Alexandre Julliard61fece01999-06-26 19:09:08 +00001803 else DPRINTF("from = NULL\n");
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001804#endif
1805
Ove Kaavenf45608f1999-10-23 16:53:34 +00001806 if( _check_ws(pwsi, s) )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001807 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001808 int fd = _get_sock_fd(s);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001809 int length;
1810
Ove Kaavenf45608f1999-10-23 16:53:34 +00001811 if (_is_blocking(s))
1812 {
1813 /* block here */
1814 /* FIXME: OOB and exceptfds */
1815 do_block(fd, 1);
1816 }
1817 if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001818 {
Alexandre Julliard61fece01999-06-26 19:09:08 +00001819 TRACE(" -> %i bytes\n", length);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001820
Pavel Roskin94d99641998-12-26 11:52:51 +00001821#ifdef HAVE_IPX
Stephen Langasek12392cd1998-11-14 16:47:09 +00001822 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1823 from = (struct sockaddr *)
1824 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1825 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
Stephen Langasekdc163421998-11-08 15:42:40 +00001826 from2->sipx_family = WS_AF_IPX;
1827 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1828 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1829 memcpy(from2->sipx_node,
1830 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1831 free(from);
1832 }
1833#endif
Ove Kaavenf45608f1999-10-23 16:53:34 +00001834 close(fd);
1835 _enable_event(s, FD_READ, 0, 0);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001836 return (INT16)length;
1837 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001838 SetLastError(wsaErrno());
Ove Kaavenf45608f1999-10-23 16:53:34 +00001839 close(fd);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001840 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001841 else SetLastError(WSAENOTSOCK);
Alexandre Julliard61fece01999-06-26 19:09:08 +00001842 WARN(" -> ERROR\n");
Pavel Roskin94d99641998-12-26 11:52:51 +00001843#ifdef HAVE_IPX
Stephen Langasek12392cd1998-11-14 16:47:09 +00001844 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1845 from = (struct sockaddr *)
1846 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1847 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
Stephen Langasekdc163421998-11-08 15:42:40 +00001848 from2->sipx_family = WS_AF_IPX;
1849 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1850 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1851 memcpy(from2->sipx_node,
1852 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1853 free(from);
1854 }
1855#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001856 return SOCKET_ERROR;
1857}
1858
1859/***********************************************************************
1860 * recvfrom() (WINSOCK.17)
1861 */
1862INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1863 struct sockaddr *from, INT16 *fromlen16)
1864{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001865 INT fromlen32;
1866 INT *p = &fromlen32;
1867 INT retVal;
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001868
1869 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001870 retVal = WSOCK32_recvfrom( s, buf, len, flags, from, p );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001871 if( fromlen16 ) *fromlen16 = fromlen32;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001872 return (INT16)retVal;
1873}
1874
1875/***********************************************************************
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001876 * select() (WINSOCK.18)(WSOCK32.18)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001877 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001878static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001879 struct timeval *timeout )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001880{
Ove Kaavenf45608f1999-10-23 16:53:34 +00001881 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001882
Alexandre Julliard61fece01999-06-26 19:09:08 +00001883 TRACE("(%08x): read %8x, write %8x, excp %8x\n",
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001884 (unsigned) pwsi, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001885
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001886 if( pwsi )
1887 {
1888 int highfd = 0;
1889 fd_set readfds, writefds, exceptfds;
1890 fd_set *p_read, *p_write, *p_except;
Ove Kaavenf45608f1999-10-23 16:53:34 +00001891 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001892
Ove Kaavenf45608f1999-10-23 16:53:34 +00001893 p_read = fd_set_import(&readfds, pwsi, ws_readfds, &highfd, readfd, b32);
1894 p_write = fd_set_import(&writefds, pwsi, ws_writefds, &highfd, writefd, b32);
1895 p_except = fd_set_import(&exceptfds, pwsi, ws_exceptfds, &highfd, exceptfd, b32);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001896
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001897 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001898 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001899 fd_set_export(pwsi, &readfds, p_except, ws_readfds, readfd, b32);
1900 fd_set_export(pwsi, &writefds, p_except, ws_writefds, writefd, b32);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001901
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001902 if (p_except && ws_exceptfds)
1903 {
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001904#define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1905#define wsfds32 ((ws_fd_set32*)ws_exceptfds)
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001906 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001907
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001908 for (i = j = 0; i < count; i++)
1909 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001910 int fd = exceptfd[i];
1911 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001912 {
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001913 if( b32 )
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001914 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001915 else
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001916 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001917 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00001918 if( fd >= 0 ) close(fd);
1919 exceptfd[i] = -1;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001920 }
1921 if( b32 )
1922 wsfds32->fd_count = j;
1923 else
1924 wsfds16->fd_count = j;
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001925#undef wsfds32
1926#undef wsfds16
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001927 }
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001928 return highfd;
1929 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00001930 fd_set_unimport(ws_readfds, readfd, b32);
1931 fd_set_unimport(ws_writefds, writefd, b32);
1932 fd_set_unimport(ws_exceptfds, exceptfd, b32);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001933 if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1934 if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1935 if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1936
1937 if( highfd == 0 ) return 0;
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001938 SetLastError(wsaErrno());
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001939 }
1940 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001941}
1942
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001943INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1944 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1945 struct timeval *timeout)
1946{
1947 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1948}
1949
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001950INT WINAPI WSOCK32_select(INT nfds, ws_fd_set32 *ws_readfds,
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001951 ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001952 struct timeval *timeout)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001953{
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001954 /* struct timeval is the same for both 32- and 16-bit code */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001955 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001956}
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001957
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001958
1959/***********************************************************************
1960 * send() (WSOCK32.19)
1961 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00001962INT WINAPI WSOCK32_send(SOCKET s, char *buf, INT len, INT flags)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001963{
Ove Kaavenf45608f1999-10-23 16:53:34 +00001964 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001965
Alexandre Julliard61fece01999-06-26 19:09:08 +00001966 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00001967 (unsigned)pwsi, s, (unsigned) buf, len, flags);
Ove Kaavenf45608f1999-10-23 16:53:34 +00001968 if( _check_ws(pwsi, s) )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001969 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00001970 int fd = _get_sock_fd(s);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001971 int length;
1972
Ove Kaavenf45608f1999-10-23 16:53:34 +00001973 if (_is_blocking(s))
1974 {
1975 /* block here */
1976 /* FIXME: exceptfds */
1977 do_block(fd, 2);
1978 }
1979 if ((length = send(fd, buf, len, flags)) < 0 )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001980 {
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001981 SetLastError(wsaErrno());
Ove Kaavenf45608f1999-10-23 16:53:34 +00001982 if( GetLastError() == WSAEWOULDBLOCK )
1983 _enable_event(s, FD_WRITE, 0, 0);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001984 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00001985 else
1986 {
1987 close(fd);
1988 return (INT16)length;
1989 }
1990 close(fd);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001991 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00001992 else SetLastError(WSAENOTSOCK);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001993 return SOCKET_ERROR;
1994}
1995
1996/***********************************************************************
1997 * send() (WINSOCK.19)
1998 */
1999INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2000{
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00002001 return WSOCK32_send( s, buf, len, flags );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002002}
2003
2004/***********************************************************************
2005 * sendto() (WSOCK32.20)
2006 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00002007INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags,
Alexandre Julliarda3960291999-02-26 11:11:13 +00002008 struct sockaddr *to, INT tolen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002009{
Ove Kaavenf45608f1999-10-23 16:53:34 +00002010 LPWSINFO pwsi = WINSOCK_GetIData();
Pavel Roskin94d99641998-12-26 11:52:51 +00002011#ifdef HAVE_IPX
Stephen Langasekdc163421998-11-08 15:42:40 +00002012 struct ws_sockaddr_ipx* to2 = (struct ws_sockaddr_ipx *)to;
2013#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002014
Alexandre Julliard61fece01999-06-26 19:09:08 +00002015 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002016 (unsigned)pwsi, s, (unsigned) buf, len, flags);
Ove Kaavenf45608f1999-10-23 16:53:34 +00002017 if( _check_ws(pwsi, s) )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002018 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00002019 int fd = _get_sock_fd(s);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002020 INT length;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002021
Stephen Langasek12392cd1998-11-14 16:47:09 +00002022 if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
2023 ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
Pavel Roskin94d99641998-12-26 11:52:51 +00002024#ifdef HAVE_IPX
Stephen Langasek12392cd1998-11-14 16:47:09 +00002025 else if (to &&
2026 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
2027 {
Stephen Langasekdc163421998-11-08 15:42:40 +00002028 to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
2029 memset(to, '\0', sizeof(struct sockaddr_ipx));
2030 ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
2031 ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
2032 ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
2033 memcpy(((struct sockaddr_ipx *)to)->sipx_node,
2034 to2->sipx_node, IPX_NODE_LEN);
2035 tolen = sizeof(struct sockaddr_ipx);
2036 }
2037#endif
Ove Kaavenf45608f1999-10-23 16:53:34 +00002038 if (_is_blocking(s))
2039 {
2040 /* block here */
2041 /* FIXME: exceptfds */
2042 do_block(fd, 2);
2043 }
2044 if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002045 {
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002046 SetLastError(wsaErrno());
Ove Kaavenf45608f1999-10-23 16:53:34 +00002047 if( GetLastError() == WSAEWOULDBLOCK )
2048 _enable_event(s, FD_WRITE, 0, 0);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002049 }
Stephen Langasekdc163421998-11-08 15:42:40 +00002050 else {
Pavel Roskin94d99641998-12-26 11:52:51 +00002051#ifdef HAVE_IPX
Stephen Langasek12392cd1998-11-14 16:47:09 +00002052 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
Stephen Langasekdc163421998-11-08 15:42:40 +00002053 free(to);
2054 }
2055#endif
Ove Kaavenf45608f1999-10-23 16:53:34 +00002056 close(fd);
2057 return length;
Stephen Langasekdc163421998-11-08 15:42:40 +00002058 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00002059 close(fd);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002060 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002061 else SetLastError(WSAENOTSOCK);
Pavel Roskin94d99641998-12-26 11:52:51 +00002062#ifdef HAVE_IPX
Stephen Langasek12392cd1998-11-14 16:47:09 +00002063 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
Stephen Langasekdc163421998-11-08 15:42:40 +00002064 free(to);
2065 }
2066#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002067 return SOCKET_ERROR;
2068}
2069
2070/***********************************************************************
2071 * sendto() (WINSOCK.20)
2072 */
2073INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2074 struct sockaddr *to, INT16 tolen)
2075{
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00002076 return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002077}
2078
2079/***********************************************************************
2080 * setsockopt() (WSOCK32.21)
2081 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00002082INT WINAPI WSOCK32_setsockopt(SOCKET16 s, INT level, INT optname,
Alexandre Julliarda3960291999-02-26 11:11:13 +00002083 char *optval, INT optlen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002084{
Ove Kaavenf45608f1999-10-23 16:53:34 +00002085 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002086
Rein Klazes81f77712000-10-13 17:05:35 +00002087 TRACE("(%08x): socket %04x, lev %d, opt 0x%x, ptr %08x, len %d\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002088 (unsigned)pwsi, s, level, optname, (int) optval, optlen);
Ove Kaavenf45608f1999-10-23 16:53:34 +00002089 if( _check_ws(pwsi, s) )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002090 {
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00002091 struct linger linger;
Ove Kaavenf45608f1999-10-23 16:53:34 +00002092 int fd = _get_sock_fd(s);
Rein Klazes5d3f7a62000-03-07 12:23:51 +00002093 int woptval;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00002094
Rein Klazes9dd32502000-10-24 21:25:21 +00002095 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
John Gilmore5180d562000-09-16 20:51:40 +00002096 /* This is unique to WinSock and takes special conversion */
Rein Klazes20c68be2000-03-04 19:09:16 +00002097 linger.l_onoff = *((int*)optval) ? 0: 1;
2098 linger.l_linger = 0;
2099 optname=SO_LINGER;
2100 optval = (char*)&linger;
2101 optlen = sizeof(struct linger);
Rein Klazes9dd32502000-10-24 21:25:21 +00002102 level = SOL_SOCKET;
Rein Klazes20c68be2000-03-04 19:09:16 +00002103 }else{
John Gilmore5180d562000-09-16 20:51:40 +00002104 if (!convert_sockopt(&level, &optname)) {
2105 SetLastError(WSAENOPROTOOPT);
2106 close(fd);
2107 return SOCKET_ERROR;
2108 }
Rein Klazes9dd32502000-10-24 21:25:21 +00002109 if (optname == SO_LINGER && optval) {
2110 /* yes, uses unsigned short in both win16/win32 */
2111 linger.l_onoff = ((UINT16*)optval)[0];
2112 linger.l_linger = ((UINT16*)optval)[1];
2113 /* FIXME: what is documented behavior if SO_LINGER optval
2114 is null?? */
2115 optval = (char*)&linger;
2116 optlen = sizeof(struct linger);
2117 } else if (optlen < sizeof(int)){
2118 woptval= *((INT16 *) optval);
2119 optval= (char*) &woptval;
2120 optlen=sizeof(int);
2121 }
John Gilmore5180d562000-09-16 20:51:40 +00002122 }
Rein Klazes81f77712000-10-13 17:05:35 +00002123 if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2124 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2125 close( fd);
2126 return 0;
2127 }
2128
Ove Kaavenf45608f1999-10-23 16:53:34 +00002129 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2130 {
2131 close(fd);
2132 return 0;
2133 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002134 SetLastError(wsaErrno());
Ove Kaavenf45608f1999-10-23 16:53:34 +00002135 close(fd);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002136 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002137 else SetLastError(WSAENOTSOCK);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002138 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002139}
2140
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002141/***********************************************************************
2142 * setsockopt() (WINSOCK.21)
2143 */
2144INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2145 char *optval, INT16 optlen)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002146{
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00002147 if( !optval ) return SOCKET_ERROR;
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00002148 return (INT16)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002149}
2150
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002151
2152/***********************************************************************
2153 * shutdown() (WSOCK32.22)
2154 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00002155INT WINAPI WSOCK32_shutdown(SOCKET s, INT how)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002156{
Ove Kaavenf45608f1999-10-23 16:53:34 +00002157 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002158
Alexandre Julliard61fece01999-06-26 19:09:08 +00002159 TRACE("(%08x): socket %04x, how %i\n",
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002160 (unsigned)pwsi, s, how );
Ove Kaavenf45608f1999-10-23 16:53:34 +00002161 if( _check_ws(pwsi, s) )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002162 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00002163 int fd = _get_sock_fd(s);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002164 switch( how )
2165 {
2166 case 0: /* drop receives */
Ove Kaavenf45608f1999-10-23 16:53:34 +00002167 _enable_event(s, 0, 0, WS_FD_READ);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00002168#ifdef SHUT_RD
2169 how = SHUT_RD;
2170#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002171 break;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002172
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002173 case 1: /* drop sends */
Ove Kaavenf45608f1999-10-23 16:53:34 +00002174 _enable_event(s, 0, 0, WS_FD_WRITE);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00002175#ifdef SHUT_WR
2176 how = SHUT_WR;
2177#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002178 break;
2179
2180 case 2: /* drop all */
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00002181#ifdef SHUT_RDWR
2182 how = SHUT_RDWR;
2183#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002184 default:
Alexandre Julliarda3960291999-02-26 11:11:13 +00002185 WSAAsyncSelect( s, 0, 0, 0 );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002186 break;
2187 }
2188
Ove Kaavenf45608f1999-10-23 16:53:34 +00002189 if (shutdown(fd, how) == 0)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002190 {
2191 if( how > 1 )
2192 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00002193 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002194 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00002195 close(fd);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002196 return 0;
2197 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002198 SetLastError(wsaErrno());
Ove Kaavenf45608f1999-10-23 16:53:34 +00002199 close(fd);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002200 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002201 else SetLastError(WSAENOTSOCK);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002202 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002203}
2204
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002205/***********************************************************************
2206 * shutdown() (WINSOCK.22)
2207 */
2208INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2209{
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00002210 return (INT16)WSOCK32_shutdown( s, how );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002211}
2212
2213
2214/***********************************************************************
2215 * socket() (WSOCK32.23)
2216 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00002217SOCKET WINAPI WSOCK32_socket(INT af, INT type, INT protocol)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002218{
Ove Kaavenf45608f1999-10-23 16:53:34 +00002219 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard92643002000-08-31 01:59:51 +00002220 SOCKET ret;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002221
Alexandre Julliard61fece01999-06-26 19:09:08 +00002222 TRACE("(%08x): af=%d type=%d protocol=%d\n",
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002223 (unsigned)pwsi, af, type, protocol);
2224
2225 if( pwsi )
2226 {
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002227 /* check the socket family */
2228 switch(af)
2229 {
Pavel Roskin94d99641998-12-26 11:52:51 +00002230#ifdef HAVE_IPX
Stephen Langasekdc163421998-11-08 15:42:40 +00002231 case WS_AF_IPX: af = AF_IPX;
2232#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002233 case AF_INET:
2234 case AF_UNSPEC: break;
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002235 default: SetLastError(WSAEAFNOSUPPORT);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002236 return INVALID_SOCKET;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002237 }
2238
2239 /* check the socket type */
2240 switch(type)
2241 {
2242 case SOCK_STREAM:
2243 case SOCK_DGRAM:
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002244 case SOCK_RAW: break;
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002245 default: SetLastError(WSAESOCKTNOSUPPORT);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002246 return INVALID_SOCKET;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002247 }
2248
2249 /* check the protocol type */
2250 if ( protocol < 0 ) /* don't support negative values */
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002251 { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002252
2253 if ( af == AF_UNSPEC) /* did they not specify the address family? */
2254 switch(protocol)
2255 {
2256 case IPPROTO_TCP:
2257 if (type == SOCK_STREAM) { af = AF_INET; break; }
2258 case IPPROTO_UDP:
2259 if (type == SOCK_DGRAM) { af = AF_INET; break; }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002260 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002261 }
2262
Alexandre Julliard92643002000-08-31 01:59:51 +00002263 SERVER_START_REQ
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002264 {
Alexandre Julliard92643002000-08-31 01:59:51 +00002265 struct create_socket_request *req = server_alloc_req( sizeof(*req), 0 );
2266 req->family = af;
2267 req->type = type;
2268 req->protocol = protocol;
2269 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2270 req->inherit = TRUE;
2271 sock_server_call( REQ_CREATE_SOCKET );
2272 ret = req->handle;
2273 }
2274 SERVER_END_REQ;
Stephane Lussierec6f37b2000-09-01 01:21:42 +00002275 if ( ((int) ret) >= 0)
Alexandre Julliard92643002000-08-31 01:59:51 +00002276 {
2277 TRACE("\tcreated %04x\n", ret );
2278 return ret;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002279 }
2280
Ove Kaavenf45608f1999-10-23 16:53:34 +00002281 if (GetLastError() == WSAEACCES) /* raw socket denied */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002282 {
James Juran407f6ba1999-05-22 10:35:19 +00002283 if (type == SOCK_RAW)
Alexandre Julliard61fece01999-06-26 19:09:08 +00002284 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
James Juran407f6ba1999-05-22 10:35:19 +00002285 else
Alexandre Julliard61fece01999-06-26 19:09:08 +00002286 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002287 SetLastError(WSAESOCKTNOSUPPORT);
Ove Kaavenf45608f1999-10-23 16:53:34 +00002288 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002289 }
2290
Alexandre Julliard61fece01999-06-26 19:09:08 +00002291 WARN("\t\tfailed!\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +00002292 return INVALID_SOCKET;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002293}
2294
2295/***********************************************************************
2296 * socket() (WINSOCK.23)
2297 */
2298SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2299{
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00002300 return (SOCKET16)WSOCK32_socket( af, type, protocol );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002301}
2302
2303
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002304/* ----------------------------------- DNS services
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002305 *
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002306 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
Alexandre Julliard491502b1997-11-01 19:08:16 +00002307 * Also, we have to use wsock32 stubs to convert structures and
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00002308 * error codes from Unix to WSA, hence there is no direct mapping in
2309 * the relay32/wsock32.spec.
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002310 */
2311
2312static char* NULL_STRING = "NULL";
2313
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002314/***********************************************************************
Alexandre Julliard491502b1997-11-01 19:08:16 +00002315 * gethostbyaddr() (WINSOCK.51)(WSOCK32.51)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002316 */
Andreas Mohrae509412000-08-03 22:19:09 +00002317static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002318{
Rein Klazesff7a61f2000-09-24 19:41:57 +00002319 WIN_hostent *retval = NULL;
Ove Kaavenf45608f1999-10-23 16:53:34 +00002320 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002321
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002322 if( pwsi )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002323 {
Alexandre Julliard491502b1997-11-01 19:08:16 +00002324 struct hostent* host;
Rein Klazesff7a61f2000-09-24 19:41:57 +00002325#if HAVE_LINUX_GETHOSTBYNAME_R_6
2326 char *extrabuf;
2327 int ebufsize=1024;
2328 struct hostent hostentry;
2329 int locerr=ENOBUFS;
2330 host = NULL;
2331 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2332 while(extrabuf) {
2333 int res = gethostbyaddr_r(addr, len, type,
2334 &hostentry, extrabuf, ebufsize, &host, &locerr);
2335 if( res != ERANGE) break;
2336 ebufsize *=2;
2337 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2338 }
2339 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2340#else
2341 EnterCriticalSection( &csWSgetXXXbyYYY );
2342 host = gethostbyaddr(addr, len, type);
2343 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2344#endif
2345 if( host != NULL )
2346 {
Alexandre Julliard491502b1997-11-01 19:08:16 +00002347 if( WS_dup_he(pwsi, host, dup_flag) )
Rein Klazesff7a61f2000-09-24 19:41:57 +00002348 retval = (WIN_hostent*)(pwsi->he);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002349 else
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002350 SetLastError(WSAENOBUFS);
Rein Klazesff7a61f2000-09-24 19:41:57 +00002351 }
2352#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2353 HeapFree(GetProcessHeap(),0,extrabuf);
2354#else
2355 LeaveCriticalSection( &csWSgetXXXbyYYY );
2356#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002357 }
Rein Klazesff7a61f2000-09-24 19:41:57 +00002358 return retval;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002359}
2360
Alexandre Julliard491502b1997-11-01 19:08:16 +00002361SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2362{
Andreas Mohrae509412000-08-03 22:19:09 +00002363 WIN_hostent* retval;
Alexandre Julliard61fece01999-06-26 19:09:08 +00002364 TRACE("ptr %08x, len %d, type %d\n",
Alexandre Julliard491502b1997-11-01 19:08:16 +00002365 (unsigned) addr, len, type);
2366 retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
2367 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2368}
2369
Andreas Mohrae509412000-08-03 22:19:09 +00002370WIN_hostent* WINAPI WSOCK32_gethostbyaddr(const char *addr, INT len,
Alexandre Julliarda3960291999-02-26 11:11:13 +00002371 INT type)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002372{
Alexandre Julliard61fece01999-06-26 19:09:08 +00002373 TRACE("ptr %08x, len %d, type %d\n",
Alexandre Julliard491502b1997-11-01 19:08:16 +00002374 (unsigned) addr, len, type);
2375 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2376}
2377
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002378/***********************************************************************
Alexandre Julliard491502b1997-11-01 19:08:16 +00002379 * gethostbyname() (WINSOCK.52)(WSOCK32.52)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002380 */
Andreas Mohrae509412000-08-03 22:19:09 +00002381static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002382{
Rein Klazesff7a61f2000-09-24 19:41:57 +00002383 WIN_hostent *retval = NULL;
Ove Kaavenf45608f1999-10-23 16:53:34 +00002384 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002385
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002386 if( pwsi )
2387 {
2388 struct hostent* host;
Rein Klazesff7a61f2000-09-24 19:41:57 +00002389#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2390 char *extrabuf;
2391 int ebufsize=1024;
2392 struct hostent hostentry;
2393 int locerr = ENOBUFS;
2394 host = NULL;
2395 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2396 while(extrabuf) {
2397 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2398 if( res != ERANGE) break;
2399 ebufsize *=2;
2400 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2401 }
2402 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2403#else
2404 EnterCriticalSection( &csWSgetXXXbyYYY );
2405 host = gethostbyname(name);
2406 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2407#endif
2408 if( host != NULL )
2409 {
Alexandre Julliard491502b1997-11-01 19:08:16 +00002410 if( WS_dup_he(pwsi, host, dup_flag) )
Rein Klazesff7a61f2000-09-24 19:41:57 +00002411 retval = (WIN_hostent*)(pwsi->he);
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002412 else SetLastError(WSAENOBUFS);
Rein Klazesff7a61f2000-09-24 19:41:57 +00002413 }
2414#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2415 HeapFree(GetProcessHeap(),0,extrabuf);
2416#else
2417 LeaveCriticalSection( &csWSgetXXXbyYYY );
2418#endif
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002419 }
Rein Klazesff7a61f2000-09-24 19:41:57 +00002420 return retval;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002421}
2422
Alexandre Julliard491502b1997-11-01 19:08:16 +00002423SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2424{
Andreas Mohrae509412000-08-03 22:19:09 +00002425 WIN_hostent* retval;
Alexandre Julliard61fece01999-06-26 19:09:08 +00002426 TRACE("%s\n", (name)?name:NULL_STRING);
Alexandre Julliard491502b1997-11-01 19:08:16 +00002427 retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
2428 return (retval)? SEGPTR_GET(retval) : ((SEGPTR)NULL) ;
2429}
2430
Andreas Mohrae509412000-08-03 22:19:09 +00002431WIN_hostent* WINAPI WSOCK32_gethostbyname(const char* name)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002432{
Alexandre Julliard61fece01999-06-26 19:09:08 +00002433 TRACE("%s\n", (name)?name:NULL_STRING);
Alexandre Julliard491502b1997-11-01 19:08:16 +00002434 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2435}
2436
2437
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002438/***********************************************************************
Alexandre Julliard491502b1997-11-01 19:08:16 +00002439 * getprotobyname() (WINSOCK.53)(WSOCK32.53)
2440 */
Andreas Mohrae509412000-08-03 22:19:09 +00002441static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002442{
Rein Klazesff7a61f2000-09-24 19:41:57 +00002443 WIN_protoent* retval = NULL;
Ove Kaavenf45608f1999-10-23 16:53:34 +00002444 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard491502b1997-11-01 19:08:16 +00002445
2446 if( pwsi )
2447 {
2448 struct protoent* proto;
Rein Klazesff7a61f2000-09-24 19:41:57 +00002449 EnterCriticalSection( &csWSgetXXXbyYYY );
Alexandre Julliard491502b1997-11-01 19:08:16 +00002450 if( (proto = getprotobyname(name)) != NULL )
Rein Klazesff7a61f2000-09-24 19:41:57 +00002451 {
Alexandre Julliard491502b1997-11-01 19:08:16 +00002452 if( WS_dup_pe(pwsi, proto, dup_flag) )
Rein Klazesff7a61f2000-09-24 19:41:57 +00002453 retval = (WIN_protoent*)(pwsi->pe);
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002454 else SetLastError(WSAENOBUFS);
Rein Klazesff7a61f2000-09-24 19:41:57 +00002455 }
Rein Klazesce77ea92000-04-06 19:31:38 +00002456 else {
2457 MESSAGE("protocol %s not found; You might want to add "
2458 "this to /etc/protocols\n", debugstr_a(name) );
2459 SetLastError(WSANO_DATA);
2460 }
Rein Klazesff7a61f2000-09-24 19:41:57 +00002461 LeaveCriticalSection( &csWSgetXXXbyYYY );
Rein Klazesce77ea92000-04-06 19:31:38 +00002462 } else SetLastError(WSANOTINITIALISED);
Rein Klazesff7a61f2000-09-24 19:41:57 +00002463 return retval;
Alexandre Julliard491502b1997-11-01 19:08:16 +00002464}
2465
2466SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2467{
Andreas Mohrae509412000-08-03 22:19:09 +00002468 WIN_protoent* retval;
Alexandre Julliard61fece01999-06-26 19:09:08 +00002469 TRACE("%s\n", (name)?name:NULL_STRING);
Alexandre Julliard491502b1997-11-01 19:08:16 +00002470 retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
2471 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2472}
2473
Andreas Mohrae509412000-08-03 22:19:09 +00002474WIN_protoent* WINAPI WSOCK32_getprotobyname(const char* name)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002475{
Alexandre Julliard61fece01999-06-26 19:09:08 +00002476 TRACE("%s\n", (name)?name:NULL_STRING);
Alexandre Julliard491502b1997-11-01 19:08:16 +00002477 return __ws_getprotobyname(name, WS_DUP_LINEAR);
2478}
2479
2480
2481/***********************************************************************
2482 * getprotobynumber() (WINSOCK.54)(WSOCK32.54)
2483 */
Andreas Mohrae509412000-08-03 22:19:09 +00002484static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002485{
Rein Klazesff7a61f2000-09-24 19:41:57 +00002486 WIN_protoent* retval = NULL;
Ove Kaavenf45608f1999-10-23 16:53:34 +00002487 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard491502b1997-11-01 19:08:16 +00002488
2489 if( pwsi )
2490 {
2491 struct protoent* proto;
Rein Klazesff7a61f2000-09-24 19:41:57 +00002492 EnterCriticalSection( &csWSgetXXXbyYYY );
Alexandre Julliard491502b1997-11-01 19:08:16 +00002493 if( (proto = getprotobynumber(number)) != NULL )
Rein Klazesff7a61f2000-09-24 19:41:57 +00002494 {
Alexandre Julliard491502b1997-11-01 19:08:16 +00002495 if( WS_dup_pe(pwsi, proto, dup_flag) )
Rein Klazesff7a61f2000-09-24 19:41:57 +00002496 retval = (WIN_protoent*)(pwsi->pe);
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002497 else SetLastError(WSAENOBUFS);
Rein Klazesff7a61f2000-09-24 19:41:57 +00002498 }
Rein Klazesce77ea92000-04-06 19:31:38 +00002499 else {
2500 MESSAGE("protocol number %d not found; You might want to add "
2501 "this to /etc/protocols\n", number );
2502 SetLastError(WSANO_DATA);
2503 }
Rein Klazesff7a61f2000-09-24 19:41:57 +00002504 LeaveCriticalSection( &csWSgetXXXbyYYY );
Rein Klazesce77ea92000-04-06 19:31:38 +00002505 } else SetLastError(WSANOTINITIALISED);
Rein Klazesff7a61f2000-09-24 19:41:57 +00002506 return retval;
Alexandre Julliard491502b1997-11-01 19:08:16 +00002507}
2508
2509SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2510{
Andreas Mohrae509412000-08-03 22:19:09 +00002511 WIN_protoent* retval;
Alexandre Julliard61fece01999-06-26 19:09:08 +00002512 TRACE("%i\n", number);
Alexandre Julliard491502b1997-11-01 19:08:16 +00002513 retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
2514 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2515}
2516
Andreas Mohrae509412000-08-03 22:19:09 +00002517WIN_protoent* WINAPI WSOCK32_getprotobynumber(INT number)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002518{
Alexandre Julliard61fece01999-06-26 19:09:08 +00002519 TRACE("%i\n", number);
Alexandre Julliard491502b1997-11-01 19:08:16 +00002520 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2521}
2522
2523
2524/***********************************************************************
2525 * getservbyname() (WINSOCK.55)(WSOCK32.55)
2526 */
Andreas Mohrae509412000-08-03 22:19:09 +00002527static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002528{
Rein Klazesff7a61f2000-09-24 19:41:57 +00002529 WIN_servent* retval = NULL;
Ove Kaavenf45608f1999-10-23 16:53:34 +00002530 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard491502b1997-11-01 19:08:16 +00002531
2532 if( pwsi )
2533 {
2534 struct servent* serv;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00002535 int i = wsi_strtolo( pwsi, name, proto );
2536
Lars Heetee63fdf12000-03-19 12:40:53 +00002537 if( i ) {
Rein Klazesff7a61f2000-09-24 19:41:57 +00002538 EnterCriticalSection( &csWSgetXXXbyYYY );
Lars Heetee63fdf12000-03-19 12:40:53 +00002539 serv = getservbyname(pwsi->buffer,
2540 proto ? (pwsi->buffer + i) : NULL);
2541 if( serv != NULL )
Rein Klazesff7a61f2000-09-24 19:41:57 +00002542 {
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00002543 if( WS_dup_se(pwsi, serv, dup_flag) )
Rein Klazesff7a61f2000-09-24 19:41:57 +00002544 retval = (WIN_servent*)(pwsi->se);
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002545 else SetLastError(WSAENOBUFS);
Rein Klazesff7a61f2000-09-24 19:41:57 +00002546 }
Rein Klazes5d3f7a62000-03-07 12:23:51 +00002547 else {
Rein Klazesce77ea92000-04-06 19:31:38 +00002548 MESSAGE("service %s protocol %s not found; You might want to add "
Rein Klazes5d3f7a62000-03-07 12:23:51 +00002549 "this to /etc/services\n", debugstr_a(pwsi->buffer),
Lars Heetee63fdf12000-03-19 12:40:53 +00002550 proto ? debugstr_a(pwsi->buffer+i):"*");
Rein Klazes5d3f7a62000-03-07 12:23:51 +00002551 SetLastError(WSANO_DATA);
2552 }
Rein Klazesff7a61f2000-09-24 19:41:57 +00002553 LeaveCriticalSection( &csWSgetXXXbyYYY );
Lars Heetee63fdf12000-03-19 12:40:53 +00002554 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002555 else SetLastError(WSAENOBUFS);
Rein Klazes5d3f7a62000-03-07 12:23:51 +00002556 } else SetLastError(WSANOTINITIALISED);
Rein Klazesff7a61f2000-09-24 19:41:57 +00002557 return retval;
Alexandre Julliard491502b1997-11-01 19:08:16 +00002558}
2559
2560SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2561{
Andreas Mohrae509412000-08-03 22:19:09 +00002562 WIN_servent* retval;
Alexandre Julliard61fece01999-06-26 19:09:08 +00002563 TRACE("'%s', '%s'\n",
Alexandre Julliard491502b1997-11-01 19:08:16 +00002564 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2565 retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2566 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2567}
2568
Andreas Mohrae509412000-08-03 22:19:09 +00002569WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002570{
Alexandre Julliard61fece01999-06-26 19:09:08 +00002571 TRACE("'%s', '%s'\n",
Alexandre Julliard491502b1997-11-01 19:08:16 +00002572 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2573 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2574}
2575
2576
2577/***********************************************************************
2578 * getservbyport() (WINSOCK.56)(WSOCK32.56)
2579 */
Andreas Mohrae509412000-08-03 22:19:09 +00002580static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002581{
Rein Klazesff7a61f2000-09-24 19:41:57 +00002582 WIN_servent* retval = NULL;
Ove Kaavenf45608f1999-10-23 16:53:34 +00002583 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard491502b1997-11-01 19:08:16 +00002584
2585 if( pwsi )
2586 {
2587 struct servent* serv;
Lars Heetee63fdf12000-03-19 12:40:53 +00002588 if (!proto || wsi_strtolo( pwsi, proto, NULL )) {
Rein Klazesff7a61f2000-09-24 19:41:57 +00002589 EnterCriticalSection( &csWSgetXXXbyYYY );
Lars Heetee63fdf12000-03-19 12:40:53 +00002590 if( (serv = getservbyport(port, (proto) ? pwsi->buffer : NULL)) != NULL ) {
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00002591 if( WS_dup_se(pwsi, serv, dup_flag) )
Rein Klazesff7a61f2000-09-24 19:41:57 +00002592 retval = (WIN_servent*)(pwsi->se);
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002593 else SetLastError(WSAENOBUFS);
Lars Heetee63fdf12000-03-19 12:40:53 +00002594 }
Rein Klazes5d3f7a62000-03-07 12:23:51 +00002595 else {
Gerald Pfeifer0a094822000-06-01 22:46:20 +00002596 MESSAGE("service on port %lu protocol %s not found; You might want to add "
Gerald Pfeifer410617f2000-05-23 23:32:42 +00002597 "this to /etc/services\n", (unsigned long)ntohl(port),
Lars Heetee63fdf12000-03-19 12:40:53 +00002598 proto ? debugstr_a(pwsi->buffer) : "*");
Rein Klazes5d3f7a62000-03-07 12:23:51 +00002599 SetLastError(WSANO_DATA);
2600 }
Rein Klazesff7a61f2000-09-24 19:41:57 +00002601 LeaveCriticalSection( &csWSgetXXXbyYYY );
Lars Heetee63fdf12000-03-19 12:40:53 +00002602 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002603 else SetLastError(WSAENOBUFS);
Rein Klazes5d3f7a62000-03-07 12:23:51 +00002604 } else SetLastError(WSANOTINITIALISED);
Rein Klazesff7a61f2000-09-24 19:41:57 +00002605 return retval;
Alexandre Julliard491502b1997-11-01 19:08:16 +00002606}
2607
2608SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2609{
Andreas Mohrae509412000-08-03 22:19:09 +00002610 WIN_servent* retval;
2611 TRACE("%d (i.e. port %d), '%s'\n",
2612 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
Alexandre Julliard491502b1997-11-01 19:08:16 +00002613 retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2614 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2615}
2616
Andreas Mohrae509412000-08-03 22:19:09 +00002617WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
Alexandre Julliard491502b1997-11-01 19:08:16 +00002618{
Andreas Mohrae509412000-08-03 22:19:09 +00002619 TRACE("%d (i.e. port %d), '%s'\n",
2620 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
Alexandre Julliard491502b1997-11-01 19:08:16 +00002621 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2622}
2623
2624
2625/***********************************************************************
2626 * gethostname() (WSOCK32.57)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002627 */
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00002628INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002629{
Ove Kaavenf45608f1999-10-23 16:53:34 +00002630 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002631
Alexandre Julliard61fece01999-06-26 19:09:08 +00002632 TRACE("(%08x): name %s, len %d\n",
Alexandre Julliard491502b1997-11-01 19:08:16 +00002633 (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002634 if( pwsi )
2635 {
2636 if (gethostname(name, namelen) == 0) return 0;
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002637 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002638 }
2639 return SOCKET_ERROR;
2640}
2641
2642/***********************************************************************
Alexandre Julliard491502b1997-11-01 19:08:16 +00002643 * gethostname() (WINSOCK.57)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002644 */
2645INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2646{
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00002647 return (INT16)WSOCK32_gethostname(name, namelen);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002648}
2649
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002650
2651/* ------------------------------------- Windows sockets extensions -- *
2652 * *
2653 * ------------------------------------------------------------------- */
Ove Kaavenf45608f1999-10-23 16:53:34 +00002654
Patrik Stridvallb167d4b2000-06-23 15:47:36 +00002655/***********************************************************************
2656 * WSAEnumNetworkEvents
2657 */
Ove Kaavenf45608f1999-10-23 16:53:34 +00002658int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2659{
2660 LPWSINFO pwsi = WINSOCK_GetIData();
Ove Kaavenf45608f1999-10-23 16:53:34 +00002661
2662 TRACE("(%08x): %08x, hEvent %08x, lpEvent %08x\n",
2663 (unsigned)pwsi, s, hEvent, (unsigned)lpEvent );
2664 if( _check_ws(pwsi, s) )
2665 {
Alexandre Julliard92643002000-08-31 01:59:51 +00002666 SERVER_START_REQ
2667 {
2668 struct get_socket_event_request *req = server_alloc_req( sizeof(*req),
2669 sizeof(lpEvent->iErrorCode) );
2670 req->handle = s;
2671 req->service = TRUE;
2672 req->s_event = 0;
2673 req->c_event = hEvent;
2674 sock_server_call( REQ_GET_SOCKET_EVENT );
2675 lpEvent->lNetworkEvents = req->pmask;
2676 memcpy(lpEvent->iErrorCode, server_data_ptr(req), server_data_size(req) );
2677 }
2678 SERVER_END_REQ;
2679 return 0;
Ove Kaavenf45608f1999-10-23 16:53:34 +00002680 }
2681 else SetLastError(WSAEINVAL);
2682 return SOCKET_ERROR;
2683}
2684
Patrik Stridvallb167d4b2000-06-23 15:47:36 +00002685/***********************************************************************
2686 * WSAEventSelect
2687 */
Ove Kaavenf45608f1999-10-23 16:53:34 +00002688int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2689{
2690 LPWSINFO pwsi = WINSOCK_GetIData();
Ove Kaavenf45608f1999-10-23 16:53:34 +00002691
2692 TRACE("(%08x): %08x, hEvent %08x, event %08x\n",
2693 (unsigned)pwsi, s, hEvent, (unsigned)lEvent );
2694 if( _check_ws(pwsi, s) )
2695 {
Alexandre Julliard92643002000-08-31 01:59:51 +00002696 SERVER_START_REQ
2697 {
2698 struct set_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
2699 req->handle = s;
2700 req->mask = lEvent;
2701 req->event = hEvent;
2702 sock_server_call( REQ_SET_SOCKET_EVENT );
2703 }
2704 SERVER_END_REQ;
2705 return 0;
Ove Kaavenf45608f1999-10-23 16:53:34 +00002706 }
2707 else SetLastError(WSAEINVAL);
2708 return SOCKET_ERROR;
2709}
2710
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002711/***********************************************************************
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00002712 * WSAAsyncSelect() (WINSOCK.101)(WSOCK32.101)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002713 */
2714
Ove Kaavenf45608f1999-10-23 16:53:34 +00002715VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002716{
Ove Kaavenf45608f1999-10-23 16:53:34 +00002717 ws_select_info *info = (ws_select_info*)ptr;
Ove Kaavencb98a6e2000-03-26 18:21:16 +00002718 LPWSINFO pwsi = info->pwsi;
Ove Kaavencb98a6e2000-03-26 18:21:16 +00002719 unsigned int i, pmask, orphan = FALSE;
Alexandre Julliard92643002000-08-31 01:59:51 +00002720 int errors[FD_MAX_EVENTS];
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002721
Ove Kaavenf45608f1999-10-23 16:53:34 +00002722 TRACE("socket %08x, event %08x\n", info->sock, info->event);
2723 SetLastError(0);
Alexandre Julliard92643002000-08-31 01:59:51 +00002724 SERVER_START_REQ
2725 {
2726 struct get_socket_event_request *req = server_alloc_req( sizeof(*req), sizeof(errors) );
2727 req->handle = info->sock;
2728 req->service = TRUE;
2729 req->s_event = info->event; /* <== avoid race conditions */
2730 req->c_event = info->event;
2731 sock_server_call( REQ_GET_SOCKET_EVENT );
2732 pmask = req->pmask;
2733 memcpy( errors, server_data_ptr(req), server_data_size(req) );
2734 }
2735 SERVER_END_REQ;
Ove Kaavencb98a6e2000-03-26 18:21:16 +00002736 if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002737 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00002738 /* orphaned event (socket closed or something) */
Ove Kaavencb98a6e2000-03-26 18:21:16 +00002739 pmask = WS_FD_SERVEVENT;
2740 orphan = TRUE;
Alexandre Julliard92643002000-08-31 01:59:51 +00002741 }
2742
Ove Kaavencb98a6e2000-03-26 18:21:16 +00002743 /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2744 if (pmask & WS_FD_SERVEVENT) {
2745 int q;
2746 for (q=0; q<WS_ACCEPT_QUEUE; q++)
2747 if (pwsi->accept_old[q] == info->sock) {
2748 /* there's only one service thread per pwsi, no lock necessary */
2749 HANDLE as = pwsi->accept_new[q];
2750 if (as) {
2751 pwsi->accept_new[q] = 0;
2752 pwsi->accept_old[q] = 0;
2753 WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
2754 }
2755 }
2756 pmask &= ~WS_FD_SERVEVENT;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002757 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00002758 /* dispatch network events */
Ove Kaavenf45608f1999-10-23 16:53:34 +00002759 for (i=0; i<FD_MAX_EVENTS; i++)
2760 if (pmask & (1<<i)) {
Alexandre Julliard92643002000-08-31 01:59:51 +00002761 TRACE("post: event bit %d, error %d\n", i, errors[i]);
Ove Kaavenf45608f1999-10-23 16:53:34 +00002762 PostMessageA(info->hWnd, info->uMsg, info->sock,
Alexandre Julliard92643002000-08-31 01:59:51 +00002763 WSAMAKESELECTREPLY(1<<i, errors[i]));
Ove Kaavenf45608f1999-10-23 16:53:34 +00002764 }
Ove Kaavencb98a6e2000-03-26 18:21:16 +00002765 /* cleanup */
2766 if (orphan)
2767 {
2768 TRACE("orphaned event, self-destructing\n");
2769 /* SERVICE_Delete closes the event object */
2770 SERVICE_Delete( info->service );
2771 WS_FREE(info);
2772 }
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002773}
2774
Patrik Stridvallb8684a21999-07-31 17:32:05 +00002775INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002776{
Ove Kaavenf45608f1999-10-23 16:53:34 +00002777 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002778
Alexandre Julliard61fece01999-06-26 19:09:08 +00002779 TRACE("(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00002780 (unsigned)pwsi, (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
Ove Kaavenf45608f1999-10-23 16:53:34 +00002781 if( _check_ws(pwsi, s) )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002782 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002783 if( lEvent )
2784 {
Ove Kaavenf45608f1999-10-23 16:53:34 +00002785 ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2786 if( info )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002787 {
Ove Kaavencb98a6e2000-03-26 18:21:16 +00002788 HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
Ove Kaavenf45608f1999-10-23 16:53:34 +00002789 INT err;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002790
Ove Kaavencb98a6e2000-03-26 18:21:16 +00002791 info->sock = s;
2792 info->event = hObj;
2793 info->hWnd = hWnd;
2794 info->uMsg = uMsg;
2795 info->lEvent = lEvent;
2796 info->pwsi = pwsi;
Ove Kaavenf45608f1999-10-23 16:53:34 +00002797 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002798
Ove Kaavenf45608f1999-10-23 16:53:34 +00002799 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2800 if (err) {
Ove Kaavencb98a6e2000-03-26 18:21:16 +00002801 /* SERVICE_Delete closes the event object */
Ove Kaavenf45608f1999-10-23 16:53:34 +00002802 SERVICE_Delete( info->service );
2803 WS_FREE(info);
2804 return err;
2805 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002806
2807 return 0; /* success */
2808 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002809 else SetLastError(WSAENOBUFS);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002810 }
Ove Kaavenf45608f1999-10-23 16:53:34 +00002811 else
2812 {
2813 WSAEventSelect(s, 0, 0);
2814 return 0;
2815 }
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002816 }
Marcus Meissner01f3dc31999-05-12 10:34:03 +00002817 else SetLastError(WSAEINVAL);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002818 return SOCKET_ERROR;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002819}
2820
Patrik Stridvallb8684a21999-07-31 17:32:05 +00002821INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00002822{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002823 return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00002824}
2825
Moses DeJonge0a3ba51999-11-23 22:29:00 +00002826/***********************************************************************
2827 * WSARecvEx() (WSOCK32.1107)
2828 *
2829 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
2830 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
2831 * into the flags parameter when a partial packet is read. This only applies to
2832 * sockets using the datagram protocol. This method does not seem to be implemented
2833 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
2834 * flag when a fragmented packet arrives.
2835 */
2836INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags) {
2837 FIXME("(WSARecvEx) partial packet return value not set \n");
2838
Patrik Stridvallfcfacb92000-03-24 20:46:04 +00002839 return WSOCK32_recv(s, buf, len, *flags);
Moses DeJonge0a3ba51999-11-23 22:29:00 +00002840}
2841
2842
2843/***********************************************************************
2844 * WSARecvEx16() (WINSOCK.1107)
2845 *
2846 * See description for WSARecvEx()
2847 */
2848INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2849 FIXME("(WSARecvEx16) partial packet return value not set \n");
2850
2851 return WINSOCK_recv16(s, buf, len, *flags);
2852}
2853
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002854
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002855/***********************************************************************
James Hatheway829405a2000-06-18 17:23:17 +00002856 * WSACreateEvent() (WS2_32.???)
2857 *
2858 */
2859WSAEVENT WINAPI WSACreateEvent(void)
2860{
2861 /* Create a manual-reset event, with initial state: unsignealed */
2862 TRACE("\n");
2863
2864 return CreateEventA(NULL, TRUE, FALSE, NULL);
2865}
2866
2867/***********************************************************************
2868 * WSACloseEvent() (WS2_32.???)
2869 *
2870 */
2871BOOL WINAPI WSACloseEvent(WSAEVENT event)
2872{
2873 TRACE ("event=0x%x\n", event);
2874
2875 return CloseHandle(event);
2876}
2877
2878/***********************************************************************
2879 * WSASocketA() (WS2_32.???)
2880 *
2881 */
2882SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2883 LPWSAPROTOCOL_INFOA lpProtocolInfo,
2884 GROUP g, DWORD dwFlags)
2885{
2886 /*
2887 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2888 g, dwFlags) are ignored.
2889 */
2890
2891 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
2892 af, type, protocol, lpProtocolInfo, g, dwFlags );
2893
2894 return ( WSOCK32_socket (af, type, protocol) );
2895}
2896
2897
2898/***********************************************************************
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002899 * __WSAFDIsSet() (WINSOCK.151)
2900 */
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00002901INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002902{
2903 int i = set->fd_count;
2904
Alexandre Julliard61fece01999-06-26 19:09:08 +00002905 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002906
2907 while (i--)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002908 if (set->fd_array[i] == s) return 1;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002909 return 0;
2910}
2911
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002912/***********************************************************************
2913 * __WSAFDIsSet() (WSOCK32.151)
2914 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002915INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002916{
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00002917 int i = set->fd_count;
2918
Alexandre Julliard61fece01999-06-26 19:09:08 +00002919 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00002920
2921 while (i--)
2922 if (set->fd_array[i] == s) return 1;
2923 return 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002924}
2925
2926/***********************************************************************
2927 * WSAIsBlocking() (WINSOCK.114)(WSOCK32.114)
2928 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002929BOOL WINAPI WSAIsBlocking(void)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002930{
2931 /* By default WinSock should set all its sockets to non-blocking mode
2932 * and poll in PeekMessage loop when processing "blocking" ones. This
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00002933 * function is supposed to tell if the program is in this loop. Our
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002934 * blocking calls are truly blocking so we always return FALSE.
2935 *
2936 * Note: It is allowed to call this function without prior WSAStartup().
2937 */
2938
Alexandre Julliard61fece01999-06-26 19:09:08 +00002939 TRACE("\n");
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002940 return FALSE;
2941}
2942
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002943/***********************************************************************
2944 * WSACancelBlockingCall() (WINSOCK.113)(WSOCK32.113)
2945 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002946INT WINAPI WSACancelBlockingCall(void)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002947{
Ove Kaavenf45608f1999-10-23 16:53:34 +00002948 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002949
Alexandre Julliard61fece01999-06-26 19:09:08 +00002950 TRACE("(%08x)\n", (unsigned)pwsi);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002951
2952 if( pwsi ) return 0;
2953 return SOCKET_ERROR;
2954}
2955
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002956
2957/***********************************************************************
2958 * WSASetBlockingHook16() (WINSOCK.109)
2959 */
2960FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002961{
2962 FARPROC16 prev;
Ove Kaavenf45608f1999-10-23 16:53:34 +00002963 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002964
Alexandre Julliard61fece01999-06-26 19:09:08 +00002965 TRACE("(%08x): hook %08x\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002966 (unsigned)pwsi, (unsigned) lpBlockFunc);
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00002967 if( pwsi )
2968 {
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002969 prev = (FARPROC16)pwsi->blocking_hook;
2970 pwsi->blocking_hook = (DWORD)lpBlockFunc;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002971 pwsi->flags &= ~WSI_BLOCKINGHOOK;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002972 return prev;
2973 }
2974 return 0;
2975}
2976
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00002977
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002978/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00002979 * WSASetBlockingHook()
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002980 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002981FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002982{
Alexandre Julliarda3960291999-02-26 11:11:13 +00002983 FARPROC prev;
Ove Kaavenf45608f1999-10-23 16:53:34 +00002984 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00002985
Alexandre Julliard61fece01999-06-26 19:09:08 +00002986 TRACE("(%08x): hook %08x\n",
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002987 (unsigned)pwsi, (unsigned) lpBlockFunc);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002988 if( pwsi ) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002989 prev = (FARPROC)pwsi->blocking_hook;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002990 pwsi->blocking_hook = (DWORD)lpBlockFunc;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002991 pwsi->flags |= WSI_BLOCKINGHOOK;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002992 return prev;
2993 }
Alexandre Julliard23946ad1997-06-16 17:43:53 +00002994 return NULL;
2995}
2996
Alexandre Julliard670cdc41997-08-24 16:00:30 +00002997
2998/***********************************************************************
2999 * WSAUnhookBlockingHook16() (WINSOCK.110)
3000 */
3001INT16 WINAPI WSAUnhookBlockingHook16(void)
3002{
Ove Kaavenf45608f1999-10-23 16:53:34 +00003003 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003004
Alexandre Julliard61fece01999-06-26 19:09:08 +00003005 TRACE("(%08x)\n", (unsigned)pwsi);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003006 if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
3007 return SOCKET_ERROR;
3008}
3009
3010
3011/***********************************************************************
Patrik Stridvall2d6457c2000-03-28 20:22:59 +00003012 * WSAUnhookBlockingHook()
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003013 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003014INT WINAPI WSAUnhookBlockingHook(void)
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003015{
Ove Kaavenf45608f1999-10-23 16:53:34 +00003016 LPWSINFO pwsi = WINSOCK_GetIData();
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003017
Alexandre Julliard61fece01999-06-26 19:09:08 +00003018 TRACE("(%08x)\n", (unsigned)pwsi);
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003019 if( pwsi )
3020 {
3021 pwsi->blocking_hook = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003022 pwsi->flags &= ~WSI_BLOCKINGHOOK;
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003023 return 0;
3024 }
3025 return SOCKET_ERROR;
3026}
3027
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00003028
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003029/* ----------------------------------- end of API stuff */
3030
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00003031/* ----------------------------------- helper functions -
3032 *
3033 * TODO: Merge WS_dup_..() stuff into one function that
3034 * would operate with a generic structure containing internal
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00003035 * pointers (via a template of some kind).
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00003036 */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003037
3038static int list_size(char** l, int item_size)
3039{
3040 int i,j = 0;
3041 if(l)
3042 { for(i=0;l[i];i++)
3043 j += (item_size) ? item_size : strlen(l[i]) + 1;
3044 j += (i + 1) * sizeof(char*); }
3045 return j;
3046}
3047
3048static int list_dup(char** l_src, char* ref, char* base, int item_size)
3049{
3050 /* base is either either equal to ref or 0 or SEGPTR */
3051
3052 char* p = ref;
3053 char** l_to = (char**)ref;
3054 int i,j,k;
3055
3056 for(j=0;l_src[j];j++) ;
3057 p += (j + 1) * sizeof(char*);
3058 for(i=0;i<j;i++)
3059 { l_to[i] = base + (p - ref);
3060 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3061 memcpy(p, l_src[i], k); p += k; }
3062 l_to[i] = NULL;
3063 return (p - ref);
3064}
3065
3066/* ----- hostent */
3067
3068static int hostent_size(struct hostent* p_he)
3069{
3070 int size = 0;
3071 if( p_he )
3072 { size = sizeof(struct hostent);
3073 size += strlen(p_he->h_name) + 1;
3074 size += list_size(p_he->h_aliases, 0);
3075 size += list_size(p_he->h_addr_list, p_he->h_length ); }
3076 return size;
3077}
3078
Andreas Mohrae509412000-08-03 22:19:09 +00003079/* duplicate hostent entry
3080 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3081 * Dito for protoent and servent.
3082 */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003083int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
3084{
Andreas Mohrae509412000-08-03 22:19:09 +00003085 /* Convert hostent structure into ws_hostent so that the data fits
3086 * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or
3087 * relative to pwsi->buffer depending on "flag" value. Returns size
3088 * of the data copied (also in the pwsi->buflen).
3089 */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003090
Andreas Mohrae509412000-08-03 22:19:09 +00003091 int size = hostent_size(p_he);
3092 if( size )
3093 {
3094 char *p_name,*p_aliases,*p_addr,*p_base,*p;
3095 char *p_to;
3096 struct ws_hostent16 *p_to16;
3097 struct ws_hostent32 *p_to32;
Alexandre Julliard767e6f61998-08-09 12:47:43 +00003098
Andreas Mohrae509412000-08-03 22:19:09 +00003099 _check_buffer_he(pwsi, size);
3100 p_to = (char *)pwsi->he;
3101 p_to16 = (struct ws_hostent16*)pwsi->he;
3102 p_to32 = (struct ws_hostent32*)pwsi->he;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003103
Andreas Mohrae509412000-08-03 22:19:09 +00003104 p = p_to;
3105 p_base = (flag & WS_DUP_OFFSET) ? NULL
3106 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3107 p += (flag & WS_DUP_SEGPTR) ?
3108 sizeof(struct ws_hostent16) : sizeof(struct ws_hostent32);
3109 p_name = p;
3110 strcpy(p, p_he->h_name); p += strlen(p) + 1;
3111 p_aliases = p;
3112 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3113 p_addr = p;
3114 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
Alexandre Julliardb1bac321996-12-15 19:45:59 +00003115
Andreas Mohrae509412000-08-03 22:19:09 +00003116 if (flag & WS_DUP_SEGPTR) /* Win16 */
3117 {
3118 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
3119 p_to16->h_length = (INT16)p_he->h_length;
3120 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3121 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3122 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3123 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3124 }
3125 else /* Win32 */
3126 {
3127 p_to32->h_addrtype = p_he->h_addrtype;
3128 p_to32->h_length = p_he->h_length;
3129 p_to32->h_name = (p_base + (p_name - p_to));
3130 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3131 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3132 size += (sizeof(struct ws_hostent32) - sizeof(struct hostent));
3133 }
3134 }
3135 return size;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003136}
3137
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003138/* ----- protoent */
3139
3140static int protoent_size(struct protoent* p_pe)
3141{
3142 int size = 0;
3143 if( p_pe )
3144 { size = sizeof(struct protoent);
3145 size += strlen(p_pe->p_name) + 1;
3146 size += list_size(p_pe->p_aliases, 0); }
3147 return size;
3148}
3149
3150int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
3151{
Andreas Mohrae509412000-08-03 22:19:09 +00003152 int size = protoent_size(p_pe);
3153 if( size )
3154 {
3155 char *p_to;
3156 struct ws_protoent16 *p_to16;
3157 struct ws_protoent32 *p_to32;
3158 char *p_name,*p_aliases,*p_base,*p;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003159
Andreas Mohrae509412000-08-03 22:19:09 +00003160 _check_buffer_pe(pwsi, size);
3161 p_to = (char *)pwsi->pe;
3162 p_to16 = (struct ws_protoent16*)pwsi->pe;
3163 p_to32 = (struct ws_protoent32*)pwsi->pe;
3164 p = p_to;
3165 p_base = (flag & WS_DUP_OFFSET) ? NULL
3166 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3167 p += (flag & WS_DUP_SEGPTR) ?
3168 sizeof(struct ws_protoent16) : sizeof(struct ws_protoent32);
3169 p_name = p;
3170 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3171 p_aliases = p;
3172 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +00003173
Andreas Mohrae509412000-08-03 22:19:09 +00003174 if (flag & WS_DUP_SEGPTR) /* Win16 */
3175 {
3176 p_to16->p_proto = (INT16)p_pe->p_proto;
3177 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3178 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3179 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3180 }
3181 else /* Win32 */
3182 {
3183 p_to32->p_proto = p_pe->p_proto;
3184 p_to32->p_name = (p_base) + (p_name - p_to);
3185 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3186 size += (sizeof(struct ws_protoent32) - sizeof(struct protoent));
3187 }
3188 }
3189 return size;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003190}
3191
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003192/* ----- servent */
3193
3194static int servent_size(struct servent* p_se)
3195{
3196 int size = 0;
3197 if( p_se )
3198 { size += sizeof(struct servent);
3199 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3200 size += list_size(p_se->s_aliases, 0); }
3201 return size;
3202}
3203
3204int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
3205{
Andreas Mohrae509412000-08-03 22:19:09 +00003206 int size = servent_size(p_se);
3207 if( size )
3208 {
3209 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3210 char *p_to;
3211 struct ws_servent16 *p_to16;
3212 struct ws_servent32 *p_to32;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003213
Andreas Mohrae509412000-08-03 22:19:09 +00003214 _check_buffer_se(pwsi, size);
3215 p_to = (char *)pwsi->se;
3216 p_to16 = (struct ws_servent16*)pwsi->se;
3217 p_to32 = (struct ws_servent32*)pwsi->se;
3218 p = p_to;
3219 p_base = (flag & WS_DUP_OFFSET) ? NULL
3220 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3221 p += (flag & WS_DUP_SEGPTR) ?
3222 sizeof(struct ws_servent16) : sizeof(struct ws_servent32);
3223 p_name = p;
3224 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3225 p_proto = p;
3226 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3227 p_aliases = p;
3228 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003229
Andreas Mohrae509412000-08-03 22:19:09 +00003230 if (flag & WS_DUP_SEGPTR) /* Win16 */
3231 {
3232 p_to16->s_port = (INT16)p_se->s_port;
3233 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3234 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3235 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3236 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3237 }
3238 else /* Win32 */
3239 {
3240 p_to32->s_port = p_se->s_port;
3241 p_to32->s_name = (p_base + (p_name - p_to));
3242 p_to32->s_proto = (p_base + (p_proto - p_to));
3243 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3244 size += (sizeof(struct ws_servent32) - sizeof(struct servent));
3245 }
3246 }
3247 return size;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003248}
3249
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003250/* ----------------------------------- error handling */
3251
3252UINT16 wsaErrno(void)
3253{
3254 int loc_errno = errno;
Alexandre Julliard61fece01999-06-26 19:09:08 +00003255 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003256
3257 switch(loc_errno)
3258 {
3259 case EINTR: return WSAEINTR;
3260 case EBADF: return WSAEBADF;
Ove Kaavenf45608f1999-10-23 16:53:34 +00003261 case EPERM:
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003262 case EACCES: return WSAEACCES;
3263 case EFAULT: return WSAEFAULT;
3264 case EINVAL: return WSAEINVAL;
3265 case EMFILE: return WSAEMFILE;
3266 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3267 case EINPROGRESS: return WSAEINPROGRESS;
3268 case EALREADY: return WSAEALREADY;
3269 case ENOTSOCK: return WSAENOTSOCK;
3270 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3271 case EMSGSIZE: return WSAEMSGSIZE;
3272 case EPROTOTYPE: return WSAEPROTOTYPE;
3273 case ENOPROTOOPT: return WSAENOPROTOOPT;
3274 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3275 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3276 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3277 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3278 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3279 case EADDRINUSE: return WSAEADDRINUSE;
3280 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3281 case ENETDOWN: return WSAENETDOWN;
3282 case ENETUNREACH: return WSAENETUNREACH;
3283 case ENETRESET: return WSAENETRESET;
3284 case ECONNABORTED: return WSAECONNABORTED;
Alexandre Julliard54c27111998-03-29 19:44:57 +00003285 case EPIPE:
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003286 case ECONNRESET: return WSAECONNRESET;
3287 case ENOBUFS: return WSAENOBUFS;
3288 case EISCONN: return WSAEISCONN;
3289 case ENOTCONN: return WSAENOTCONN;
3290 case ESHUTDOWN: return WSAESHUTDOWN;
3291 case ETOOMANYREFS: return WSAETOOMANYREFS;
3292 case ETIMEDOUT: return WSAETIMEDOUT;
3293 case ECONNREFUSED: return WSAECONNREFUSED;
3294 case ELOOP: return WSAELOOP;
3295 case ENAMETOOLONG: return WSAENAMETOOLONG;
3296 case EHOSTDOWN: return WSAEHOSTDOWN;
3297 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3298 case ENOTEMPTY: return WSAENOTEMPTY;
3299#ifdef EPROCLIM
3300 case EPROCLIM: return WSAEPROCLIM;
3301#endif
3302#ifdef EUSERS
3303 case EUSERS: return WSAEUSERS;
3304#endif
3305#ifdef EDQUOT
3306 case EDQUOT: return WSAEDQUOT;
3307#endif
Alexandre Julliard349a9531997-02-02 19:01:52 +00003308#ifdef ESTALE
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003309 case ESTALE: return WSAESTALE;
Alexandre Julliard349a9531997-02-02 19:01:52 +00003310#endif
3311#ifdef EREMOTE
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003312 case EREMOTE: return WSAEREMOTE;
Alexandre Julliard349a9531997-02-02 19:01:52 +00003313#endif
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003314
3315 /* just in case we ever get here and there are no problems */
3316 case 0: return 0;
3317 default:
Alexandre Julliard61fece01999-06-26 19:09:08 +00003318 WARN("Unknown errno %d!\n", loc_errno);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003319 return WSAEOPNOTSUPP;
3320 }
3321}
3322
Rein Klazesff7a61f2000-09-24 19:41:57 +00003323UINT16 wsaHerrno(int loc_errno)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003324{
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003325
Alexandre Julliard61fece01999-06-26 19:09:08 +00003326 WARN("h_errno %d.\n", loc_errno);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003327
3328 switch(loc_errno)
3329 {
3330 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3331 case TRY_AGAIN: return WSATRY_AGAIN;
3332 case NO_RECOVERY: return WSANO_RECOVERY;
3333 case NO_DATA: return WSANO_DATA;
Rein Klazesff7a61f2000-09-24 19:41:57 +00003334 case ENOBUFS: return WSAENOBUFS;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003335
3336 case 0: return 0;
3337 default:
Alexandre Julliard61fece01999-06-26 19:09:08 +00003338 WARN("Unknown h_errno %d!\n", loc_errno);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00003339 return WSAEOPNOTSUPP;
3340 }
3341}