Added the DFCS_{HOT,TRANSPARENT} definitions.
[wine/gsoc_dplay.git] / dlls / winsock / socket.c
blobc1b99c6299c57a38df992d39306cb1f4f183bd13
1 /*
2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
4 *
5 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * NOTE: If you make any changes to fix a particular app, make sure
22 * they don't break something else like Netscape or telnet and ftp
23 * clients and servers (www.winsite.com got a lot of those).
26 #include "config.h"
27 #include "wine/port.h"
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #ifdef HAVE_SYS_IPC_H
33 # include <sys/ipc.h>
34 #endif
35 #include <sys/ioctl.h>
36 #ifdef HAVE_SYS_FILIO_H
37 # include <sys/filio.h>
38 #endif
39 #ifdef HAVE_SYS_SOCKIO_H
40 # include <sys/sockio.h>
41 #endif
43 #if defined(__EMX__)
44 # include <sys/so_ioctl.h>
45 #endif
47 #ifdef HAVE_SYS_PARAM_H
48 # include <sys/param.h>
49 #endif
51 #ifdef HAVE_SYS_MSG_H
52 # include <sys/msg.h>
53 #endif
54 #ifdef HAVE_SYS_WAIT_H
55 # include <sys/wait.h>
56 #endif
57 #ifdef HAVE_SYS_SOCKET_H
58 #include <sys/socket.h>
59 #endif
60 #ifdef HAVE_NETINET_IN_H
61 # include <netinet/in.h>
62 #endif
63 #ifdef HAVE_NETINET_TCP_H
64 # include <netinet/tcp.h>
65 #endif
66 #ifdef HAVE_ARPA_INET_H
67 # include <arpa/inet.h>
68 #endif
69 #include <ctype.h>
70 #include <fcntl.h>
71 #include <errno.h>
72 #ifdef HAVE_SYS_ERRNO_H
73 #include <sys/errno.h>
74 #endif
75 #ifdef HAVE_NETDB_H
76 #include <netdb.h>
77 #endif
78 #include <unistd.h>
79 #include <stdlib.h>
80 #ifdef HAVE_ARPA_NAMESER_H
81 # include <arpa/nameser.h>
82 #endif
83 #ifdef HAVE_RESOLV_H
84 # include <resolv.h>
85 #endif
86 #ifdef HAVE_NET_IF_H
87 # include <net/if.h>
88 #endif
89 #ifdef HAVE_IPX_GNU
90 # include <netipx/ipx.h>
91 # define HAVE_IPX
92 #endif
93 #ifdef HAVE_IPX_LINUX
94 # include <asm/types.h>
95 # include <linux/ipx.h>
96 # define HAVE_IPX
97 #endif
99 #ifdef HAVE_SYS_TIME_H
100 # include <sys/time.h>
101 #endif
103 #include "wine/winbase16.h"
104 #include "wingdi.h"
105 #include "winuser.h"
106 #include "winsock2.h"
107 #include "ws2tcpip.h"
108 #include "wsipx.h"
109 #include "wine/winsock16.h"
110 #include "winnt.h"
111 #include "wine/server.h"
112 #include "wine/debug.h"
115 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
117 /* critical section to protect some non-rentrant net function */
118 extern CRITICAL_SECTION csWSgetXXXbyYYY;
120 #define DEBUG_SOCKADDR 0
121 #define dump_sockaddr(a) \
122 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
123 ((struct sockaddr_in *)a)->sin_family, \
124 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
125 ntohs(((struct sockaddr_in *)a)->sin_port))
127 /* ----------------------------------- internal data */
129 /* ws_... struct conversion flags */
131 #define WS_DUP_LINEAR 0x0001
132 #define WS_DUP_SEGPTR 0x0002 /* internal pointers are SEGPTRs */
133 /* by default, internal pointers are linear */
134 typedef struct /* WSAAsyncSelect() control struct */
136 HANDLE service, event, sock;
137 HWND hWnd;
138 UINT uMsg;
139 LONG lEvent;
140 } ws_select_info;
142 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
143 #define WS_MAX_UDP_DATAGRAM 1024
145 #define PROCFS_NETDEV_FILE "/proc/net/dev" /* Points to the file in the /proc fs
146 that lists the network devices.
147 Do we need an #ifdef LINUX for this? */
149 static void *he_buffer; /* typecast for Win16/32 ws_hostent */
150 static SEGPTR he_buffer_seg;
151 static void *se_buffer; /* typecast for Win16/32 ws_servent */
152 static SEGPTR se_buffer_seg;
153 static void *pe_buffer; /* typecast for Win16/32 ws_protoent */
154 static SEGPTR pe_buffer_seg;
155 static char* local_buffer;
156 static SEGPTR dbuffer_seg;
157 static INT num_startup; /* reference counter */
158 static FARPROC blocking_hook;
160 /* function prototypes */
161 static int WS_dup_he(struct hostent* p_he, int flag);
162 static int WS_dup_pe(struct protoent* p_pe, int flag);
163 static int WS_dup_se(struct servent* p_se, int flag);
165 typedef void WIN_hostent;
166 typedef void WIN_protoent;
167 typedef void WIN_servent;
169 int WSAIOCTL_GetInterfaceCount(void);
170 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
172 UINT16 wsaErrno(void);
173 UINT16 wsaHerrno(int errnr);
175 static HANDLE _WSHeap = 0;
177 #define WS_ALLOC(size) \
178 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
179 #define WS_FREE(ptr) \
180 HeapFree(_WSHeap, 0, (ptr) )
182 static INT _ws_sock_ops[] =
183 { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
184 WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
185 WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE,
186 #ifdef SO_RCVTIMEO
187 WS_SO_RCVTIMEO,
188 #endif
189 #ifdef SO_SNDTIMEO
190 WS_SO_SNDTIMEO,
191 #endif
192 0 };
193 static int _px_sock_ops[] =
194 { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
195 SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
196 #ifdef SO_RCVTIMEO
197 SO_RCVTIMEO,
198 #endif
199 #ifdef SO_SNDTIMEO
200 SO_SNDTIMEO,
201 #endif
204 static INT _ws_tcp_ops[] = {
205 #ifdef TCP_NODELAY
206 WS_TCP_NODELAY,
207 #endif
210 static int _px_tcp_ops[] = {
211 #ifdef TCP_NODELAY
212 TCP_NODELAY,
213 #endif
217 /* Holds value of SO_OPENTYPE socket option. This is essentially a global
218 * variable that Windows uses to affect how new sockets are created. See
219 * <http://support.microsoft.com/default.aspx?scid=kb;EN-US;q181611>. Right
220 * now, Wine does not do anything with this value other than get and set it on
221 * request.
223 static int opentype = 0;
225 /* set last error code from NT status without mapping WSA errors */
226 inline static unsigned int set_error( unsigned int err )
228 if (err)
230 /* do not map WSA errors */
231 if ((err < WSABASEERR) || (err >= 0x10000000)) err = RtlNtStatusToDosError(err);
232 SetLastError( err );
234 return err;
237 static char* check_buffer(int size);
239 inline static int _get_sock_fd(SOCKET s)
241 int fd;
243 if (set_error( wine_server_handle_to_fd( s, GENERIC_READ, &fd, NULL, NULL ) )) return -1;
244 return fd;
247 static void _enable_event(SOCKET s, unsigned int event,
248 unsigned int sstate, unsigned int cstate)
250 SERVER_START_REQ( enable_socket_event )
252 req->handle = s;
253 req->mask = event;
254 req->sstate = sstate;
255 req->cstate = cstate;
256 wine_server_call( req );
258 SERVER_END_REQ;
261 static int _is_blocking(SOCKET s)
263 int ret;
264 SERVER_START_REQ( get_socket_event )
266 req->handle = s;
267 req->service = FALSE;
268 req->c_event = 0;
269 wine_server_call( req );
270 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
272 SERVER_END_REQ;
273 return ret;
276 static unsigned int _get_sock_mask(SOCKET s)
278 unsigned int ret;
279 SERVER_START_REQ( get_socket_event )
281 req->handle = s;
282 req->service = FALSE;
283 req->c_event = 0;
284 wine_server_call( req );
285 ret = reply->mask;
287 SERVER_END_REQ;
288 return ret;
291 static void _sync_sock_state(SOCKET s)
293 /* do a dummy wineserver request in order to let
294 the wineserver run through its select loop once */
295 (void)_is_blocking(s);
298 static int _get_sock_error(SOCKET s, unsigned int bit)
300 int events[FD_MAX_EVENTS];
302 SERVER_START_REQ( get_socket_event )
304 req->handle = s;
305 req->service = FALSE;
306 req->c_event = 0;
307 wine_server_set_reply( req, events, sizeof(events) );
308 wine_server_call( req );
310 SERVER_END_REQ;
311 return events[bit];
314 static void WINSOCK_DeleteIData(void)
316 /* delete scratch buffers */
318 UnMapLS( he_buffer_seg );
319 UnMapLS( se_buffer_seg );
320 UnMapLS( pe_buffer_seg );
321 UnMapLS( dbuffer_seg );
322 if (he_buffer) HeapFree( GetProcessHeap(), 0, he_buffer );
323 if (se_buffer) HeapFree( GetProcessHeap(), 0, se_buffer );
324 if (pe_buffer) HeapFree( GetProcessHeap(), 0, pe_buffer );
325 if (local_buffer) HeapFree( GetProcessHeap(), 0, local_buffer );
326 he_buffer = NULL;
327 se_buffer = NULL;
328 pe_buffer = NULL;
329 local_buffer = NULL;
330 he_buffer_seg = 0;
331 se_buffer_seg = 0;
332 pe_buffer_seg = 0;
333 dbuffer_seg = 0;
334 num_startup = 0;
337 /***********************************************************************
338 * WS_LibMain (WS2_32.init)
340 BOOL WINAPI WS_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
342 TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
343 switch (fdwReason) {
344 case DLL_PROCESS_DETACH:
345 WINSOCK_DeleteIData();
346 break;
348 return TRUE;
351 /***********************************************************************
352 * convert_sockopt()
354 * Converts socket flags from Windows format.
355 * Return 1 if converted, 0 if not (error).
357 static int convert_sockopt(INT *level, INT *optname)
359 int i;
360 switch (*level)
362 case WS_SOL_SOCKET:
363 *level = SOL_SOCKET;
364 for(i=0; _ws_sock_ops[i]; i++)
365 if( _ws_sock_ops[i] == *optname ) break;
366 if( _ws_sock_ops[i] ) {
367 *optname = _px_sock_ops[i];
368 return 1;
370 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
371 break;
372 case WS_IPPROTO_TCP:
373 *level = IPPROTO_TCP;
374 for(i=0; _ws_tcp_ops[i]; i++)
375 if ( _ws_tcp_ops[i] == *optname ) break;
376 if( _ws_tcp_ops[i] ) {
377 *optname = _px_tcp_ops[i];
378 return 1;
380 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
381 break;
383 return 0;
386 /* ----------------------------------- Per-thread info (or per-process?) */
388 static int wsi_strtolo(const char* name, const char* opt)
390 /* Stuff a lowercase copy of the string into the local buffer */
392 int i = strlen(name) + 2;
393 char* p = check_buffer(i + ((opt)?strlen(opt):0));
395 if( p )
397 do *p++ = tolower(*name); while(*name++);
398 i = (p - local_buffer);
399 if( opt ) do *p++ = tolower(*opt); while(*opt++);
400 return i;
402 return 0;
405 static fd_set* fd_set_import( fd_set* fds, void* wsfds, int* highfd, int lfd[], BOOL b32 )
407 /* translate Winsock fd set into local fd set */
409 if( wsfds )
411 #define wsfds16 ((ws_fd_set16*)wsfds)
412 #define wsfds32 ((WS_fd_set*)wsfds)
413 int i, count;
415 FD_ZERO(fds);
416 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
418 for( i = 0; i < count; i++ )
420 int s = (b32) ? wsfds32->fd_array[i]
421 : wsfds16->fd_array[i];
422 int fd = _get_sock_fd(s);
423 if (fd != -1)
425 lfd[ i ] = fd;
426 if( fd > *highfd ) *highfd = fd;
427 FD_SET(fd, fds);
429 else lfd[ i ] = -1;
431 #undef wsfds32
432 #undef wsfds16
433 return fds;
435 return NULL;
438 inline static int sock_error_p(int s)
440 unsigned int optval, optlen;
442 optlen = sizeof(optval);
443 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
444 if (optval) WARN("\t[%i] error: %d\n", s, optval);
445 return optval != 0;
448 static int fd_set_export( fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
450 int num_err = 0;
452 /* translate local fd set into Winsock fd set, adding
453 * errors to exceptfds (only if app requested it) */
455 if( wsfds )
457 #define wsfds16 ((ws_fd_set16*)wsfds)
458 #define wsfds32 ((WS_fd_set*)wsfds)
459 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
461 for( i = 0, j = 0; i < count; i++ )
463 if( lfd[i] >= 0 )
465 int fd = lfd[i];
466 if( FD_ISSET(fd, fds) )
468 if ( exceptfds && sock_error_p(fd) )
470 FD_SET(fd, exceptfds);
471 num_err++;
473 else if( b32 )
474 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
475 else
476 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
478 close(fd);
479 lfd[i] = -1;
483 if( b32 ) wsfds32->fd_count = j;
484 else wsfds16->fd_count = j;
486 TRACE("\n");
487 #undef wsfds32
488 #undef wsfds16
490 return num_err;
493 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
495 if ( wsfds )
497 #define wsfds16 ((ws_fd_set16*)wsfds)
498 #define wsfds32 ((WS_fd_set*)wsfds)
499 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
501 for( i = 0; i < count; i++ )
502 if ( lfd[i] >= 0 )
503 close(lfd[i]);
505 TRACE("\n");
506 #undef wsfds32
507 #undef wsfds16
511 static int do_block( int fd, int mask )
513 fd_set fds[3];
514 int i, r;
516 FD_ZERO(&fds[0]);
517 FD_ZERO(&fds[1]);
518 FD_ZERO(&fds[2]);
519 for (i=0; i<3; i++)
520 if (mask & (1<<i))
521 FD_SET(fd, &fds[i]);
522 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
523 if (i <= 0) return -1;
524 r = 0;
525 for (i=0; i<3; i++)
526 if (FD_ISSET(fd, &fds[i]))
527 r |= 1<<i;
528 return r;
531 void* __ws_memalloc( int size )
533 return WS_ALLOC(size);
536 void __ws_memfree(void* ptr)
538 WS_FREE(ptr);
542 /* ----------------------------------- API -----
544 * Init / cleanup / error checking.
547 /***********************************************************************
548 * WSAStartup (WINSOCK.115)
550 * Create socket control struct, attach it to the global list and
551 * update a pointer in the task struct.
553 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA16 lpWSAData)
555 static const WSADATA16 data =
557 0x0101, 0x0101,
558 "WINE Sockets 1.1",
559 #ifdef linux
560 "Linux/i386",
561 #elif defined(__NetBSD__)
562 "NetBSD/i386",
563 #elif defined(sunos)
564 "SunOS",
565 #elif defined(__FreeBSD__)
566 "FreeBSD",
567 #elif defined(__OpenBSD__)
568 "OpenBSD/i386",
569 #else
570 "Unknown",
571 #endif
572 WS_MAX_SOCKETS_PER_PROCESS,
573 WS_MAX_UDP_DATAGRAM,
577 TRACE("verReq=%x\n", wVersionRequested);
579 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
580 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
582 if (!lpWSAData) return WSAEINVAL;
584 /* initialize socket heap */
586 if( !_WSHeap )
588 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
589 if( !_WSHeap )
591 ERR("Fatal: failed to create WinSock heap\n");
592 return 0;
595 if( _WSHeap == 0 ) return WSASYSNOTREADY;
597 num_startup++;
599 /* return winsock information */
601 memcpy(lpWSAData, &data, sizeof(data));
603 TRACE("succeeded\n");
604 return 0;
607 /***********************************************************************
608 * WSAStartup (WS2_32.115)
610 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
612 static const WSADATA data =
614 0x0202, 0x0202,
615 "WINE Sockets 2.0",
616 #ifdef linux
617 "Linux",
618 #elif defined(__NetBSD__)
619 "NetBSD",
620 #elif defined(sunos)
621 "SunOS",
622 #elif defined(__FreeBSD__)
623 "FreeBSD",
624 #elif defined(__OpenBSD__)
625 "OpenBSD",
626 #else
627 "Unknown",
628 #endif
629 WS_MAX_SOCKETS_PER_PROCESS,
630 WS_MAX_UDP_DATAGRAM,
631 NULL
634 TRACE("verReq=%x\n", wVersionRequested);
636 if (LOBYTE(wVersionRequested) < 1)
637 return WSAVERNOTSUPPORTED;
639 if (!lpWSAData) return WSAEINVAL;
641 /* initialize socket heap */
643 if( !_WSHeap )
645 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
646 if( !_WSHeap )
648 ERR("Fatal: failed to create WinSock heap\n");
649 return 0;
652 if( _WSHeap == 0 ) return WSASYSNOTREADY;
654 num_startup++;
656 /* return winsock information */
657 memcpy(lpWSAData, &data, sizeof(data));
659 /* that's the whole of the negotiation for now */
660 lpWSAData->wVersion = wVersionRequested;
662 TRACE("succeeded\n");
663 return 0;
667 /***********************************************************************
668 * WSACleanup (WINSOCK.116)
669 * WSACleanup (WS2_32.116)
671 INT WINAPI WSACleanup(void)
673 if (num_startup)
675 if (--num_startup > 0) return 0;
676 WINSOCK_DeleteIData();
677 return 0;
679 SetLastError(WSANOTINITIALISED);
680 return SOCKET_ERROR;
684 /***********************************************************************
685 * WSAGetLastError (WINSOCK.111)
686 * WSAGetLastError (WS2_32.111)
688 INT WINAPI WSAGetLastError(void)
690 return GetLastError();
693 /***********************************************************************
694 * WSASetLastError (WS2_32.112)
696 void WINAPI WSASetLastError(INT iError) {
697 SetLastError(iError);
700 /***********************************************************************
701 * WSASetLastError (WINSOCK.112)
703 void WINAPI WSASetLastError16(INT16 iError)
705 WSASetLastError(iError);
708 static char* check_buffer(int size)
710 static int local_buflen;
712 if (local_buffer)
714 if (local_buflen >= size ) return local_buffer;
715 HeapFree( GetProcessHeap(), 0, local_buffer );
717 local_buffer = HeapAlloc( GetProcessHeap(), 0, (local_buflen = size) );
718 return local_buffer;
721 static struct ws_hostent* check_buffer_he(int size)
723 static int he_len;
724 if (he_buffer)
726 if (he_len >= size ) return he_buffer;
727 UnMapLS( he_buffer_seg );
728 HeapFree( GetProcessHeap(), 0, he_buffer );
730 he_buffer = HeapAlloc( GetProcessHeap(), 0, (he_len = size) );
731 he_buffer_seg = MapLS( he_buffer );
732 return he_buffer;
735 static void* check_buffer_se(int size)
737 static int se_len;
738 if (se_buffer)
740 if (se_len >= size ) return se_buffer;
741 UnMapLS( se_buffer_seg );
742 HeapFree( GetProcessHeap(), 0, se_buffer );
744 se_buffer = HeapAlloc( GetProcessHeap(), 0, (se_len = size) );
745 se_buffer_seg = MapLS( he_buffer );
746 return se_buffer;
749 static struct ws_protoent* check_buffer_pe(int size)
751 static int pe_len;
752 if (pe_buffer)
754 if (pe_len >= size ) return pe_buffer;
755 UnMapLS( pe_buffer_seg );
756 HeapFree( GetProcessHeap(), 0, pe_buffer );
758 pe_buffer = HeapAlloc( GetProcessHeap(), 0, (pe_len = size) );
759 pe_buffer_seg = MapLS( he_buffer );
760 return pe_buffer;
763 /* ----------------------------------- i/o APIs */
765 #ifdef HAVE_IPX
766 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
767 #else
768 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
769 #endif
772 /**********************************************************************/
774 /* Returns the converted address if successful, NULL if it was too small to
775 * start with. Note that the returned pointer may be the original pointer
776 * if no conversion is necessary.
778 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
780 switch (wsaddr->sa_family)
782 #ifdef HAVE_IPX
783 case WS_AF_IPX:
785 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
786 struct sockaddr_ipx* uipx;
788 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
789 return NULL;
791 *uaddrlen=sizeof(struct sockaddr_ipx);
792 uipx=malloc(*uaddrlen);
793 uipx->sipx_family=AF_IPX;
794 uipx->sipx_port=wsipx->sa_socket;
795 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
796 * in one go
798 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
799 uipx->sipx_type=IPX_FRAME_NONE;
800 uipx->sipx_zero=0;
801 return (const struct sockaddr*)uipx;
803 #endif
805 default:
806 if (wsaddrlen<sizeof(struct WS_sockaddr))
807 return NULL;
809 /* No conversion needed, just return the original address */
810 *uaddrlen=wsaddrlen;
811 return (const struct sockaddr*)wsaddr;
813 return NULL;
816 /* allocates a Unix sockaddr structure to receive the data */
817 inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
819 if (wsaddr==NULL)
820 return NULL;
821 if (*wsaddrlen==0)
822 *uaddrlen=0;
823 else
824 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
826 return malloc(*uaddrlen);
829 /* Returns 0 if successful, -1 if the buffer is too small */
830 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
832 int res;
834 switch(uaddr->sa_family)
836 #ifdef HAVE_IPX
837 case AF_IPX:
839 struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
840 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
842 res=-1;
843 switch (*wsaddrlen) /* how much can we copy? */
845 default:
846 res=0; /* enough */
847 *wsaddrlen=uaddrlen;
848 wsipx->sa_socket=uipx->sipx_port;
849 /* fall through */
850 case 13:
851 case 12:
852 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
853 /* fall through */
854 case 11:
855 case 10:
856 case 9:
857 case 8:
858 case 7:
859 case 6:
860 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
861 /* fall through */
862 case 5:
863 case 4:
864 case 3:
865 case 2:
866 wsipx->sa_family=WS_AF_IPX;
867 /* fall through */
868 case 1:
869 case 0:
870 /* way too small */
871 break;
874 break;
875 #endif
877 default:
878 /* No conversion needed */
879 memcpy(wsaddr,uaddr,*wsaddrlen);
880 if (*wsaddrlen<uaddrlen) {
881 res=-1;
882 } else {
883 *wsaddrlen=uaddrlen;
884 res=0;
887 return res;
890 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
891 * ws_sockaddr_alloc
893 inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
895 if (uaddr!=NULL && uaddr!=(const struct sockaddr*)wsaddr)
896 free((void*)uaddr);
899 /***********************************************************************
900 * accept (WS2_32.1)
902 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
903 int *addrlen32)
905 int fd = _get_sock_fd(s);
907 TRACE("socket %04x\n", (UINT16)s );
908 if (fd != -1)
910 SOCKET as;
911 if (_is_blocking(s))
913 /* block here */
914 do_block(fd, 5);
915 _sync_sock_state(s); /* let wineserver notice connection */
916 /* retrieve any error codes from it */
917 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
918 /* FIXME: care about the error? */
920 close(fd);
921 SERVER_START_REQ( accept_socket )
923 req->lhandle = s;
924 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
925 req->inherit = TRUE;
926 set_error( wine_server_call( req ) );
927 as = (SOCKET)reply->handle;
929 SERVER_END_REQ;
930 if (as)
932 WS_getpeername(as, addr, addrlen32);
933 return as;
936 else
938 SetLastError(WSAENOTSOCK);
940 return INVALID_SOCKET;
943 /***********************************************************************
944 * accept (WINSOCK.1)
946 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct WS_sockaddr* addr,
947 INT16* addrlen16 )
949 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
950 SOCKET retSocket = WS_accept( s, addr, &addrlen32 );
951 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
952 return (SOCKET16)retSocket;
955 /***********************************************************************
956 * bind (WS2_32.2)
958 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
960 int fd = _get_sock_fd(s);
961 int res;
963 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
964 #if DEBUG_SOCKADDR
965 dump_sockaddr(name);
966 #endif
968 res=SOCKET_ERROR;
969 if (fd != -1)
971 if (!name || !SUPPORTED_PF(name->sa_family))
973 SetLastError(WSAEAFNOSUPPORT);
975 else
977 const struct sockaddr* uaddr;
978 int uaddrlen;
980 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
981 if (uaddr == NULL)
983 SetLastError(WSAEFAULT);
985 else
987 if (bind(fd, uaddr, uaddrlen) < 0)
989 int loc_errno = errno;
990 WARN("\tfailure - errno = %i\n", errno);
991 errno = loc_errno;
992 switch (errno)
994 case EBADF:
995 SetLastError(WSAENOTSOCK);
996 break;
997 case EADDRNOTAVAIL:
998 SetLastError(WSAEINVAL);
999 break;
1000 default:
1001 SetLastError(wsaErrno());
1002 break;
1005 else
1007 res=0; /* success */
1009 ws_sockaddr_free(uaddr,name);
1012 close(fd);
1014 else
1016 SetLastError(WSAENOTSOCK);
1018 return res;
1021 /***********************************************************************
1022 * bind (WINSOCK.2)
1024 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1026 return (INT16)WS_bind( s, name, namelen );
1029 /***********************************************************************
1030 * closesocket (WS2_32.3)
1032 int WINAPI WS_closesocket(SOCKET s)
1034 TRACE("socket %08x\n", s);
1035 if (CloseHandle(s)) return 0;
1036 return SOCKET_ERROR;
1039 /***********************************************************************
1040 * closesocket (WINSOCK.3)
1042 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
1044 return (INT16)WS_closesocket(s);
1047 /***********************************************************************
1048 * connect (WS2_32.4)
1050 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1052 int fd = _get_sock_fd(s);
1054 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
1055 #if DEBUG_SOCKADDR
1056 dump_sockaddr(name);
1057 #endif
1059 if (fd != -1)
1061 const struct sockaddr* uaddr;
1062 int uaddrlen;
1064 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1065 if (uaddr == NULL)
1067 SetLastError(WSAEFAULT);
1069 else
1071 int rc;
1073 rc=connect(fd, uaddr, uaddrlen);
1074 ws_sockaddr_free(uaddr,name);
1075 if (rc == 0)
1076 goto connect_success;
1079 if (errno == EINPROGRESS)
1081 /* tell wineserver that a connection is in progress */
1082 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1083 FD_CONNECT|FD_READ|FD_WRITE,
1084 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1085 if (_is_blocking(s))
1087 int result;
1088 /* block here */
1089 do_block(fd, 7);
1090 _sync_sock_state(s); /* let wineserver notice connection */
1091 /* retrieve any error codes from it */
1092 result = _get_sock_error(s, FD_CONNECT_BIT);
1093 if (result)
1094 SetLastError(result);
1095 else
1097 goto connect_success;
1100 else
1102 SetLastError(WSAEWOULDBLOCK);
1105 else
1107 SetLastError(wsaErrno());
1109 close(fd);
1111 else
1113 SetLastError(WSAENOTSOCK);
1115 return SOCKET_ERROR;
1117 connect_success:
1118 close(fd);
1119 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1120 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1121 FD_CONNECT|FD_WINE_LISTENING);
1122 return 0;
1125 /***********************************************************************
1126 * connect (WINSOCK.4)
1128 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1130 return (INT16)WS_connect( s, name, namelen );
1133 /***********************************************************************
1134 * getpeername (WS2_32.5)
1136 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1138 int fd = _get_sock_fd(s);
1139 int res;
1141 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1143 res=SOCKET_ERROR;
1144 if (fd != -1)
1146 struct sockaddr* uaddr;
1147 int uaddrlen;
1149 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1150 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1152 SetLastError(wsaErrno());
1154 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1156 /* The buffer was too small */
1157 SetLastError(WSAEFAULT);
1159 else
1161 res=0;
1163 ws_sockaddr_free(uaddr,name);
1164 close(fd);
1166 else
1168 SetLastError(WSAENOTSOCK);
1170 return res;
1173 /***********************************************************************
1174 * getpeername (WINSOCK.5)
1176 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct WS_sockaddr *name,
1177 INT16 *namelen16)
1179 INT namelen32 = *namelen16;
1180 INT retVal = WS_getpeername( s, name, &namelen32 );
1182 #if DEBUG_SOCKADDR
1183 dump_sockaddr(name);
1184 #endif
1186 *namelen16 = namelen32;
1187 return (INT16)retVal;
1190 /***********************************************************************
1191 * getsockname (WS2_32.6)
1193 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1195 int fd = _get_sock_fd(s);
1196 int res;
1198 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1200 res=SOCKET_ERROR;
1201 if (fd != -1)
1203 struct sockaddr* uaddr;
1204 int uaddrlen;
1206 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1207 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1209 SetLastError(wsaErrno());
1211 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1213 /* The buffer was too small */
1214 SetLastError(WSAEFAULT);
1216 else
1218 res=0;
1220 close(fd);
1222 else
1224 SetLastError(WSAENOTSOCK);
1226 return res;
1229 /***********************************************************************
1230 * getsockname (WINSOCK.6)
1232 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct WS_sockaddr *name,
1233 INT16 *namelen16)
1235 INT retVal;
1237 if( namelen16 )
1239 INT namelen32 = *namelen16;
1240 retVal = WS_getsockname( s, name, &namelen32 );
1241 *namelen16 = namelen32;
1243 #if DEBUG_SOCKADDR
1244 dump_sockaddr(name);
1245 #endif
1248 else retVal = SOCKET_ERROR;
1249 return (INT16)retVal;
1253 /***********************************************************************
1254 * getsockopt (WS2_32.7)
1256 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1257 INT optname, char *optval, INT *optlen)
1259 int fd;
1261 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1262 (int) optname, (int) optval, (int) *optlen);
1263 /* SO_OPENTYPE does not require a valid socket handle. */
1264 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1266 if (!optlen || *optlen < sizeof(int) || !optval)
1268 SetLastError(WSAEFAULT);
1269 return SOCKET_ERROR;
1271 *(int *)optval = opentype;
1272 *optlen = sizeof(int);
1273 TRACE("getting global SO_OPENTYPE = 0x%x\n", opentype);
1274 return 0;
1277 fd = _get_sock_fd(s);
1278 if (fd != -1)
1280 if (!convert_sockopt(&level, &optname)) {
1281 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1282 } else {
1283 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1285 close(fd);
1286 return 0;
1288 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1290 close(fd);
1292 return SOCKET_ERROR;
1296 /***********************************************************************
1297 * getsockopt (WINSOCK.7)
1299 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1300 INT16 optname, char *optval, INT16 *optlen)
1302 INT optlen32;
1303 INT *p = &optlen32;
1304 INT retVal;
1305 if( optlen ) optlen32 = *optlen; else p = NULL;
1306 retVal = WS_getsockopt( s, (UINT16)level, optname, optval, p );
1307 if( optlen ) *optlen = optlen32;
1308 return (INT16)retVal;
1312 /***********************************************************************
1313 * htonl (WINSOCK.8)
1314 * htonl (WS2_32.8)
1316 u_long WINAPI WS_htonl(u_long hostlong)
1318 return htonl(hostlong);
1322 /***********************************************************************
1323 * htons (WINSOCK.9)
1324 * htons (WS2_32.9)
1326 u_short WINAPI WS_htons(u_short hostshort)
1328 return htons(hostshort);
1332 /***********************************************************************
1333 * inet_addr (WINSOCK.10)
1334 * inet_addr (WS2_32.11)
1336 u_long WINAPI WS_inet_addr(const char *cp)
1338 return inet_addr(cp);
1342 /***********************************************************************
1343 * ntohl (WINSOCK.14)
1344 * ntohl (WS2_32.14)
1346 u_long WINAPI WS_ntohl(u_long netlong)
1348 return ntohl(netlong);
1352 /***********************************************************************
1353 * ntohs (WINSOCK.15)
1354 * ntohs (WS2_32.15)
1356 u_short WINAPI WS_ntohs(u_short netshort)
1358 return ntohs(netshort);
1362 /***********************************************************************
1363 * inet_ntoa (WS2_32.12)
1365 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1367 /* use "buffer for dummies" here because some applications have
1368 * propensity to decode addresses in ws_hostent structure without
1369 * saving them first...
1371 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1373 char* s = inet_ntoa(*((struct in_addr*)&in));
1374 if( s )
1376 strcpy(dbuffer, s);
1377 return dbuffer;
1379 SetLastError(wsaErrno());
1380 return NULL;
1383 /***********************************************************************
1384 * inet_ntoa (WINSOCK.11)
1386 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1388 char* retVal;
1389 if (!(retVal = WS_inet_ntoa(*((struct WS_in_addr*)&in)))) return 0;
1390 if (!dbuffer_seg) dbuffer_seg = MapLS( retVal );
1391 return dbuffer_seg;
1395 /**********************************************************************
1396 * WSAIoctl (WS2_32.50)
1399 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1401 INT WINAPI WSAIoctl (SOCKET s,
1402 DWORD dwIoControlCode,
1403 LPVOID lpvInBuffer,
1404 DWORD cbInBuffer,
1405 LPVOID lpbOutBuffer,
1406 DWORD cbOutBuffer,
1407 LPDWORD lpcbBytesReturned,
1408 LPWSAOVERLAPPED lpOverlapped,
1409 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1411 int fd = _get_sock_fd(s);
1413 if (fd != -1)
1415 switch( dwIoControlCode )
1417 case SIO_GET_INTERFACE_LIST:
1419 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1420 int i, numInt;
1421 struct ifreq ifInfo;
1422 char ifName[512];
1425 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1427 numInt = WSAIOCTL_GetInterfaceCount();
1428 if (numInt < 0)
1430 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1431 close(fd);
1432 WSASetLastError(WSAEINVAL);
1433 return (SOCKET_ERROR);
1436 for (i=0; i<numInt; i++)
1438 if (!WSAIOCTL_GetInterfaceName(i, ifName))
1440 ERR ("Error parsing /proc filesystem!\n");
1441 close(fd);
1442 WSASetLastError(WSAEINVAL);
1443 return (SOCKET_ERROR);
1446 ifInfo.ifr_addr.sa_family = AF_INET;
1448 /* IP Address */
1449 strcpy (ifInfo.ifr_name, ifName);
1450 if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
1452 ERR ("Error obtaining IP address\n");
1453 close(fd);
1454 WSASetLastError(WSAEINVAL);
1455 return (SOCKET_ERROR);
1457 else
1459 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_addr;
1461 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1462 intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1463 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
1466 /* Broadcast Address */
1467 strcpy (ifInfo.ifr_name, ifName);
1468 if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1470 ERR ("Error obtaining Broadcast IP address\n");
1471 close(fd);
1472 WSASetLastError(WSAEINVAL);
1473 return (SOCKET_ERROR);
1475 else
1477 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_broadaddr;
1479 intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
1480 intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
1481 intArray->iiBroadcastAddress.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
1484 /* Subnet Mask */
1485 strcpy (ifInfo.ifr_name, ifName);
1486 if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
1488 ERR ("Error obtaining Subnet IP address\n");
1489 close(fd);
1490 WSASetLastError(WSAEINVAL);
1491 return (SOCKET_ERROR);
1493 else
1495 /* Trying to avoid some compile problems across platforms.
1496 (Linux, FreeBSD, Solaris...) */
1497 #ifndef ifr_netmask
1498 #ifndef ifr_addr
1499 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1500 intArray->iiNetmask.AddressIn.sin_port = 0;
1501 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = 0;
1502 ERR ("Unable to determine Netmask on your platform!\n");
1503 #else
1504 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_addr;
1506 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1507 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1508 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
1509 #endif
1510 #else
1511 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_netmask;
1513 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1514 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1515 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
1516 #endif
1519 /* Socket Status Flags */
1520 strcpy(ifInfo.ifr_name, ifName);
1521 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1523 ERR ("Error obtaining status flags for socket!\n");
1524 close(fd);
1525 WSASetLastError(WSAEINVAL);
1526 return (SOCKET_ERROR);
1528 else
1530 /* FIXME - Is this the right flag to use? */
1531 intArray->iiFlags = ifInfo.ifr_flags;
1533 intArray++; /* Prepare for another interface */
1536 /* Calculate the size of the array being returned */
1537 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1538 break;
1541 default:
1543 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1544 close(fd);
1545 WSASetLastError(WSAEOPNOTSUPP);
1546 return (SOCKET_ERROR);
1550 /* Function executed with no errors */
1551 close(fd);
1552 return (0);
1554 else
1556 WSASetLastError(WSAENOTSOCK);
1557 return (SOCKET_ERROR);
1563 Helper function for WSAIoctl - Get count of the number of interfaces
1564 by parsing /proc filesystem.
1566 int WSAIOCTL_GetInterfaceCount(void)
1568 FILE *procfs;
1569 char buf[512]; /* Size doesn't matter, something big */
1570 int intcnt=0;
1573 /* Open /proc filesystem file for network devices */
1574 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1575 if (!procfs)
1577 /* If we can't open the file, return an error */
1578 return (-1);
1581 /* Omit first two lines, they are only headers */
1582 fgets(buf, sizeof buf, procfs);
1583 fgets(buf, sizeof buf, procfs);
1585 while (fgets(buf, sizeof buf, procfs))
1587 /* Each line in the file represents a network interface */
1588 intcnt++;
1591 fclose(procfs);
1592 return(intcnt);
1597 Helper function for WSAIoctl - Get name of device from interface number
1598 by parsing /proc filesystem.
1600 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
1602 FILE *procfs;
1603 char buf[512]; /* Size doesn't matter, something big */
1604 int i;
1606 /* Open /proc filesystem file for network devices */
1607 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1608 if (!procfs)
1610 /* If we can't open the file, return an error */
1611 return (-1);
1614 /* Omit first two lines, they are only headers */
1615 fgets(buf, sizeof(buf), procfs);
1616 fgets(buf, sizeof(buf), procfs);
1618 for (i=0; i<intNumber; i++)
1620 /* Skip the lines that don't interest us. */
1621 fgets(buf, sizeof(buf), procfs);
1623 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
1626 /* Parse out the line, grabbing only the name of the device
1627 to the intName variable
1629 The Line comes in like this: (we only care about the device name)
1630 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
1632 i=0;
1633 while (isspace(buf[i])) /* Skip initial space(s) */
1635 i++;
1638 while (buf[i])
1640 if (isspace(buf[i]))
1642 break;
1645 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
1647 /* This interface could be an alias... */
1648 int hold = i;
1649 char *dotname = intName;
1650 *intName++ = buf[i++];
1652 while (isdigit(buf[i]))
1654 *intName++ = buf[i++];
1657 if (buf[i] != ':')
1659 /* ... It wasn't, so back up */
1660 i = hold;
1661 intName = dotname;
1664 if (buf[i] == '\0')
1666 fclose(procfs);
1667 return(FALSE);
1670 i++;
1671 break;
1674 *intName++ = buf[i++];
1676 *intName++ = '\0';
1678 fclose(procfs);
1679 return(TRUE);
1683 /***********************************************************************
1684 * ioctlsocket (WS2_32.10)
1686 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
1688 int fd = _get_sock_fd(s);
1690 TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
1691 if (fd != -1)
1693 long newcmd = cmd;
1695 switch( cmd )
1697 case WS_FIONREAD:
1698 newcmd=FIONREAD;
1699 break;
1701 case WS_FIONBIO:
1702 newcmd=FIONBIO;
1703 if( _get_sock_mask(s) )
1705 /* AsyncSelect()'ed sockets are always nonblocking */
1706 if (*argp) {
1707 close(fd);
1708 return 0;
1710 SetLastError(WSAEINVAL);
1711 close(fd);
1712 return SOCKET_ERROR;
1714 close(fd);
1715 if (*argp)
1716 _enable_event(s, 0, FD_WINE_NONBLOCKING, 0);
1717 else
1718 _enable_event(s, 0, 0, FD_WINE_NONBLOCKING);
1719 return 0;
1721 case WS_SIOCATMARK:
1722 newcmd=SIOCATMARK;
1723 break;
1725 case WS__IOW('f',125,u_long):
1726 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1727 SetLastError(WSAEINVAL);
1728 return SOCKET_ERROR;
1730 case SIOCGIFBRDADDR:
1731 case SIOCGIFNETMASK:
1732 case SIOCGIFADDR:
1733 /* These don't need any special handling. They are used by
1734 WsControl, and are here to suppress an unecessary warning. */
1735 break;
1738 default:
1739 /* Netscape tries hard to use bogus ioctl 0x667e */
1740 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1742 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1744 close(fd);
1745 return 0;
1747 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1748 close(fd);
1750 return SOCKET_ERROR;
1753 /***********************************************************************
1754 * ioctlsocket (WINSOCK.12)
1756 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
1758 return (INT16)WS_ioctlsocket( s, cmd, argp );
1762 /***********************************************************************
1763 * listen (WS2_32.13)
1765 int WINAPI WS_listen(SOCKET s, int backlog)
1767 int fd = _get_sock_fd(s);
1769 TRACE("socket %04x, backlog %d\n", s, backlog);
1770 if (fd != -1)
1772 if (listen(fd, backlog) == 0)
1774 close(fd);
1775 _enable_event(s, FD_ACCEPT,
1776 FD_WINE_LISTENING,
1777 FD_CONNECT|FD_WINE_CONNECTED);
1778 return 0;
1780 SetLastError(wsaErrno());
1782 else SetLastError(WSAENOTSOCK);
1783 return SOCKET_ERROR;
1786 /***********************************************************************
1787 * listen (WINSOCK.13)
1789 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1791 return (INT16)WS_listen( s, backlog );
1795 /***********************************************************************
1796 * recv (WS2_32.16)
1798 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
1800 int fd = _get_sock_fd(s);
1802 TRACE("socket %04x, buf %8x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
1804 if (fd != -1)
1806 INT length;
1808 if (_is_blocking(s))
1810 /* block here */
1811 /* FIXME: OOB and exceptfds? */
1812 do_block(fd, 1);
1814 if ((length = recv(fd, buf, len, flags)) >= 0)
1816 TRACE(" -> %i bytes\n", length);
1818 close(fd);
1819 _enable_event(s, FD_READ, 0, 0);
1820 return length;
1822 SetLastError(wsaErrno());
1823 close(fd);
1825 else SetLastError(WSAENOTSOCK);
1826 WARN(" -> ERROR\n");
1827 return SOCKET_ERROR;
1830 /***********************************************************************
1831 * recv (WINSOCK.16)
1833 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1835 return (INT16)WS_recv( s, buf, len, flags );
1839 /***********************************************************************
1840 * recvfrom (WS2_32.17)
1842 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
1843 struct WS_sockaddr *from, int *fromlen)
1845 int fd = _get_sock_fd(s);
1846 int res;
1848 TRACE("socket %04x, ptr %08x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
1849 #if DEBUG_SOCKADDR
1850 if (from)
1851 dump_sockaddr(from);
1852 else
1853 DPRINTF("from = NULL\n");
1854 #endif
1856 res=SOCKET_ERROR;
1857 if (fd != -1)
1859 struct sockaddr* uaddr;
1860 int uaddrlen;
1861 int length;
1863 if (_is_blocking(s))
1865 /* block here */
1866 /* FIXME: OOB and exceptfds */
1867 do_block(fd, 1);
1870 uaddr=ws_sockaddr_alloc(from,fromlen,&uaddrlen);
1871 length=recvfrom(fd, buf, len, flags, uaddr, &uaddrlen);
1872 if (length < 0)
1874 SetLastError(wsaErrno());
1875 WARN(" -> ERROR\n");
1877 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,from,fromlen) != 0)
1879 /* The from buffer was too small, but we read the data
1880 * anyway. Is that really bad?
1882 SetLastError(WSAEFAULT);
1883 WARN(" -> WSAEFAULT\n");
1885 else
1887 TRACE(" -> %i bytes\n", length);
1888 _enable_event(s, FD_READ, 0, 0);
1889 res=length;
1891 close(fd);
1893 else
1895 SetLastError(WSAENOTSOCK);
1896 WARN(" -> WSAENOTSOCK\n");
1898 return res;
1901 /***********************************************************************
1902 * recvfrom (WINSOCK.17)
1904 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1905 struct WS_sockaddr *from, INT16 *fromlen16)
1907 INT fromlen32;
1908 INT *p = &fromlen32;
1909 INT retVal;
1911 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1912 retVal = WS_recvfrom( s, buf, len, flags, from, p );
1913 if( fromlen16 ) *fromlen16 = fromlen32;
1914 return (INT16)retVal;
1917 /***********************************************************************
1918 * __ws_select
1920 static int __ws_select(BOOL b32,
1921 void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1922 const struct WS_timeval *ws_timeout)
1924 int highfd = 0;
1925 fd_set readfds, writefds, exceptfds;
1926 fd_set *p_read, *p_write, *p_except;
1927 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1928 struct timeval timeout, *timeoutaddr = NULL;
1930 TRACE("read %p, write %p, excp %p timeout %p\n",
1931 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
1933 p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
1934 p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
1935 p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
1936 if (ws_timeout)
1938 timeoutaddr = &timeout;
1939 timeout.tv_sec=ws_timeout->tv_sec;
1940 timeout.tv_usec=ws_timeout->tv_usec;
1943 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
1945 fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
1946 fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
1948 if (p_except && ws_exceptfds)
1950 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1951 #define wsfds32 ((WS_fd_set*)ws_exceptfds)
1952 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1954 for (i = j = 0; i < count; i++)
1956 int fd = exceptfd[i];
1957 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
1959 if( b32 )
1960 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1961 else
1962 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1964 if( fd >= 0 ) close(fd);
1965 exceptfd[i] = -1;
1967 if( b32 )
1968 wsfds32->fd_count = j;
1969 else
1970 wsfds16->fd_count = j;
1971 #undef wsfds32
1972 #undef wsfds16
1974 return highfd;
1976 fd_set_unimport(ws_readfds, readfd, b32);
1977 fd_set_unimport(ws_writefds, writefd, b32);
1978 fd_set_unimport(ws_exceptfds, exceptfd, b32);
1979 if( ws_readfds ) ((WS_fd_set*)ws_readfds)->fd_count = 0;
1980 if( ws_writefds ) ((WS_fd_set*)ws_writefds)->fd_count = 0;
1981 if( ws_exceptfds ) ((WS_fd_set*)ws_exceptfds)->fd_count = 0;
1983 if( highfd == 0 ) return 0;
1984 SetLastError(wsaErrno());
1985 return SOCKET_ERROR;
1988 /***********************************************************************
1989 * select (WINSOCK.18)
1991 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1992 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1993 struct WS_timeval* timeout)
1995 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1998 /***********************************************************************
1999 * select (WS2_32.18)
2001 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2002 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2003 const struct WS_timeval* timeout)
2005 /* struct timeval is the same for both 32- and 16-bit code */
2006 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2010 /***********************************************************************
2011 * send (WS2_32.19)
2013 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2015 int fd = _get_sock_fd(s);
2017 TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
2018 if (fd != -1)
2020 int length;
2022 if (_is_blocking(s))
2024 /* block here */
2025 /* FIXME: exceptfds */
2026 do_block(fd, 2);
2028 if ((length = send(fd, buf, len, flags)) < 0 )
2030 SetLastError(wsaErrno());
2031 if( GetLastError() == WSAEWOULDBLOCK )
2032 _enable_event(s, FD_WRITE, 0, 0);
2034 else
2036 close(fd);
2037 return length;
2039 close(fd);
2041 else SetLastError(WSAENOTSOCK);
2042 return SOCKET_ERROR;
2045 /***********************************************************************
2046 * WSASend (WS2_32.72)
2048 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2049 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2050 LPWSAOVERLAPPED lpOverlapped,
2051 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2053 INT iFlags = 0;
2054 INT rc = 0;
2055 DWORD dwCount;
2057 /* Overlapped is not supported or checked for */
2058 FIXME( "(%u,%p,0x%lx,%p,0x%lx,%p,%p): semi stub\n",
2059 s, lpBuffers, dwBufferCount, lpNumberOfBytesSent,
2060 dwFlags, lpOverlapped, lpCompletionRoutine );
2062 /* Convert setup flags */
2063 if( dwFlags & MSG_DONTROUTE )
2065 iFlags |= MSG_DONTROUTE;
2068 if( dwFlags & MSG_OOB )
2070 iFlags |= MSG_OOB;
2073 /* Indicate nothing yet sent */
2074 *lpNumberOfBytesSent = 0;
2076 /* Send all buffers with the same flags */
2077 for(dwCount = 0; dwCount < dwBufferCount; dwCount++ )
2079 if( ( rc = WS_send( s, lpBuffers[ dwCount ].buf,
2080 lpBuffers[ dwCount ].len, iFlags ) ) != 0 )
2082 break;
2085 /* Indicate that we've sent something */
2086 *lpNumberOfBytesSent += lpBuffers[ dwCount ].len;
2089 return rc;
2092 /***********************************************************************
2093 * send (WINSOCK.19)
2095 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2097 return WS_send( s, buf, len, flags );
2100 /***********************************************************************
2101 * sendto (WS2_32.20)
2103 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2104 const struct WS_sockaddr *to, int tolen)
2106 int fd = _get_sock_fd(s);
2107 int res;
2109 TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
2111 res=SOCKET_ERROR;
2112 if (fd != -1)
2114 const struct sockaddr* uaddr;
2115 int uaddrlen;
2117 uaddr=ws_sockaddr_ws2u(to,tolen,&uaddrlen);
2118 if (uaddr == NULL)
2120 SetLastError(WSAEFAULT);
2122 else
2124 if (_is_blocking(s))
2126 /* block here */
2127 /* FIXME: exceptfds */
2128 do_block(fd, 2);
2130 res=sendto(fd, buf, len, flags, uaddr, uaddrlen);
2131 if (res < 0 )
2133 SetLastError(wsaErrno());
2134 if( GetLastError() == WSAEWOULDBLOCK )
2135 _enable_event(s, FD_WRITE, 0, 0);
2137 ws_sockaddr_free(uaddr,to);
2139 close(fd);
2141 else
2143 SetLastError(WSAENOTSOCK);
2145 return res;
2148 /***********************************************************************
2149 * sendto (WINSOCK.20)
2151 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2152 struct WS_sockaddr *to, INT16 tolen)
2154 return (INT16)WS_sendto( s, buf, len, flags, to, tolen );
2157 /***********************************************************************
2158 * setsockopt (WS2_32.21)
2160 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2161 const char *optval, int optlen)
2163 int fd;
2165 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
2166 (int) optname, (int) optval, optlen);
2167 /* SO_OPENTYPE does not require a valid socket handle. */
2168 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2170 if (optlen < sizeof(int) || !optval)
2172 SetLastError(WSAEFAULT);
2173 return SOCKET_ERROR;
2175 opentype = *(int *)optval;
2176 TRACE("setting global SO_OPENTYPE to 0x%x\n", opentype);
2177 return 0;
2180 fd = _get_sock_fd(s);
2181 if (fd != -1)
2183 struct linger linger;
2184 int woptval;
2186 /* Is a privileged and useless operation, so we don't. */
2187 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
2188 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2189 return 0;
2192 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2193 /* This is unique to WinSock and takes special conversion */
2194 linger.l_onoff = *((int*)optval) ? 0: 1;
2195 linger.l_linger = 0;
2196 optname=SO_LINGER;
2197 optval = (char*)&linger;
2198 optlen = sizeof(struct linger);
2199 level = SOL_SOCKET;
2200 }else{
2201 if (!convert_sockopt(&level, &optname)) {
2202 SetLastError(WSAENOPROTOOPT);
2203 close(fd);
2204 return SOCKET_ERROR;
2206 if (optname == SO_LINGER && optval) {
2207 /* yes, uses unsigned short in both win16/win32 */
2208 linger.l_onoff = ((UINT16*)optval)[0];
2209 linger.l_linger = ((UINT16*)optval)[1];
2210 /* FIXME: what is documented behavior if SO_LINGER optval
2211 is null?? */
2212 optval = (char*)&linger;
2213 optlen = sizeof(struct linger);
2214 } else if (optlen < sizeof(int)){
2215 woptval= *((INT16 *) optval);
2216 optval= (char*) &woptval;
2217 optlen=sizeof(int);
2220 if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2221 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2222 close( fd);
2223 return 0;
2226 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2228 close(fd);
2229 return 0;
2231 SetLastError(wsaErrno());
2232 close(fd);
2234 else SetLastError(WSAENOTSOCK);
2235 return SOCKET_ERROR;
2238 /***********************************************************************
2239 * setsockopt (WINSOCK.21)
2241 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2242 char *optval, INT16 optlen)
2244 if( !optval ) return SOCKET_ERROR;
2245 return (INT16)WS_setsockopt( s, (UINT16)level, optname, optval, optlen );
2249 /***********************************************************************
2250 * shutdown (WS2_32.22)
2252 int WINAPI WS_shutdown(SOCKET s, int how)
2254 int fd = _get_sock_fd(s);
2256 TRACE("socket %04x, how %i\n", s, how );
2257 if (fd != -1)
2259 switch( how )
2261 case 0: /* drop receives */
2262 _enable_event(s, 0, 0, FD_READ);
2263 #ifdef SHUT_RD
2264 how = SHUT_RD;
2265 #endif
2266 break;
2268 case 1: /* drop sends */
2269 _enable_event(s, 0, 0, FD_WRITE);
2270 #ifdef SHUT_WR
2271 how = SHUT_WR;
2272 #endif
2273 break;
2275 case 2: /* drop all */
2276 #ifdef SHUT_RDWR
2277 how = SHUT_RDWR;
2278 #endif
2279 default:
2280 WSAAsyncSelect( s, 0, 0, 0 );
2281 break;
2284 if (shutdown(fd, how) == 0)
2286 if( how > 1 )
2288 _enable_event(s, 0, 0, FD_WINE_CONNECTED|FD_WINE_LISTENING);
2290 close(fd);
2291 return 0;
2293 SetLastError(wsaErrno());
2294 close(fd);
2296 else SetLastError(WSAENOTSOCK);
2297 return SOCKET_ERROR;
2300 /***********************************************************************
2301 * shutdown (WINSOCK.22)
2303 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2305 return (INT16)WS_shutdown( s, how );
2309 /***********************************************************************
2310 * socket (WS2_32.23)
2312 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2314 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2316 /* The Winsock2 specification states that socket() always opens sockets
2317 in overlapped mode.
2318 FIXME: is the SO_OPENTYPE behaviour correct? */
2319 return WSASocketA ( af, type, protocol, NULL, 0, (opentype ? 0 : WSA_FLAG_OVERLAPPED) );
2322 /***********************************************************************
2323 * socket (WINSOCK.23)
2325 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2327 return (SOCKET16)WS_socket( af, type, protocol );
2331 /* ----------------------------------- DNS services
2333 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2334 * Also, we have to use wsock32 stubs to convert structures and
2335 * error codes from Unix to WSA, hence there is no direct mapping in
2336 * the relay32/wsock32.spec.
2340 /***********************************************************************
2341 * __ws_gethostbyaddr
2343 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2345 WIN_hostent *retval = NULL;
2347 struct hostent* host;
2348 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2349 char *extrabuf;
2350 int ebufsize=1024;
2351 struct hostent hostentry;
2352 int locerr=ENOBUFS;
2353 host = NULL;
2354 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2355 while(extrabuf) {
2356 int res = gethostbyaddr_r(addr, len, type,
2357 &hostentry, extrabuf, ebufsize, &host, &locerr);
2358 if( res != ERANGE) break;
2359 ebufsize *=2;
2360 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2362 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2363 #else
2364 EnterCriticalSection( &csWSgetXXXbyYYY );
2365 host = gethostbyaddr(addr, len, type);
2366 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2367 #endif
2368 if( host != NULL )
2370 if( WS_dup_he(host, dup_flag) )
2371 retval = he_buffer;
2372 else
2373 SetLastError(WSAENOBUFS);
2375 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2376 HeapFree(GetProcessHeap(),0,extrabuf);
2377 #else
2378 LeaveCriticalSection( &csWSgetXXXbyYYY );
2379 #endif
2380 return retval;
2383 /***********************************************************************
2384 * gethostbyaddr (WINSOCK.51)
2386 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2388 TRACE("ptr %p, len %d, type %d\n", addr, len, type);
2389 if (!__ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR )) return 0;
2390 return he_buffer_seg;
2393 /***********************************************************************
2394 * gethostbyaddr (WS2_32.51)
2396 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len,
2397 int type)
2399 TRACE("ptr %08x, len %d, type %d\n",
2400 (unsigned) addr, len, type);
2401 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2404 /***********************************************************************
2405 * __ws_gethostbyname
2407 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2409 WIN_hostent *retval = NULL;
2410 struct hostent* host;
2411 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2412 char *extrabuf;
2413 int ebufsize=1024;
2414 struct hostent hostentry;
2415 int locerr = ENOBUFS;
2416 host = NULL;
2417 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2418 while(extrabuf) {
2419 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2420 if( res != ERANGE) break;
2421 ebufsize *=2;
2422 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2424 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2425 #else
2426 EnterCriticalSection( &csWSgetXXXbyYYY );
2427 host = gethostbyname(name);
2428 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2429 #endif
2430 if( host != NULL )
2432 if( WS_dup_he(host, dup_flag) )
2433 retval = he_buffer;
2434 else SetLastError(WSAENOBUFS);
2436 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2437 HeapFree(GetProcessHeap(),0,extrabuf);
2438 #else
2439 LeaveCriticalSection( &csWSgetXXXbyYYY );
2440 #endif
2441 return retval;
2444 /***********************************************************************
2445 * gethostbyname (WINSOCK.52)
2447 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2449 TRACE( "%s\n", debugstr_a(name) );
2450 if (!__ws_gethostbyname( name, WS_DUP_SEGPTR )) return 0;
2451 return he_buffer_seg;
2454 /***********************************************************************
2455 * gethostbyname (WS2_32.52)
2457 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2459 TRACE( "%s\n", debugstr_a(name) );
2460 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2464 /***********************************************************************
2465 * __ws_getprotobyname
2467 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2469 WIN_protoent* retval = NULL;
2471 struct protoent* proto;
2472 EnterCriticalSection( &csWSgetXXXbyYYY );
2473 if( (proto = getprotobyname(name)) != NULL )
2475 if( WS_dup_pe(proto, dup_flag) )
2476 retval = pe_buffer;
2477 else SetLastError(WSAENOBUFS);
2479 else {
2480 MESSAGE("protocol %s not found; You might want to add "
2481 "this to /etc/protocols\n", debugstr_a(name) );
2482 SetLastError(WSANO_DATA);
2484 LeaveCriticalSection( &csWSgetXXXbyYYY );
2485 return retval;
2488 /***********************************************************************
2489 * getprotobyname (WINSOCK.53)
2491 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2493 TRACE( "%s\n", debugstr_a(name) );
2494 if (!__ws_getprotobyname(name, WS_DUP_SEGPTR)) return 0;
2495 return pe_buffer_seg;
2498 /***********************************************************************
2499 * getprotobyname (WS2_32.53)
2501 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
2503 TRACE( "%s\n", debugstr_a(name) );
2504 return __ws_getprotobyname(name, WS_DUP_LINEAR);
2508 /***********************************************************************
2509 * __ws_getprotobynumber
2511 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2513 WIN_protoent* retval = NULL;
2514 struct protoent* proto;
2515 EnterCriticalSection( &csWSgetXXXbyYYY );
2516 if( (proto = getprotobynumber(number)) != NULL )
2518 if( WS_dup_pe(proto, dup_flag) )
2519 retval = pe_buffer;
2520 else SetLastError(WSAENOBUFS);
2522 else {
2523 MESSAGE("protocol number %d not found; You might want to add "
2524 "this to /etc/protocols\n", number );
2525 SetLastError(WSANO_DATA);
2527 LeaveCriticalSection( &csWSgetXXXbyYYY );
2528 return retval;
2531 /***********************************************************************
2532 * getprotobynumber (WINSOCK.54)
2534 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2536 TRACE("%i\n", number);
2537 if (!__ws_getprotobynumber(number, WS_DUP_SEGPTR)) return 0;
2538 return pe_buffer_seg;
2541 /***********************************************************************
2542 * getprotobynumber (WS2_32.54)
2544 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
2546 TRACE("%i\n", number);
2547 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2551 /***********************************************************************
2552 * __ws_getservbyname
2554 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
2556 WIN_servent* retval = NULL;
2557 struct servent* serv;
2558 int i = wsi_strtolo( name, proto );
2560 if( i ) {
2561 EnterCriticalSection( &csWSgetXXXbyYYY );
2562 serv = getservbyname(local_buffer,
2563 proto ? (local_buffer + i) : NULL);
2564 if( serv != NULL )
2566 if( WS_dup_se(serv, dup_flag) )
2567 retval = se_buffer;
2568 else SetLastError(WSAENOBUFS);
2570 else {
2571 MESSAGE("service %s protocol %s not found; You might want to add "
2572 "this to /etc/services\n", debugstr_a(local_buffer),
2573 proto ? debugstr_a(local_buffer+i):"*");
2574 SetLastError(WSANO_DATA);
2576 LeaveCriticalSection( &csWSgetXXXbyYYY );
2578 else SetLastError(WSAENOBUFS);
2579 return retval;
2582 /***********************************************************************
2583 * getservbyname (WINSOCK.55)
2585 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2587 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
2588 if (!__ws_getservbyname(name, proto, WS_DUP_SEGPTR)) return 0;
2589 return se_buffer_seg;
2592 /***********************************************************************
2593 * getservbyname (WS2_32.55)
2595 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
2597 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
2598 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2602 /***********************************************************************
2603 * __ws_getservbyport
2605 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2607 WIN_servent* retval = NULL;
2608 struct servent* serv;
2609 if (!proto || wsi_strtolo( proto, NULL )) {
2610 EnterCriticalSection( &csWSgetXXXbyYYY );
2611 if( (serv = getservbyport(port, (proto) ? local_buffer : NULL)) != NULL ) {
2612 if( WS_dup_se(serv, dup_flag) )
2613 retval = se_buffer;
2614 else SetLastError(WSAENOBUFS);
2616 else {
2617 MESSAGE("service on port %lu protocol %s not found; You might want to add "
2618 "this to /etc/services\n", (unsigned long)ntohl(port),
2619 proto ? debugstr_a(local_buffer) : "*");
2620 SetLastError(WSANO_DATA);
2622 LeaveCriticalSection( &csWSgetXXXbyYYY );
2624 else SetLastError(WSAENOBUFS);
2625 return retval;
2628 /***********************************************************************
2629 * getservbyport (WINSOCK.56)
2631 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2633 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
2634 if (!__ws_getservbyport(port, proto, WS_DUP_SEGPTR)) return 0;
2635 return se_buffer_seg;
2638 /***********************************************************************
2639 * getservbyport (WS2_32.56)
2641 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
2643 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
2644 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2648 /***********************************************************************
2649 * gethostname (WS2_32.57)
2651 int WINAPI WS_gethostname(char *name, int namelen)
2653 TRACE("name %p, len %d\n", name, namelen);
2655 if (gethostname(name, namelen) == 0)
2657 TRACE("<- '%s'\n", name);
2658 return 0;
2660 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2661 TRACE("<- ERROR !\n");
2662 return SOCKET_ERROR;
2665 /***********************************************************************
2666 * gethostname (WINSOCK.57)
2668 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2670 return (INT16)WS_gethostname(name, namelen);
2674 /* ------------------------------------- Windows sockets extensions -- *
2676 * ------------------------------------------------------------------- */
2678 /***********************************************************************
2679 * WSAEnumNetworkEvents (WS2_32.36)
2681 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2683 int ret;
2685 TRACE("%08x, hEvent %08x, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2687 SERVER_START_REQ( get_socket_event )
2689 req->handle = s;
2690 req->service = TRUE;
2691 req->c_event = hEvent;
2692 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
2693 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
2695 SERVER_END_REQ;
2696 if (!ret) return 0;
2697 SetLastError(WSAEINVAL);
2698 return SOCKET_ERROR;
2701 /***********************************************************************
2702 * WSAEventSelect (WS2_32.39)
2704 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2706 int ret;
2708 TRACE("%08x, hEvent %08x, event %08x\n", s, hEvent, (unsigned)lEvent );
2710 SERVER_START_REQ( set_socket_event )
2712 req->handle = s;
2713 req->mask = lEvent;
2714 req->event = hEvent;
2715 req->window = 0;
2716 req->msg = 0;
2717 ret = wine_server_call( req );
2719 SERVER_END_REQ;
2720 if (!ret) return 0;
2721 SetLastError(WSAEINVAL);
2722 return SOCKET_ERROR;
2725 /***********************************************************************
2726 * WSAAsyncSelect (WS2_32.101)
2728 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2730 int ret;
2732 TRACE("%x, hWnd %x, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
2734 SERVER_START_REQ( set_socket_event )
2736 req->handle = s;
2737 req->mask = lEvent;
2738 req->event = 0;
2739 req->window = hWnd;
2740 req->msg = uMsg;
2741 ret = wine_server_call( req );
2743 SERVER_END_REQ;
2744 if (!ret) return 0;
2745 SetLastError(WSAEINVAL);
2746 return SOCKET_ERROR;
2749 /***********************************************************************
2750 * WSAAsyncSelect (WINSOCK.101)
2752 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2754 return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2757 /***********************************************************************
2758 * WSARecvEx (WINSOCK.1107)
2760 * See description for WSARecvEx()
2762 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags)
2764 FIXME("(WSARecvEx16) partial packet return value not set \n");
2766 return WINSOCK_recv16(s, buf, len, *flags);
2770 /***********************************************************************
2771 * WSACreateEvent (WS2_32.31)
2774 WSAEVENT WINAPI WSACreateEvent(void)
2776 /* Create a manual-reset event, with initial state: unsignealed */
2777 TRACE("\n");
2779 return CreateEventA(NULL, TRUE, FALSE, NULL);
2782 /***********************************************************************
2783 * WSACloseEvent (WS2_32.29)
2786 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2788 TRACE ("event=0x%x\n", event);
2790 return CloseHandle(event);
2793 /***********************************************************************
2794 * WSASocketA (WS2_32.78)
2797 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2798 LPWSAPROTOCOL_INFOA lpProtocolInfo,
2799 GROUP g, DWORD dwFlags)
2801 SOCKET ret;
2804 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2805 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
2808 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
2809 af, type, protocol, lpProtocolInfo, g, dwFlags );
2811 /* check the socket family */
2812 switch(af)
2814 #ifdef HAVE_IPX
2815 case WS_AF_IPX: af = AF_IPX;
2816 #endif
2817 case AF_INET:
2818 case AF_UNSPEC:
2819 break;
2820 default:
2821 SetLastError(WSAEAFNOSUPPORT);
2822 return INVALID_SOCKET;
2825 /* check the socket type */
2826 switch(type)
2828 case WS_SOCK_STREAM:
2829 type=SOCK_STREAM;
2830 break;
2831 case WS_SOCK_DGRAM:
2832 type=SOCK_DGRAM;
2833 break;
2834 case WS_SOCK_RAW:
2835 type=SOCK_RAW;
2836 break;
2837 default:
2838 SetLastError(WSAESOCKTNOSUPPORT);
2839 return INVALID_SOCKET;
2842 /* check the protocol type */
2843 if ( protocol < 0 ) /* don't support negative values */
2845 SetLastError(WSAEPROTONOSUPPORT);
2846 return INVALID_SOCKET;
2849 if ( af == AF_UNSPEC) /* did they not specify the address family? */
2850 switch(protocol)
2852 case IPPROTO_TCP:
2853 if (type == SOCK_STREAM) { af = AF_INET; break; }
2854 case IPPROTO_UDP:
2855 if (type == SOCK_DGRAM) { af = AF_INET; break; }
2856 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2859 SERVER_START_REQ( create_socket )
2861 req->family = af;
2862 req->type = type;
2863 req->protocol = protocol;
2864 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2865 req->flags = dwFlags;
2866 req->inherit = TRUE;
2867 set_error( wine_server_call( req ) );
2868 ret = (SOCKET)reply->handle;
2870 SERVER_END_REQ;
2871 if (ret)
2873 TRACE("\tcreated %04x\n", ret );
2874 return ret;
2877 if (GetLastError() == WSAEACCES) /* raw socket denied */
2879 if (type == SOCK_RAW)
2880 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2881 else
2882 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2883 SetLastError(WSAESOCKTNOSUPPORT);
2886 WARN("\t\tfailed!\n");
2887 return INVALID_SOCKET;
2891 /***********************************************************************
2892 * __WSAFDIsSet (WINSOCK.151)
2894 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2896 int i = set->fd_count;
2898 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2900 while (i--)
2901 if (set->fd_array[i] == s) return 1;
2902 return 0;
2905 /***********************************************************************
2906 * __WSAFDIsSet (WS2_32.151)
2908 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
2910 int i = set->fd_count;
2912 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2914 while (i--)
2915 if (set->fd_array[i] == s) return 1;
2916 return 0;
2919 /***********************************************************************
2920 * WSAIsBlocking (WINSOCK.114)
2921 * WSAIsBlocking (WS2_32.114)
2923 BOOL WINAPI WSAIsBlocking(void)
2925 /* By default WinSock should set all its sockets to non-blocking mode
2926 * and poll in PeekMessage loop when processing "blocking" ones. This
2927 * function is supposed to tell if the program is in this loop. Our
2928 * blocking calls are truly blocking so we always return FALSE.
2930 * Note: It is allowed to call this function without prior WSAStartup().
2933 TRACE("\n");
2934 return FALSE;
2937 /***********************************************************************
2938 * WSACancelBlockingCall (WINSOCK.113)
2939 * WSACancelBlockingCall (WS2_32.113)
2941 INT WINAPI WSACancelBlockingCall(void)
2943 TRACE("\n");
2944 return 0;
2948 /***********************************************************************
2949 * WSASetBlockingHook (WINSOCK.109)
2951 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2953 FARPROC16 prev = (FARPROC16)blocking_hook;
2954 blocking_hook = (FARPROC)lpBlockFunc;
2955 TRACE("hook %p\n", lpBlockFunc);
2956 return prev;
2960 /***********************************************************************
2961 * WSASetBlockingHook (WS2_32.109)
2963 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2965 FARPROC prev = blocking_hook;
2966 blocking_hook = lpBlockFunc;
2967 TRACE("hook %p\n", lpBlockFunc);
2968 return prev;
2972 /***********************************************************************
2973 * WSAUnhookBlockingHook (WINSOCK.110)
2975 INT16 WINAPI WSAUnhookBlockingHook16(void)
2977 blocking_hook = NULL;
2978 return 0;
2982 /***********************************************************************
2983 * WSAUnhookBlockingHook (WS2_32.110)
2985 INT WINAPI WSAUnhookBlockingHook(void)
2987 blocking_hook = NULL;
2988 return 0;
2992 /* ----------------------------------- end of API stuff */
2994 /* ----------------------------------- helper functions -
2996 * TODO: Merge WS_dup_..() stuff into one function that
2997 * would operate with a generic structure containing internal
2998 * pointers (via a template of some kind).
3001 static int list_size(char** l, int item_size)
3003 int i,j = 0;
3004 if(l)
3005 { for(i=0;l[i];i++)
3006 j += (item_size) ? item_size : strlen(l[i]) + 1;
3007 j += (i + 1) * sizeof(char*); }
3008 return j;
3011 static int list_dup(char** l_src, char* ref, char* base, int item_size)
3013 /* base is either either equal to ref or 0 or SEGPTR */
3015 char* p = ref;
3016 char** l_to = (char**)ref;
3017 int i,j,k;
3019 for(j=0;l_src[j];j++) ;
3020 p += (j + 1) * sizeof(char*);
3021 for(i=0;i<j;i++)
3022 { l_to[i] = base + (p - ref);
3023 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3024 memcpy(p, l_src[i], k); p += k; }
3025 l_to[i] = NULL;
3026 return (p - ref);
3029 /* ----- hostent */
3031 static int hostent_size(struct hostent* p_he)
3033 int size = 0;
3034 if( p_he )
3035 { size = sizeof(struct hostent);
3036 size += strlen(p_he->h_name) + 1;
3037 size += list_size(p_he->h_aliases, 0);
3038 size += list_size(p_he->h_addr_list, p_he->h_length ); }
3039 return size;
3042 /* duplicate hostent entry
3043 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3044 * Dito for protoent and servent.
3046 static int WS_dup_he(struct hostent* p_he, int flag)
3048 /* Convert hostent structure into ws_hostent so that the data fits
3049 * into local_buffer. Internal pointers can be linear, SEGPTR, or
3050 * relative to local_buffer depending on "flag" value. Returns size
3051 * of the data copied.
3054 int size = hostent_size(p_he);
3055 if( size )
3057 char *p_name,*p_aliases,*p_addr,*p_base,*p;
3058 char *p_to;
3059 struct ws_hostent16 *p_to16;
3060 struct WS_hostent *p_to32;
3062 check_buffer_he(size);
3063 p_to = he_buffer;
3064 p_to16 = he_buffer;
3065 p_to32 = he_buffer;
3067 p = p_to;
3068 p_base = (flag & WS_DUP_SEGPTR) ? (char*)he_buffer_seg : he_buffer;
3069 p += (flag & WS_DUP_SEGPTR) ?
3070 sizeof(struct ws_hostent16) : sizeof(struct WS_hostent);
3071 p_name = p;
3072 strcpy(p, p_he->h_name); p += strlen(p) + 1;
3073 p_aliases = p;
3074 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3075 p_addr = p;
3076 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
3078 if (flag & WS_DUP_SEGPTR) /* Win16 */
3080 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
3081 p_to16->h_length = (INT16)p_he->h_length;
3082 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3083 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3084 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3085 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3087 else /* Win32 */
3089 p_to32->h_addrtype = p_he->h_addrtype;
3090 p_to32->h_length = p_he->h_length;
3091 p_to32->h_name = (p_base + (p_name - p_to));
3092 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3093 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3094 size += (sizeof(struct WS_hostent) - sizeof(struct hostent));
3097 return size;
3100 /* ----- protoent */
3102 static int protoent_size(struct protoent* p_pe)
3104 int size = 0;
3105 if( p_pe )
3106 { size = sizeof(struct protoent);
3107 size += strlen(p_pe->p_name) + 1;
3108 size += list_size(p_pe->p_aliases, 0); }
3109 return size;
3112 static int WS_dup_pe(struct protoent* p_pe, int flag)
3114 int size = protoent_size(p_pe);
3115 if( size )
3117 char *p_to;
3118 struct ws_protoent16 *p_to16;
3119 struct WS_protoent *p_to32;
3120 char *p_name,*p_aliases,*p_base,*p;
3122 check_buffer_pe(size);
3123 p_to = pe_buffer;
3124 p_to16 = pe_buffer;
3125 p_to32 = pe_buffer;
3126 p = p_to;
3127 p_base = (flag & WS_DUP_SEGPTR) ? (char*)pe_buffer_seg : pe_buffer;
3128 p += (flag & WS_DUP_SEGPTR) ?
3129 sizeof(struct ws_protoent16) : sizeof(struct WS_protoent);
3130 p_name = p;
3131 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3132 p_aliases = p;
3133 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3135 if (flag & WS_DUP_SEGPTR) /* Win16 */
3137 p_to16->p_proto = (INT16)p_pe->p_proto;
3138 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3139 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3140 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3142 else /* Win32 */
3144 p_to32->p_proto = p_pe->p_proto;
3145 p_to32->p_name = (p_base) + (p_name - p_to);
3146 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3147 size += (sizeof(struct WS_protoent) - sizeof(struct protoent));
3150 return size;
3153 /* ----- servent */
3155 static int servent_size(struct servent* p_se)
3157 int size = 0;
3158 if( p_se )
3159 { size += sizeof(struct servent);
3160 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3161 size += list_size(p_se->s_aliases, 0); }
3162 return size;
3165 static int WS_dup_se(struct servent* p_se, int flag)
3167 int size = servent_size(p_se);
3168 if( size )
3170 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3171 char *p_to;
3172 struct ws_servent16 *p_to16;
3173 struct WS_servent *p_to32;
3175 check_buffer_se(size);
3176 p_to = se_buffer;
3177 p_to16 = se_buffer;
3178 p_to32 = se_buffer;
3179 p = p_to;
3180 p_base = (flag & WS_DUP_SEGPTR) ? (char*)se_buffer_seg : se_buffer;
3181 p += (flag & WS_DUP_SEGPTR) ?
3182 sizeof(struct ws_servent16) : sizeof(struct WS_servent);
3183 p_name = p;
3184 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3185 p_proto = p;
3186 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3187 p_aliases = p;
3188 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3190 if (flag & WS_DUP_SEGPTR) /* Win16 */
3192 p_to16->s_port = (INT16)p_se->s_port;
3193 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3194 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3195 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3196 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3198 else /* Win32 */
3200 p_to32->s_port = p_se->s_port;
3201 p_to32->s_name = (p_base + (p_name - p_to));
3202 p_to32->s_proto = (p_base + (p_proto - p_to));
3203 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3204 size += (sizeof(struct WS_servent) - sizeof(struct servent));
3207 return size;
3210 /* ----------------------------------- error handling */
3212 UINT16 wsaErrno(void)
3214 int loc_errno = errno;
3215 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3217 switch(loc_errno)
3219 case EINTR: return WSAEINTR;
3220 case EBADF: return WSAEBADF;
3221 case EPERM:
3222 case EACCES: return WSAEACCES;
3223 case EFAULT: return WSAEFAULT;
3224 case EINVAL: return WSAEINVAL;
3225 case EMFILE: return WSAEMFILE;
3226 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3227 case EINPROGRESS: return WSAEINPROGRESS;
3228 case EALREADY: return WSAEALREADY;
3229 case ENOTSOCK: return WSAENOTSOCK;
3230 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3231 case EMSGSIZE: return WSAEMSGSIZE;
3232 case EPROTOTYPE: return WSAEPROTOTYPE;
3233 case ENOPROTOOPT: return WSAENOPROTOOPT;
3234 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3235 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3236 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3237 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3238 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3239 case EADDRINUSE: return WSAEADDRINUSE;
3240 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3241 case ENETDOWN: return WSAENETDOWN;
3242 case ENETUNREACH: return WSAENETUNREACH;
3243 case ENETRESET: return WSAENETRESET;
3244 case ECONNABORTED: return WSAECONNABORTED;
3245 case EPIPE:
3246 case ECONNRESET: return WSAECONNRESET;
3247 case ENOBUFS: return WSAENOBUFS;
3248 case EISCONN: return WSAEISCONN;
3249 case ENOTCONN: return WSAENOTCONN;
3250 case ESHUTDOWN: return WSAESHUTDOWN;
3251 case ETOOMANYREFS: return WSAETOOMANYREFS;
3252 case ETIMEDOUT: return WSAETIMEDOUT;
3253 case ECONNREFUSED: return WSAECONNREFUSED;
3254 case ELOOP: return WSAELOOP;
3255 case ENAMETOOLONG: return WSAENAMETOOLONG;
3256 case EHOSTDOWN: return WSAEHOSTDOWN;
3257 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3258 case ENOTEMPTY: return WSAENOTEMPTY;
3259 #ifdef EPROCLIM
3260 case EPROCLIM: return WSAEPROCLIM;
3261 #endif
3262 #ifdef EUSERS
3263 case EUSERS: return WSAEUSERS;
3264 #endif
3265 #ifdef EDQUOT
3266 case EDQUOT: return WSAEDQUOT;
3267 #endif
3268 #ifdef ESTALE
3269 case ESTALE: return WSAESTALE;
3270 #endif
3271 #ifdef EREMOTE
3272 case EREMOTE: return WSAEREMOTE;
3273 #endif
3275 /* just in case we ever get here and there are no problems */
3276 case 0: return 0;
3277 default:
3278 WARN("Unknown errno %d!\n", loc_errno);
3279 return WSAEOPNOTSUPP;
3283 UINT16 wsaHerrno(int loc_errno)
3286 WARN("h_errno %d.\n", loc_errno);
3288 switch(loc_errno)
3290 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3291 case TRY_AGAIN: return WSATRY_AGAIN;
3292 case NO_RECOVERY: return WSANO_RECOVERY;
3293 case NO_DATA: return WSANO_DATA;
3294 case ENOBUFS: return WSAENOBUFS;
3296 case 0: return 0;
3297 default:
3298 WARN("Unknown h_errno %d!\n", loc_errno);
3299 return WSAEOPNOTSUPP;
3304 /***********************************************************************
3305 * WSARecvFrom (WS2_32.69)
3307 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3308 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3309 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3310 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3312 DWORD dwCount;
3313 INT rc;
3315 FIXME( "(%i,%p,%lu,%p,%p,%p,%p,%p,%p: stub\n",
3316 s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags,
3317 lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine );
3319 for( dwCount = 0, rc = 0; dwCount < dwBufferCount; dwCount++ )
3322 if( ( rc = WS_recvfrom(s, lpBuffers[ dwCount ].buf, (INT)lpBuffers[ dwCount ].len,
3323 (INT)*lpFlags, lpFrom, lpFromlen ) ) != 0 )
3325 break;
3330 return rc;
3334 /***********************************************************************
3335 * WSCInstallProvider (WS2_32.88)
3337 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
3338 LPCWSTR lpszProviderDllPath,
3339 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
3340 DWORD dwNumberOfEntries,
3341 LPINT lpErrno )
3343 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
3344 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
3345 dwNumberOfEntries, lpErrno);
3346 *lpErrno = 0;
3347 return 0;
3351 /***********************************************************************
3352 * WSCDeinstallProvider (WS2_32.83)
3354 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
3356 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
3357 *lpErrno = 0;
3358 return 0;
3362 /***********************************************************************
3363 * WSAAccept (WS2_32.26)
3365 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
3366 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
3369 int ret = 0, size = 0;
3370 WSABUF CallerId, CallerData, CalleeId, CalleeData;
3371 /* QOS SQOS, GQOS; */
3372 GROUP g;
3373 SOCKET cs;
3374 SOCKADDR src_addr, dst_addr;
3376 TRACE("Socket %ui, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackD ata %ld\n",
3377 s, addr, addrlen, lpfnCondition, dwCallbackData);
3380 size = sizeof(src_addr);
3381 cs = WS_accept(s, &src_addr, &size);
3383 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
3385 CallerId.buf = (char *)&src_addr;
3386 CallerId.len = sizeof(src_addr);
3388 CallerData.buf = NULL;
3389 CallerData.len = (ULONG)NULL;
3391 WS_getsockname(cs, &dst_addr, &size);
3393 CalleeId.buf = (char *)&dst_addr;
3394 CalleeId.len = sizeof(dst_addr);
3397 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
3398 &CalleeId, &CalleeData, &g, dwCallbackData);
3400 switch (ret)
3402 case CF_ACCEPT:
3403 if (addr && addrlen)
3404 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
3405 return cs;
3406 case CF_DEFER:
3407 SetLastError(WSATRY_AGAIN);
3408 return SOCKET_ERROR;
3409 case CF_REJECT:
3410 WS_closesocket(cs);
3411 SetLastError(WSAECONNREFUSED);
3412 return SOCKET_ERROR;
3413 default:
3414 FIXME("Unknown return type from Condition function\n");
3415 SetLastError(WSAENOTSOCK);
3416 return SOCKET_ERROR;
3419 SetLastError(WSAENOTSOCK);
3420 return SOCKET_ERROR;