Check for a null pointer in WS_setsockopt.
[wine.git] / dlls / winsock / socket.c
blob644bebc5463e622e7c910e4613ff7413b4648ed1
1 /*
2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
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 #ifdef HAVE_SYS_IOCTL_H
36 # include <sys/ioctl.h>
37 #endif
38 #ifdef HAVE_SYS_FILIO_H
39 # include <sys/filio.h>
40 #endif
41 #ifdef HAVE_SYS_SOCKIO_H
42 # include <sys/sockio.h>
43 #endif
45 #if defined(__EMX__)
46 # include <sys/so_ioctl.h>
47 #endif
49 #ifdef HAVE_SYS_PARAM_H
50 # include <sys/param.h>
51 #endif
53 #ifdef HAVE_SYS_MSG_H
54 # include <sys/msg.h>
55 #endif
56 #ifdef HAVE_SYS_WAIT_H
57 # include <sys/wait.h>
58 #endif
59 #ifdef HAVE_SYS_UIO_H
60 # include <sys/uio.h>
61 #endif
62 #ifdef HAVE_SYS_SOCKET_H
63 #include <sys/socket.h>
64 #endif
65 #ifdef HAVE_NETINET_IN_H
66 # include <netinet/in.h>
67 #endif
68 #ifdef HAVE_NETINET_TCP_H
69 # include <netinet/tcp.h>
70 #endif
71 #ifdef HAVE_ARPA_INET_H
72 # include <arpa/inet.h>
73 #endif
74 #include <ctype.h>
75 #include <fcntl.h>
76 #include <errno.h>
77 #ifdef HAVE_SYS_ERRNO_H
78 #include <sys/errno.h>
79 #endif
80 #ifdef HAVE_NETDB_H
81 #include <netdb.h>
82 #endif
83 #ifdef HAVE_UNISTD_H
84 # include <unistd.h>
85 #endif
86 #include <stdlib.h>
87 #ifdef HAVE_ARPA_NAMESER_H
88 # include <arpa/nameser.h>
89 #endif
90 #ifdef HAVE_RESOLV_H
91 # include <resolv.h>
92 #endif
93 #ifdef HAVE_NET_IF_H
94 # include <net/if.h>
95 #endif
96 #ifdef HAVE_IPX_GNU
97 # include <netipx/ipx.h>
98 # define HAVE_IPX
99 #endif
100 #ifdef HAVE_IPX_LINUX
101 # include <asm/types.h>
102 # include <linux/ipx.h>
103 # define HAVE_IPX
104 #endif
106 #ifdef HAVE_SYS_TIME_H
107 # include <sys/time.h>
108 #endif
110 #include "wine/winbase16.h"
111 #include "wingdi.h"
112 #include "winuser.h"
113 #include "winerror.h"
114 #include "winsock2.h"
115 #include "ws2tcpip.h"
116 #include "wsipx.h"
117 #include "wine/winsock16.h"
118 #include "winnt.h"
119 #include "wownt32.h"
120 #include "iphlpapi.h"
121 #include "wine/server.h"
122 #include "wine/debug.h"
124 #ifdef __FreeBSD__
125 # define sipx_network sipx_addr.x_net
126 # define sipx_node sipx_addr.x_host.c_host
127 #endif /* __FreeBSD__ */
129 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
131 /* critical section to protect some non-rentrant net function */
132 extern CRITICAL_SECTION csWSgetXXXbyYYY;
134 #define DEBUG_SOCKADDR 0
135 #define dump_sockaddr(a) \
136 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
137 ((struct sockaddr_in *)a)->sin_family, \
138 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
139 ntohs(((struct sockaddr_in *)a)->sin_port))
141 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
142 #define SOCKET2HANDLE(s) ((HANDLE)(s))
143 #define HANDLE2SOCKET(h) ((SOCKET)(h))
145 /****************************************************************
146 * Async IO declarations
147 ****************************************************************/
148 #include "async.h"
150 static DWORD ws2_async_get_status (const struct async_private *ovp);
151 static DWORD ws2_async_get_count (const struct async_private *ovp);
152 static void ws2_async_set_status (struct async_private *ovp, const DWORD status);
153 static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
154 static void ws2_async_cleanup ( struct async_private *ovp );
156 static struct async_ops ws2_async_ops =
158 ws2_async_get_status,
159 ws2_async_set_status,
160 ws2_async_get_count,
161 ws2_async_call_completion,
162 ws2_async_cleanup
165 static struct async_ops ws2_nocomp_async_ops =
167 ws2_async_get_status,
168 ws2_async_set_status,
169 ws2_async_get_count,
170 NULL, /* call_completion */
171 ws2_async_cleanup
174 typedef struct ws2_async
176 async_private async;
177 LPWSAOVERLAPPED overlapped;
178 LPWSAOVERLAPPED user_overlapped;
179 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
180 struct iovec *iovec;
181 int n_iovecs;
182 struct WS_sockaddr *addr;
183 union {
184 int val; /* for send operations */
185 int *ptr; /* for recv operations */
186 } addrlen;
187 DWORD flags;
188 } ws2_async;
190 /****************************************************************/
192 /* ----------------------------------- internal data */
194 /* ws_... struct conversion flags */
196 #define WS_DUP_LINEAR 0x0001
197 #define WS_DUP_SEGPTR 0x0002 /* internal pointers are SEGPTRs */
198 /* by default, internal pointers are linear */
199 typedef struct /* WSAAsyncSelect() control struct */
201 HANDLE service, event, sock;
202 HWND hWnd;
203 UINT uMsg;
204 LONG lEvent;
205 } ws_select_info;
207 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
208 #define WS_MAX_UDP_DATAGRAM 1024
210 static void *he_buffer; /* typecast for Win16/32 ws_hostent */
211 static SEGPTR he_buffer_seg;
212 static void *se_buffer; /* typecast for Win16/32 ws_servent */
213 static SEGPTR se_buffer_seg;
214 static void *pe_buffer; /* typecast for Win16/32 ws_protoent */
215 static SEGPTR pe_buffer_seg;
216 static char* local_buffer;
217 static SEGPTR dbuffer_seg;
218 static INT num_startup; /* reference counter */
219 static FARPROC blocking_hook;
221 /* function prototypes */
222 static int WS_dup_he(struct hostent* p_he, int flag);
223 static int WS_dup_pe(struct protoent* p_pe, int flag);
224 static int WS_dup_se(struct servent* p_se, int flag);
226 typedef void WIN_hostent;
227 typedef void WIN_protoent;
228 typedef void WIN_servent;
230 int WSAIOCTL_GetInterfaceCount(void);
231 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
233 UINT16 wsaErrno(void);
234 UINT16 wsaHerrno(int errnr);
236 static HANDLE _WSHeap = 0;
238 #define WS_ALLOC(size) \
239 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
240 #define WS_FREE(ptr) \
241 HeapFree(_WSHeap, 0, (ptr) )
243 #define MAP_OPTION(opt) { WS_##opt, opt }
245 static const int ws_sock_map[][2] =
247 MAP_OPTION( SO_DEBUG ),
248 MAP_OPTION( SO_REUSEADDR ),
249 MAP_OPTION( SO_KEEPALIVE ),
250 MAP_OPTION( SO_DONTROUTE ),
251 MAP_OPTION( SO_BROADCAST ),
252 MAP_OPTION( SO_LINGER ),
253 MAP_OPTION( SO_OOBINLINE ),
254 MAP_OPTION( SO_SNDBUF ),
255 MAP_OPTION( SO_RCVBUF ),
256 MAP_OPTION( SO_ERROR ),
257 MAP_OPTION( SO_TYPE ),
258 #ifdef SO_RCVTIMEO
259 MAP_OPTION( SO_RCVTIMEO ),
260 #endif
261 #ifdef SO_SNDTIMEO
262 MAP_OPTION( SO_SNDTIMEO ),
263 #endif
264 { 0, 0 }
267 static const int ws_tcp_map[][2] =
269 #ifdef TCP_NODELAY
270 MAP_OPTION( TCP_NODELAY ),
271 #endif
272 { 0, 0 }
275 static const int ws_ip_map[][2] =
277 MAP_OPTION( IP_MULTICAST_IF ),
278 MAP_OPTION( IP_MULTICAST_TTL ),
279 MAP_OPTION( IP_MULTICAST_LOOP ),
280 MAP_OPTION( IP_ADD_MEMBERSHIP ),
281 MAP_OPTION( IP_DROP_MEMBERSHIP ),
282 MAP_OPTION( IP_OPTIONS ),
283 MAP_OPTION( IP_HDRINCL ),
284 MAP_OPTION( IP_TOS ),
285 MAP_OPTION( IP_TTL ),
286 { 0, 0 }
289 static DWORD opentype_tls_index = -1; /* TLS index for SO_OPENTYPE flag */
291 inline static DWORD NtStatusToWSAError ( const DWORD status )
293 /* We only need to cover the status codes set by server async request handling */
294 DWORD wserr;
295 switch ( status )
297 case STATUS_SUCCESS: wserr = 0; break;
298 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
299 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
300 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
301 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
302 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
303 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
304 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
305 default:
306 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
307 /* It is not a NT status code but a winsock error */
308 wserr = status;
309 else
311 wserr = RtlNtStatusToDosError( status );
312 FIXME ( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
315 return wserr;
318 /* set last error code from NT status without mapping WSA errors */
319 inline static unsigned int set_error( unsigned int err )
321 if (err)
323 err = NtStatusToWSAError ( err );
324 SetLastError( err );
326 return err;
329 static char* check_buffer(int size);
331 inline static int _get_sock_fd(SOCKET s)
333 int fd;
335 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), GENERIC_READ, &fd, NULL, NULL ) ))
336 return -1;
337 return fd;
340 inline static int _get_sock_fd_type( SOCKET s, DWORD access, enum fd_type *type, int *flags )
342 int fd;
343 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, type, flags ) )) return -1;
344 if ( ( (access & GENERIC_READ) && (*flags & FD_FLAG_RECV_SHUTDOWN ) ) ||
345 ( (access & GENERIC_WRITE) && (*flags & FD_FLAG_SEND_SHUTDOWN ) ) )
347 close (fd);
348 WSASetLastError ( WSAESHUTDOWN );
349 return -1;
351 return fd;
354 static void _enable_event( HANDLE s, unsigned int event,
355 unsigned int sstate, unsigned int cstate )
357 SERVER_START_REQ( enable_socket_event )
359 req->handle = s;
360 req->mask = event;
361 req->sstate = sstate;
362 req->cstate = cstate;
363 wine_server_call( req );
365 SERVER_END_REQ;
368 static int _is_blocking(SOCKET s)
370 int ret;
371 SERVER_START_REQ( get_socket_event )
373 req->handle = SOCKET2HANDLE(s);
374 req->service = FALSE;
375 req->c_event = 0;
376 wine_server_call( req );
377 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
379 SERVER_END_REQ;
380 return ret;
383 static unsigned int _get_sock_mask(SOCKET s)
385 unsigned int ret;
386 SERVER_START_REQ( get_socket_event )
388 req->handle = SOCKET2HANDLE(s);
389 req->service = FALSE;
390 req->c_event = 0;
391 wine_server_call( req );
392 ret = reply->mask;
394 SERVER_END_REQ;
395 return ret;
398 static void _sync_sock_state(SOCKET s)
400 /* do a dummy wineserver request in order to let
401 the wineserver run through its select loop once */
402 (void)_is_blocking(s);
405 static int _get_sock_error(SOCKET s, unsigned int bit)
407 int events[FD_MAX_EVENTS];
409 SERVER_START_REQ( get_socket_event )
411 req->handle = SOCKET2HANDLE(s);
412 req->service = FALSE;
413 req->c_event = 0;
414 wine_server_set_reply( req, events, sizeof(events) );
415 wine_server_call( req );
417 SERVER_END_REQ;
418 return events[bit];
421 static void WINSOCK_DeleteIData(void)
423 /* delete scratch buffers */
425 UnMapLS( he_buffer_seg );
426 UnMapLS( se_buffer_seg );
427 UnMapLS( pe_buffer_seg );
428 UnMapLS( dbuffer_seg );
429 if (he_buffer) HeapFree( GetProcessHeap(), 0, he_buffer );
430 if (se_buffer) HeapFree( GetProcessHeap(), 0, se_buffer );
431 if (pe_buffer) HeapFree( GetProcessHeap(), 0, pe_buffer );
432 if (local_buffer) HeapFree( GetProcessHeap(), 0, local_buffer );
433 he_buffer = NULL;
434 se_buffer = NULL;
435 pe_buffer = NULL;
436 local_buffer = NULL;
437 he_buffer_seg = 0;
438 se_buffer_seg = 0;
439 pe_buffer_seg = 0;
440 dbuffer_seg = 0;
441 num_startup = 0;
444 /***********************************************************************
445 * DllMain (WS2_32.init)
447 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
449 TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
450 switch (fdwReason) {
451 case DLL_PROCESS_ATTACH:
452 opentype_tls_index = TlsAlloc();
453 break;
454 case DLL_PROCESS_DETACH:
455 TlsFree( opentype_tls_index );
456 WINSOCK_DeleteIData();
457 break;
459 return TRUE;
462 /***********************************************************************
463 * convert_sockopt()
465 * Converts socket flags from Windows format.
466 * Return 1 if converted, 0 if not (error).
468 static int convert_sockopt(INT *level, INT *optname)
470 int i;
471 switch (*level)
473 case WS_SOL_SOCKET:
474 *level = SOL_SOCKET;
475 for(i=0; ws_sock_map[i][0]; i++)
477 if( ws_sock_map[i][0] == *optname )
479 *optname = ws_sock_map[i][1];
480 return 1;
483 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
484 break;
485 case WS_IPPROTO_TCP:
486 *level = IPPROTO_TCP;
487 for(i=0; ws_tcp_map[i][0]; i++)
489 if ( ws_tcp_map[i][0] == *optname )
491 *optname = ws_tcp_map[i][1];
492 return 1;
495 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
496 break;
497 case WS_IPPROTO_IP:
498 *level = IPPROTO_IP;
499 for(i=0; ws_ip_map[i][0]; i++)
501 if (ws_ip_map[i][0] == *optname )
503 *optname = ws_ip_map[i][1];
504 return 1;
507 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
508 break;
509 default: FIXME("Unimplemented or unknown socket level\n");
511 return 0;
514 /* ----------------------------------- Per-thread info (or per-process?) */
516 static int wsi_strtolo(const char* name, const char* opt)
518 /* Stuff a lowercase copy of the string into the local buffer */
520 int i = strlen(name) + 2;
521 char* p = check_buffer(i + ((opt)?strlen(opt):0));
523 if( p )
525 do *p++ = tolower(*name); while(*name++);
526 i = (p - local_buffer);
527 if( opt ) do *p++ = tolower(*opt); while(*opt++);
528 return i;
530 return 0;
533 static fd_set* fd_set_import( fd_set* fds, void* wsfds, int* highfd, int lfd[], BOOL b32 )
535 /* translate Winsock fd set into local fd set */
537 if( wsfds )
539 #define wsfds16 ((ws_fd_set16*)wsfds)
540 #define wsfds32 ((WS_fd_set*)wsfds)
541 int i, count;
543 FD_ZERO(fds);
544 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
546 for( i = 0; i < count; i++ )
548 int s = (b32) ? wsfds32->fd_array[i]
549 : wsfds16->fd_array[i];
550 int fd = _get_sock_fd(s);
551 if (fd != -1)
553 lfd[ i ] = fd;
554 if( fd > *highfd ) *highfd = fd;
555 FD_SET(fd, fds);
557 else lfd[ i ] = -1;
559 #undef wsfds32
560 #undef wsfds16
561 return fds;
563 return NULL;
566 inline static int sock_error_p(int s)
568 unsigned int optval, optlen;
570 optlen = sizeof(optval);
571 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
572 if (optval) WARN("\t[%i] error: %d\n", s, optval);
573 return optval != 0;
576 static int fd_set_export( fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
578 int num_err = 0;
580 /* translate local fd set into Winsock fd set, adding
581 * errors to exceptfds (only if app requested it) */
583 if( wsfds )
585 #define wsfds16 ((ws_fd_set16*)wsfds)
586 #define wsfds32 ((WS_fd_set*)wsfds)
587 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
589 for( i = 0, j = 0; i < count; i++ )
591 if( lfd[i] >= 0 )
593 int fd = lfd[i];
594 if( FD_ISSET(fd, fds) )
596 if ( exceptfds && sock_error_p(fd) )
598 FD_SET(fd, exceptfds);
599 num_err++;
601 else if( b32 )
602 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
603 else
604 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
606 close(fd);
607 lfd[i] = -1;
611 if( b32 ) wsfds32->fd_count = j;
612 else wsfds16->fd_count = j;
614 TRACE("\n");
615 #undef wsfds32
616 #undef wsfds16
618 return num_err;
621 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
623 if ( wsfds )
625 #define wsfds16 ((ws_fd_set16*)wsfds)
626 #define wsfds32 ((WS_fd_set*)wsfds)
627 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
629 for( i = 0; i < count; i++ )
630 if ( lfd[i] >= 0 )
631 close(lfd[i]);
633 TRACE("\n");
634 #undef wsfds32
635 #undef wsfds16
639 static int do_block( int fd, int mask )
641 fd_set fds[3];
642 int i, r;
644 FD_ZERO(&fds[0]);
645 FD_ZERO(&fds[1]);
646 FD_ZERO(&fds[2]);
647 for (i=0; i<3; i++)
648 if (mask & (1<<i))
649 FD_SET(fd, &fds[i]);
650 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
651 if (i <= 0) return -1;
652 r = 0;
653 for (i=0; i<3; i++)
654 if (FD_ISSET(fd, &fds[i]))
655 r |= 1<<i;
656 return r;
659 void* __ws_memalloc( int size )
661 return WS_ALLOC(size);
664 void __ws_memfree(void* ptr)
666 WS_FREE(ptr);
670 /* ----------------------------------- API -----
672 * Init / cleanup / error checking.
675 /***********************************************************************
676 * WSAStartup (WINSOCK.115)
678 * Create socket control struct, attach it to the global list and
679 * update a pointer in the task struct.
681 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA16 lpWSAData)
683 static const WSADATA16 data =
685 0x0101, 0x0101,
686 "WINE Sockets 1.1",
687 #ifdef linux
688 "Linux/i386",
689 #elif defined(__NetBSD__)
690 "NetBSD/i386",
691 #elif defined(sunos)
692 "SunOS",
693 #elif defined(__FreeBSD__)
694 "FreeBSD",
695 #elif defined(__OpenBSD__)
696 "OpenBSD/i386",
697 #else
698 "Unknown",
699 #endif
700 WS_MAX_SOCKETS_PER_PROCESS,
701 WS_MAX_UDP_DATAGRAM,
705 TRACE("verReq=%x\n", wVersionRequested);
707 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
708 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
710 if (!lpWSAData) return WSAEINVAL;
712 /* initialize socket heap */
714 if( !_WSHeap )
716 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
717 if( !_WSHeap )
719 ERR("Fatal: failed to create WinSock heap\n");
720 return 0;
723 if( _WSHeap == 0 ) return WSASYSNOTREADY;
725 num_startup++;
727 /* return winsock information */
729 memcpy(lpWSAData, &data, sizeof(data));
731 TRACE("succeeded\n");
732 return 0;
735 /***********************************************************************
736 * WSAStartup (WS2_32.115)
738 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
740 TRACE("verReq=%x\n", wVersionRequested);
742 if (LOBYTE(wVersionRequested) < 1)
743 return WSAVERNOTSUPPORTED;
745 if (!lpWSAData) return WSAEINVAL;
747 /* initialize socket heap */
749 if( !_WSHeap )
751 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
752 if( !_WSHeap )
754 ERR("Fatal: failed to create WinSock heap\n");
755 return 0;
758 if( _WSHeap == 0 ) return WSASYSNOTREADY;
760 num_startup++;
762 /* that's the whole of the negotiation for now */
763 lpWSAData->wVersion = wVersionRequested;
764 /* return winsock information */
765 lpWSAData->wHighVersion = 0x0202;
766 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
767 strcpy(lpWSAData->szSystemStatus, "Running" );
768 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
769 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
770 /* don't do anything with lpWSAData->lpVendorInfo */
771 /* (some apps don't allocate the space for this field) */
773 TRACE("succeeded\n");
774 return 0;
778 /***********************************************************************
779 * WSACleanup (WINSOCK.116)
780 * WSACleanup (WS2_32.116)
782 INT WINAPI WSACleanup(void)
784 if (num_startup)
786 if (--num_startup > 0) return 0;
787 WINSOCK_DeleteIData();
788 return 0;
790 SetLastError(WSANOTINITIALISED);
791 return SOCKET_ERROR;
795 /***********************************************************************
796 * WSAGetLastError (WINSOCK.111)
797 * WSAGetLastError (WS2_32.111)
799 INT WINAPI WSAGetLastError(void)
801 return GetLastError();
804 /***********************************************************************
805 * WSASetLastError (WS2_32.112)
807 void WINAPI WSASetLastError(INT iError) {
808 SetLastError(iError);
811 /***********************************************************************
812 * WSASetLastError (WINSOCK.112)
814 void WINAPI WSASetLastError16(INT16 iError)
816 WSASetLastError(iError);
819 static char* check_buffer(int size)
821 static int local_buflen;
823 if (local_buffer)
825 if (local_buflen >= size ) return local_buffer;
826 HeapFree( GetProcessHeap(), 0, local_buffer );
828 local_buffer = HeapAlloc( GetProcessHeap(), 0, (local_buflen = size) );
829 return local_buffer;
832 static struct ws_hostent* check_buffer_he(int size)
834 static int he_len;
835 if (he_buffer)
837 if (he_len >= size ) return he_buffer;
838 UnMapLS( he_buffer_seg );
839 HeapFree( GetProcessHeap(), 0, he_buffer );
841 he_buffer = HeapAlloc( GetProcessHeap(), 0, (he_len = size) );
842 he_buffer_seg = MapLS( he_buffer );
843 return he_buffer;
846 static void* check_buffer_se(int size)
848 static int se_len;
849 if (se_buffer)
851 if (se_len >= size ) return se_buffer;
852 UnMapLS( se_buffer_seg );
853 HeapFree( GetProcessHeap(), 0, se_buffer );
855 se_buffer = HeapAlloc( GetProcessHeap(), 0, (se_len = size) );
856 se_buffer_seg = MapLS( se_buffer );
857 return se_buffer;
860 static struct ws_protoent* check_buffer_pe(int size)
862 static int pe_len;
863 if (pe_buffer)
865 if (pe_len >= size ) return pe_buffer;
866 UnMapLS( pe_buffer_seg );
867 HeapFree( GetProcessHeap(), 0, pe_buffer );
869 pe_buffer = HeapAlloc( GetProcessHeap(), 0, (pe_len = size) );
870 pe_buffer_seg = MapLS( he_buffer );
871 return pe_buffer;
874 /* ----------------------------------- i/o APIs */
876 #ifdef HAVE_IPX
877 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
878 #else
879 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
880 #endif
883 /**********************************************************************/
885 /* Returns the converted address if successful, NULL if it was too small to
886 * start with. Note that the returned pointer may be the original pointer
887 * if no conversion is necessary.
889 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
891 switch (wsaddr->sa_family)
893 #ifdef HAVE_IPX
894 case WS_AF_IPX:
896 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
897 struct sockaddr_ipx* uipx;
899 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
900 return NULL;
902 *uaddrlen=sizeof(struct sockaddr_ipx);
903 uipx=malloc(*uaddrlen);
904 uipx->sipx_family=AF_IPX;
905 uipx->sipx_port=wsipx->sa_socket;
906 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
907 * in one go
909 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
910 #ifdef IPX_FRAME_NONE
911 uipx->sipx_type=IPX_FRAME_NONE;
912 #endif
913 memset(&uipx->sipx_zero,0,sizeof uipx->sipx_zero);
914 return (const struct sockaddr*)uipx;
916 #endif
918 default:
919 if (wsaddrlen<sizeof(struct WS_sockaddr))
920 return NULL;
922 /* No conversion needed, just return the original address */
923 *uaddrlen=wsaddrlen;
924 return (const struct sockaddr*)wsaddr;
926 return NULL;
929 /* Allocates a Unix sockaddr structure to receive the data */
930 inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
932 if (wsaddr==NULL)
934 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
936 /* This is not strictly the right thing to do. Hope it works however */
937 *uaddrlen=0;
939 return NULL;
942 if (*wsaddrlen==0)
943 *uaddrlen=0;
944 else
945 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
947 return malloc(*uaddrlen);
950 /* Returns 0 if successful, -1 if the buffer is too small */
951 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
953 int res;
955 switch(uaddr->sa_family)
957 #ifdef HAVE_IPX
958 case AF_IPX:
960 struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
961 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
963 res=-1;
964 switch (*wsaddrlen) /* how much can we copy? */
966 default:
967 res=0; /* enough */
968 *wsaddrlen=uaddrlen;
969 wsipx->sa_socket=uipx->sipx_port;
970 /* fall through */
971 case 13:
972 case 12:
973 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
974 /* fall through */
975 case 11:
976 case 10:
977 case 9:
978 case 8:
979 case 7:
980 case 6:
981 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
982 /* fall through */
983 case 5:
984 case 4:
985 case 3:
986 case 2:
987 wsipx->sa_family=WS_AF_IPX;
988 /* fall through */
989 case 1:
990 case 0:
991 /* way too small */
992 break;
995 break;
996 #endif
998 default:
999 /* No conversion needed */
1000 memcpy(wsaddr,uaddr,*wsaddrlen);
1001 if (*wsaddrlen<uaddrlen) {
1002 res=-1;
1003 } else {
1004 *wsaddrlen=uaddrlen;
1005 res=0;
1008 return res;
1011 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
1012 * ws_sockaddr_alloc
1014 inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
1016 if (uaddr!=NULL && uaddr!=(const struct sockaddr*)wsaddr)
1017 free((void*)uaddr);
1020 /**************************************************************************
1021 * Functions for handling overlapped I/O
1022 **************************************************************************/
1024 static DWORD ws2_async_get_status (const struct async_private *ovp)
1026 return ((ws2_async*) ovp)->overlapped->Internal;
1029 static VOID ws2_async_set_status (struct async_private *ovp, const DWORD status)
1031 ((ws2_async*) ovp)->overlapped->Internal = status;
1034 static DWORD ws2_async_get_count (const struct async_private *ovp)
1036 return ((ws2_async*) ovp)->overlapped->InternalHigh;
1039 static void ws2_async_cleanup ( struct async_private *ap )
1041 struct ws2_async *as = (struct ws2_async*) ap;
1043 TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->overlapped );
1044 if ( !as->user_overlapped )
1046 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
1047 WSACloseEvent ( as->overlapped->hEvent );
1048 HeapFree ( GetProcessHeap(), 0, as->overlapped );
1051 if ( as->iovec )
1052 HeapFree ( GetProcessHeap(), 0, as->iovec );
1054 HeapFree ( GetProcessHeap(), 0, as );
1057 static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
1059 ws2_async* as = (ws2_async*) data;
1061 TRACE ("data: %p\n", as);
1063 as->completion_func ( NtStatusToWSAError (as->overlapped->Internal),
1064 as->overlapped->InternalHigh,
1065 as->user_overlapped,
1066 as->flags );
1067 ws2_async_cleanup ( &as->async );
1070 /***********************************************************************
1071 * WS2_make_async (INTERNAL)
1074 static void WS2_async_recv (async_private *as);
1075 static void WS2_async_send (async_private *as);
1077 inline static struct ws2_async*
1078 WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferCount,
1079 LPDWORD lpFlags, struct WS_sockaddr *addr,
1080 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
1081 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1083 struct ws2_async *wsa = HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async ) );
1085 TRACE ( "wsa %p\n", wsa );
1087 if (!wsa)
1088 return NULL;
1090 wsa->async.ops = ( lpCompletionRoutine ? &ws2_async_ops : &ws2_nocomp_async_ops );
1091 wsa->async.handle = (HANDLE) s;
1092 wsa->async.fd = fd;
1093 wsa->async.type = type;
1094 switch (type)
1096 case ASYNC_TYPE_READ:
1097 wsa->flags = *lpFlags;
1098 wsa->async.func = WS2_async_recv;
1099 wsa->addrlen.ptr = addrlen;
1100 break;
1101 case ASYNC_TYPE_WRITE:
1102 wsa->flags = 0;
1103 wsa->async.func = WS2_async_send;
1104 wsa->addrlen.val = *addrlen;
1105 break;
1106 default:
1107 ERR ("Invalid async type: %d\n", type);
1109 wsa->user_overlapped = lpOverlapped;
1110 wsa->completion_func = lpCompletionRoutine;
1111 wsa->iovec = iovec;
1112 wsa->n_iovecs = dwBufferCount;
1113 wsa->addr = addr;
1115 if ( lpOverlapped )
1117 wsa->overlapped = lpOverlapped;
1118 wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
1120 else
1122 wsa->overlapped = HeapAlloc ( GetProcessHeap(), 0,
1123 sizeof (WSAOVERLAPPED) );
1124 if ( !wsa->overlapped )
1125 goto error;
1126 wsa->async.event = wsa->overlapped->hEvent = INVALID_HANDLE_VALUE;
1129 wsa->overlapped->InternalHigh = 0;
1130 TRACE ( "wsa %p, ops %p, h %p, ev %p, fd %d, func %p, ov %p, uov %p, cfunc %p\n",
1131 wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
1132 wsa->overlapped, wsa->user_overlapped, wsa->completion_func );
1134 return wsa;
1136 error:
1137 TRACE ("Error\n");
1138 HeapFree ( GetProcessHeap(), 0, wsa );
1139 return NULL;
1142 /***********************************************************************
1143 * WS2_recv (INTERNAL)
1145 * Work horse for both synchronous and asynchronous recv() operations.
1147 static int WS2_recv ( int fd, struct iovec* iov, int count,
1148 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1149 LPDWORD lpFlags )
1151 struct msghdr hdr;
1152 int n;
1153 TRACE ( "fd %d, iovec %p, count %d addr %p, len %p, flags %lx\n",
1154 fd, iov, count, lpFrom, lpFromlen, *lpFlags);
1156 hdr.msg_name = NULL;
1158 if ( lpFrom )
1160 #if DEBUG_SOCKADDR
1161 dump_sockaddr (lpFrom);
1162 #endif
1164 hdr.msg_namelen = *lpFromlen;
1165 hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
1166 if ( !hdr.msg_name )
1168 WSASetLastError ( WSAEFAULT );
1169 n = -1;
1170 goto out;
1173 else
1174 hdr.msg_namelen = 0;
1176 hdr.msg_iov = iov;
1177 hdr.msg_iovlen = count;
1178 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1179 hdr.msg_accrights = NULL;
1180 hdr.msg_accrightslen = 0;
1181 #else
1182 hdr.msg_control = NULL;
1183 hdr.msg_controllen = 0;
1184 hdr.msg_flags = 0;
1185 #endif
1187 if ( (n = recvmsg (fd, &hdr, *lpFlags)) == -1 )
1189 TRACE ( "recvmsg error %d\n", errno);
1190 goto out;
1193 if ( lpFrom &&
1194 ws_sockaddr_u2ws ( hdr.msg_name, hdr.msg_namelen,
1195 lpFrom, lpFromlen ) != 0 )
1197 /* The from buffer was too small, but we read the data
1198 * anyway. Is that really bad?
1200 WSASetLastError ( WSAEFAULT );
1201 WARN ( "Address buffer too small\n" );
1204 out:
1206 ws_sockaddr_free ( hdr.msg_name, lpFrom );
1207 TRACE ("-> %d\n", n);
1208 return n;
1211 /***********************************************************************
1212 * WS2_async_recv (INTERNAL)
1214 * Handler for overlapped recv() operations.
1216 static void WS2_async_recv ( async_private *as )
1218 ws2_async* wsa = (ws2_async*) as;
1219 int result, err;
1221 TRACE ( "async %p\n", wsa );
1223 if ( wsa->overlapped->Internal != STATUS_PENDING )
1225 TRACE ( "status: %ld\n", wsa->overlapped->Internal );
1226 return;
1229 result = WS2_recv ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1230 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1232 if (result >= 0)
1234 wsa->overlapped->Internal = STATUS_SUCCESS;
1235 wsa->overlapped->InternalHigh = result;
1236 TRACE ( "received %d bytes\n", result );
1237 _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
1238 return;
1241 err = wsaErrno ();
1242 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1244 wsa->overlapped->Internal = STATUS_PENDING;
1245 _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
1246 TRACE ( "still pending\n" );
1248 else
1250 wsa->overlapped->Internal = err;
1251 TRACE ( "Error: %x\n", err );
1255 /***********************************************************************
1256 * WS2_send (INTERNAL)
1258 * Work horse for both synchronous and asynchronous send() operations.
1260 static int WS2_send ( int fd, struct iovec* iov, int count,
1261 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1263 struct msghdr hdr;
1264 int n = -1;
1265 TRACE ( "fd %d, iovec %p, count %d addr %p, len %d, flags %lx\n",
1266 fd, iov, count, to, tolen, dwFlags);
1268 hdr.msg_name = NULL;
1270 if ( to )
1272 #if DEBUG_SOCKADDR
1273 dump_sockaddr (to);
1274 #endif
1275 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
1276 if ( !hdr.msg_name )
1278 WSASetLastError ( WSAEFAULT );
1279 goto out;
1282 else
1283 hdr.msg_namelen = 0;
1285 hdr.msg_iov = iov;
1286 hdr.msg_iovlen = count;
1287 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1288 hdr.msg_accrights = NULL;
1289 hdr.msg_accrightslen = 0;
1290 #else
1291 hdr.msg_control = NULL;
1292 hdr.msg_controllen = 0;
1293 hdr.msg_flags = 0;
1294 #endif
1296 n = sendmsg (fd, &hdr, dwFlags);
1298 out:
1299 ws_sockaddr_free ( hdr.msg_name, to );
1300 return n;
1303 /***********************************************************************
1304 * WS2_async_send (INTERNAL)
1306 * Handler for overlapped send() operations.
1308 static void WS2_async_send ( async_private *as )
1310 ws2_async* wsa = (ws2_async*) as;
1311 int result, err;
1313 TRACE ( "async %p\n", wsa );
1315 if ( wsa->overlapped->Internal != STATUS_PENDING )
1317 TRACE ( "status: %ld\n", wsa->overlapped->Internal );
1318 return;
1321 result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1322 wsa->addr, wsa->addrlen.val, wsa->flags );
1324 if (result >= 0)
1326 wsa->overlapped->Internal = STATUS_SUCCESS;
1327 wsa->overlapped->InternalHigh = result;
1328 TRACE ( "sent %d bytes\n", result );
1329 _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
1330 return;
1333 err = wsaErrno ();
1334 if ( err == WSAEINTR )
1336 wsa->overlapped->Internal = STATUS_PENDING;
1337 _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
1338 TRACE ( "still pending\n" );
1340 else
1342 /* We set the status to a winsock error code and check for that
1343 later in NtStatusToWSAError () */
1344 wsa->overlapped->Internal = err;
1345 TRACE ( "Error: %x\n", err );
1349 /***********************************************************************
1350 * WS2_async_shutdown (INTERNAL)
1352 * Handler for shutdown() operations on overlapped sockets.
1354 static void WS2_async_shutdown ( async_private *as )
1356 ws2_async* wsa = (ws2_async*) as;
1357 int err = 1;
1359 TRACE ( "async %p %d\n", wsa, wsa->async.type );
1360 switch ( wsa->async.type )
1362 case ASYNC_TYPE_READ:
1363 err = shutdown ( wsa->async.fd, 0 );
1364 break;
1365 case ASYNC_TYPE_WRITE:
1366 err = shutdown ( wsa->async.fd, 1 );
1367 break;
1368 default:
1369 ERR ("invalid type: %d\n", wsa->async.type );
1372 if ( err )
1373 wsa->overlapped->Internal = wsaErrno ();
1374 else
1375 wsa->overlapped->Internal = STATUS_SUCCESS;
1378 /***********************************************************************
1379 * WS2_register_async_shutdown (INTERNAL)
1381 * Helper function for WS_shutdown() on overlapped sockets.
1383 static int WS2_register_async_shutdown ( SOCKET s, int fd, int type )
1385 struct ws2_async *wsa;
1386 int ret, err = WSAEFAULT;
1387 DWORD dwflags = 0;
1388 int len = 0;
1389 LPWSAOVERLAPPED ovl = HeapAlloc (GetProcessHeap(), 0, sizeof ( WSAOVERLAPPED ));
1391 TRACE ("s %d fd %d type %d\n", s, fd, type);
1392 if (!ovl)
1393 goto out;
1395 ovl->hEvent = WSACreateEvent ();
1396 if ( ovl->hEvent == WSA_INVALID_EVENT )
1397 goto out_free;
1399 wsa = WS2_make_async ( s, fd, type, NULL, 0,
1400 &dwflags, NULL, &len, ovl, NULL );
1401 if ( !wsa )
1402 goto out_close;
1404 /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
1405 wsa->user_overlapped = NULL;
1406 wsa->async.func = WS2_async_shutdown;
1407 if ( (ret = register_new_async ( &wsa->async )) )
1409 err = NtStatusToWSAError ( ret );
1410 goto out;
1412 /* Try immediate completion */
1413 while ( WaitForSingleObjectEx ( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1414 return 0;
1416 out_close:
1417 WSACloseEvent ( ovl->hEvent );
1418 out_free:
1419 HeapFree ( GetProcessHeap(), 0, ovl );
1420 out:
1421 return err;
1424 /***********************************************************************
1425 * accept (WS2_32.1)
1427 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1428 int *addrlen32)
1430 int fd = _get_sock_fd(s);
1432 TRACE("socket %04x\n", (UINT16)s );
1433 if (fd != -1)
1435 SOCKET as;
1436 if (_is_blocking(s))
1438 /* block here */
1439 do_block(fd, 5);
1440 _sync_sock_state(s); /* let wineserver notice connection */
1441 /* retrieve any error codes from it */
1442 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1443 /* FIXME: care about the error? */
1445 close(fd);
1446 SERVER_START_REQ( accept_socket )
1448 req->lhandle = SOCKET2HANDLE(s);
1449 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1450 req->inherit = TRUE;
1451 set_error( wine_server_call( req ) );
1452 as = HANDLE2SOCKET( reply->handle );
1454 SERVER_END_REQ;
1455 if (as)
1457 if (addr)
1458 WS_getpeername(as, addr, addrlen32);
1459 return as;
1462 else
1464 SetLastError(WSAENOTSOCK);
1466 return INVALID_SOCKET;
1469 /***********************************************************************
1470 * accept (WINSOCK.1)
1472 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct WS_sockaddr* addr,
1473 INT16* addrlen16 )
1475 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
1476 SOCKET retSocket = WS_accept( s, addr, &addrlen32 );
1477 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
1478 return (SOCKET16)retSocket;
1481 /***********************************************************************
1482 * bind (WS2_32.2)
1484 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1486 int fd = _get_sock_fd(s);
1487 int res;
1489 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
1490 #if DEBUG_SOCKADDR
1491 dump_sockaddr(name);
1492 #endif
1494 res=SOCKET_ERROR;
1495 if (fd != -1)
1497 if (!name || !SUPPORTED_PF(name->sa_family))
1499 SetLastError(WSAEAFNOSUPPORT);
1501 else
1503 const struct sockaddr* uaddr;
1504 int uaddrlen;
1506 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1507 if (uaddr == NULL)
1509 SetLastError(WSAEFAULT);
1511 else
1513 int on = 1;
1514 /* The game GrandPrixLegends binds more than one time, but does
1515 * not do a SO_REUSEADDR - Stevens says this is ok */
1516 TRACE( "Setting WS_SO_REUSEADDR on socket before we bind it\n");
1517 WS_setsockopt( s, WS_SOL_SOCKET, WS_SO_REUSEADDR, (char*)&on, sizeof(on) );
1519 if (bind(fd, uaddr, uaddrlen) < 0)
1521 int loc_errno = errno;
1522 WARN("\tfailure - errno = %i\n", errno);
1523 errno = loc_errno;
1524 switch (errno)
1526 case EBADF:
1527 SetLastError(WSAENOTSOCK);
1528 break;
1529 case EADDRNOTAVAIL:
1530 SetLastError(WSAEINVAL);
1531 break;
1532 default:
1533 SetLastError(wsaErrno());
1534 break;
1537 else
1539 res=0; /* success */
1541 ws_sockaddr_free(uaddr,name);
1544 close(fd);
1546 else
1548 SetLastError(WSAENOTSOCK);
1550 return res;
1553 /***********************************************************************
1554 * bind (WINSOCK.2)
1556 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1558 return (INT16)WS_bind( s, name, namelen );
1561 /***********************************************************************
1562 * closesocket (WS2_32.3)
1564 int WINAPI WS_closesocket(SOCKET s)
1566 TRACE("socket %08x\n", s);
1567 if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1568 return SOCKET_ERROR;
1571 /***********************************************************************
1572 * closesocket (WINSOCK.3)
1574 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
1576 return (INT16)WS_closesocket(s);
1579 /***********************************************************************
1580 * connect (WS2_32.4)
1582 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1584 int fd = _get_sock_fd(s);
1586 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
1587 #if DEBUG_SOCKADDR
1588 dump_sockaddr(name);
1589 #endif
1591 if (fd != -1)
1593 const struct sockaddr* uaddr;
1594 int uaddrlen;
1596 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1597 if (uaddr == NULL)
1599 SetLastError(WSAEFAULT);
1601 else
1603 int rc;
1605 rc=connect(fd, uaddr, uaddrlen);
1606 ws_sockaddr_free(uaddr,name);
1607 if (rc == 0)
1608 goto connect_success;
1611 if (errno == EINPROGRESS)
1613 /* tell wineserver that a connection is in progress */
1614 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1615 FD_CONNECT|FD_READ|FD_WRITE,
1616 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1617 if (_is_blocking(s))
1619 int result;
1620 /* block here */
1621 do_block(fd, 7);
1622 _sync_sock_state(s); /* let wineserver notice connection */
1623 /* retrieve any error codes from it */
1624 result = _get_sock_error(s, FD_CONNECT_BIT);
1625 if (result)
1626 SetLastError(result);
1627 else
1629 goto connect_success;
1632 else
1634 SetLastError(WSAEWOULDBLOCK);
1637 else
1639 SetLastError(wsaErrno());
1641 close(fd);
1643 else
1645 SetLastError(WSAENOTSOCK);
1647 return SOCKET_ERROR;
1649 connect_success:
1650 close(fd);
1651 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1652 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1653 FD_CONNECT|FD_WINE_LISTENING);
1654 return 0;
1657 /***********************************************************************
1658 * connect (WINSOCK.4)
1660 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1662 return (INT16)WS_connect( s, name, namelen );
1665 /***********************************************************************
1666 * WSAConnect (WS2_32.30)
1668 int WINAPI WSAConnect ( SOCKET s, const struct WS_sockaddr* name, int namelen,
1669 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1670 LPQOS lpSQOS, LPQOS lpGQOS )
1672 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1673 FIXME ("unsupported parameters!\n");
1674 return WS_connect ( s, name, namelen );
1678 /***********************************************************************
1679 * getpeername (WS2_32.5)
1681 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1683 int fd;
1684 int res;
1686 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1688 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1689 if( (name == NULL) || (namelen == NULL) )
1691 SetLastError( WSAEFAULT );
1692 return SOCKET_ERROR;
1695 fd = _get_sock_fd(s);
1696 res = SOCKET_ERROR;
1698 if (fd != -1)
1700 struct sockaddr* uaddr;
1701 int uaddrlen;
1703 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1704 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1706 SetLastError(wsaErrno());
1708 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1710 /* The buffer was too small */
1711 SetLastError(WSAEFAULT);
1713 else
1715 res=0;
1717 ws_sockaddr_free(uaddr,name);
1718 close(fd);
1720 else
1722 SetLastError(WSAENOTSOCK);
1724 return res;
1727 /***********************************************************************
1728 * getpeername (WINSOCK.5)
1730 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct WS_sockaddr *name,
1731 INT16 *namelen16)
1733 INT namelen32 = *namelen16;
1734 INT retVal = WS_getpeername( s, name, &namelen32 );
1736 #if DEBUG_SOCKADDR
1737 dump_sockaddr(name);
1738 #endif
1740 *namelen16 = namelen32;
1741 return (INT16)retVal;
1744 /***********************************************************************
1745 * getsockname (WS2_32.6)
1747 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1749 int fd;
1750 int res;
1752 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1754 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1755 if( (name == NULL) || (namelen == NULL) )
1757 SetLastError( WSAEFAULT );
1758 return SOCKET_ERROR;
1761 fd = _get_sock_fd(s);
1762 res = SOCKET_ERROR;
1764 if (fd != -1)
1766 struct sockaddr* uaddr;
1767 int uaddrlen;
1769 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1770 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1772 SetLastError(wsaErrno());
1774 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1776 /* The buffer was too small */
1777 SetLastError(WSAEFAULT);
1779 else
1781 res=0;
1783 close(fd);
1785 else
1787 SetLastError(WSAENOTSOCK);
1789 return res;
1792 /***********************************************************************
1793 * getsockname (WINSOCK.6)
1795 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct WS_sockaddr *name,
1796 INT16 *namelen16)
1798 INT retVal;
1800 if( namelen16 )
1802 INT namelen32 = *namelen16;
1803 retVal = WS_getsockname( s, name, &namelen32 );
1804 *namelen16 = namelen32;
1806 #if DEBUG_SOCKADDR
1807 dump_sockaddr(name);
1808 #endif
1811 else retVal = SOCKET_ERROR;
1812 return (INT16)retVal;
1816 /***********************************************************************
1817 * getsockopt (WS2_32.7)
1819 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1820 INT optname, char *optval, INT *optlen)
1822 int fd;
1824 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1825 (int) optname, (int) optval, (int) *optlen);
1826 /* SO_OPENTYPE does not require a valid socket handle. */
1827 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1829 if (!optlen || *optlen < sizeof(int) || !optval)
1831 SetLastError(WSAEFAULT);
1832 return SOCKET_ERROR;
1834 *(int *)optval = (int)TlsGetValue( opentype_tls_index );
1835 *optlen = sizeof(int);
1836 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1837 return 0;
1840 fd = _get_sock_fd(s);
1841 if (fd != -1)
1843 if (!convert_sockopt(&level, &optname)) {
1844 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1845 } else {
1846 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1848 close(fd);
1849 return 0;
1851 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1853 close(fd);
1855 return SOCKET_ERROR;
1859 /***********************************************************************
1860 * getsockopt (WINSOCK.7)
1862 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1863 INT16 optname, char *optval, INT16 *optlen)
1865 INT optlen32;
1866 INT *p = &optlen32;
1867 INT retVal;
1868 if( optlen ) optlen32 = *optlen; else p = NULL;
1869 retVal = WS_getsockopt( s, (UINT16)level, optname, optval, p );
1870 if( optlen ) *optlen = optlen32;
1871 return (INT16)retVal;
1875 /***********************************************************************
1876 * htonl (WINSOCK.8)
1877 * htonl (WS2_32.8)
1879 u_long WINAPI WS_htonl(u_long hostlong)
1881 return htonl(hostlong);
1885 /***********************************************************************
1886 * htons (WINSOCK.9)
1887 * htons (WS2_32.9)
1889 u_short WINAPI WS_htons(u_short hostshort)
1891 return htons(hostshort);
1895 /***********************************************************************
1896 * inet_addr (WINSOCK.10)
1897 * inet_addr (WS2_32.11)
1899 u_long WINAPI WS_inet_addr(const char *cp)
1901 return inet_addr(cp);
1905 /***********************************************************************
1906 * ntohl (WINSOCK.14)
1907 * ntohl (WS2_32.14)
1909 u_long WINAPI WS_ntohl(u_long netlong)
1911 return ntohl(netlong);
1915 /***********************************************************************
1916 * ntohs (WINSOCK.15)
1917 * ntohs (WS2_32.15)
1919 u_short WINAPI WS_ntohs(u_short netshort)
1921 return ntohs(netshort);
1925 /***********************************************************************
1926 * inet_ntoa (WS2_32.12)
1928 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1930 /* use "buffer for dummies" here because some applications have
1931 * propensity to decode addresses in ws_hostent structure without
1932 * saving them first...
1934 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1936 char* s = inet_ntoa(*((struct in_addr*)&in));
1937 if( s )
1939 strcpy(dbuffer, s);
1940 return dbuffer;
1942 SetLastError(wsaErrno());
1943 return NULL;
1946 /***********************************************************************
1947 * inet_ntoa (WINSOCK.11)
1949 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1951 char* retVal;
1952 if (!(retVal = WS_inet_ntoa(*((struct WS_in_addr*)&in)))) return 0;
1953 if (!dbuffer_seg) dbuffer_seg = MapLS( retVal );
1954 return dbuffer_seg;
1958 /**********************************************************************
1959 * WSAIoctl (WS2_32.50)
1962 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1964 INT WINAPI WSAIoctl (SOCKET s,
1965 DWORD dwIoControlCode,
1966 LPVOID lpvInBuffer,
1967 DWORD cbInBuffer,
1968 LPVOID lpbOutBuffer,
1969 DWORD cbOutBuffer,
1970 LPDWORD lpcbBytesReturned,
1971 LPWSAOVERLAPPED lpOverlapped,
1972 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1974 int fd = _get_sock_fd(s);
1976 if (fd != -1)
1978 switch( dwIoControlCode )
1980 case SIO_GET_INTERFACE_LIST:
1982 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1983 DWORD size, numInt, apiReturn;
1985 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1986 /* FIXME: length of output buffer not checked */
1988 apiReturn = GetAdaptersInfo(NULL, &size);
1989 if (apiReturn == ERROR_NO_DATA)
1991 numInt = 0;
1993 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
1995 PIP_ADAPTER_INFO table = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(),0,size);
1997 if (table)
1999 if (GetAdaptersInfo(table, &size) == NO_ERROR)
2001 PIP_ADAPTER_INFO ptr;
2003 for (ptr = table, numInt = 0; ptr;
2004 ptr = ptr->Next, intArray++, numInt++)
2006 unsigned int addr, mask, bcast;
2007 struct ifreq ifInfo;
2009 /* Socket Status Flags */
2010 strncpy(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
2011 ifInfo.ifr_name[IFNAMSIZ-1] = '\0';
2012 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
2014 ERR ("Error obtaining status flags for socket!\n");
2015 HeapFree(GetProcessHeap(),0,table);
2016 close(fd);
2017 WSASetLastError(WSAEINVAL);
2018 return (SOCKET_ERROR);
2020 else
2022 /* set flags; the values of IFF_* are not the same
2023 under Linux and Windows, therefore must generate
2024 new flags */
2025 intArray->iiFlags = 0;
2026 if (ifInfo.ifr_flags & IFF_BROADCAST)
2027 intArray->iiFlags |= WS_IFF_BROADCAST;
2028 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
2029 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
2030 if (ifInfo.ifr_flags & IFF_LOOPBACK)
2031 intArray->iiFlags |= WS_IFF_LOOPBACK;
2032 if (ifInfo.ifr_flags & IFF_UP)
2033 intArray->iiFlags |= WS_IFF_UP;
2036 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
2037 mask = inet_addr(ptr->IpAddressList.IpMask.String);
2038 bcast = addr | (addr & !mask);
2039 intArray->iiAddress.AddressIn.sin_family = AF_INET;
2040 intArray->iiAddress.AddressIn.sin_port = 0;
2041 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
2042 addr;
2043 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2044 intArray->iiNetmask.AddressIn.sin_port = 0;
2045 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
2046 mask;
2047 intArray->iiBroadcastAddress.AddressIn.sin_family =
2048 AF_INET;
2049 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
2050 intArray->iiBroadcastAddress.AddressIn.sin_addr.
2051 WS_s_addr = bcast;
2053 HeapFree(GetProcessHeap(),0,table);
2055 else
2057 ERR ("Unable to get interface table!\n");
2058 close(fd);
2059 HeapFree(GetProcessHeap(),0,table);
2060 WSASetLastError(WSAEINVAL);
2061 return (SOCKET_ERROR);
2064 else
2066 close(fd);
2067 WSASetLastError(WSAEINVAL);
2068 return (SOCKET_ERROR);
2071 else
2073 ERR ("Unable to get interface table!\n");
2074 close(fd);
2075 WSASetLastError(WSAEINVAL);
2076 return (SOCKET_ERROR);
2078 /* Calculate the size of the array being returned */
2079 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2080 break;
2083 default:
2085 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2086 close(fd);
2087 WSASetLastError(WSAEOPNOTSUPP);
2088 return (SOCKET_ERROR);
2092 /* Function executed with no errors */
2093 close(fd);
2094 return (0);
2096 else
2098 WSASetLastError(WSAENOTSOCK);
2099 return (SOCKET_ERROR);
2104 /***********************************************************************
2105 * ioctlsocket (WS2_32.10)
2107 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2109 int fd = _get_sock_fd(s);
2111 TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
2112 if (fd != -1)
2114 long newcmd = cmd;
2116 switch( cmd )
2118 case WS_FIONREAD:
2119 newcmd=FIONREAD;
2120 break;
2122 case WS_FIONBIO:
2123 newcmd=FIONBIO;
2124 if( _get_sock_mask(s) )
2126 /* AsyncSelect()'ed sockets are always nonblocking */
2127 if (*argp) {
2128 close(fd);
2129 return 0;
2131 SetLastError(WSAEINVAL);
2132 close(fd);
2133 return SOCKET_ERROR;
2135 close(fd);
2136 if (*argp)
2137 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2138 else
2139 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2140 return 0;
2142 case WS_SIOCATMARK:
2143 newcmd=SIOCATMARK;
2144 break;
2146 case WS__IOW('f',125,u_long):
2147 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2148 SetLastError(WSAEINVAL);
2149 return SOCKET_ERROR;
2151 case SIOCGIFBRDADDR:
2152 case SIOCGIFNETMASK:
2153 case SIOCGIFADDR:
2154 /* These don't need any special handling. They are used by
2155 WsControl, and are here to suppress an unecessary warning. */
2156 break;
2159 default:
2160 /* Netscape tries hard to use bogus ioctl 0x667e */
2161 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2163 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2165 close(fd);
2166 return 0;
2168 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2169 close(fd);
2171 return SOCKET_ERROR;
2174 /***********************************************************************
2175 * ioctlsocket (WINSOCK.12)
2177 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
2179 return (INT16)WS_ioctlsocket( s, cmd, argp );
2183 /***********************************************************************
2184 * listen (WS2_32.13)
2186 int WINAPI WS_listen(SOCKET s, int backlog)
2188 int fd = _get_sock_fd(s);
2190 TRACE("socket %04x, backlog %d\n", s, backlog);
2191 if (fd != -1)
2193 if (listen(fd, backlog) == 0)
2195 close(fd);
2196 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2197 FD_WINE_LISTENING,
2198 FD_CONNECT|FD_WINE_CONNECTED);
2199 return 0;
2201 SetLastError(wsaErrno());
2203 else SetLastError(WSAENOTSOCK);
2204 return SOCKET_ERROR;
2207 /***********************************************************************
2208 * listen (WINSOCK.13)
2210 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
2212 return (INT16)WS_listen( s, backlog );
2216 /***********************************************************************
2217 * recv (WS2_32.16)
2219 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2221 DWORD n, dwFlags = flags;
2222 WSABUF wsabuf;
2224 wsabuf.len = len;
2225 wsabuf.buf = buf;
2227 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2228 return SOCKET_ERROR;
2229 else
2230 return n;
2233 /***********************************************************************
2234 * recv (WINSOCK.16)
2236 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2238 return (INT16)WS_recv( s, buf, len, flags );
2242 /***********************************************************************
2243 * recvfrom (WS2_32.17)
2245 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2246 struct WS_sockaddr *from, int *fromlen)
2248 DWORD n, dwFlags = flags;
2249 WSABUF wsabuf;
2251 wsabuf.len = len;
2252 wsabuf.buf = buf;
2254 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2255 return SOCKET_ERROR;
2256 else
2257 return n;
2260 /***********************************************************************
2261 * recvfrom (WINSOCK.17)
2263 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2264 struct WS_sockaddr *from, INT16 *fromlen16)
2266 INT fromlen32;
2267 INT *p = &fromlen32;
2268 INT retVal;
2270 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
2271 retVal = WS_recvfrom( s, buf, len, flags, from, p );
2272 if( fromlen16 ) *fromlen16 = fromlen32;
2273 return (INT16)retVal;
2276 /***********************************************************************
2277 * __ws_select
2279 static int __ws_select(BOOL b32,
2280 void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
2281 const struct WS_timeval *ws_timeout)
2283 int highfd = 0;
2284 fd_set readfds, writefds, exceptfds;
2285 fd_set *p_read, *p_write, *p_except;
2286 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2287 struct timeval timeout, *timeoutaddr = NULL;
2289 TRACE("read %p, write %p, excp %p timeout %p\n",
2290 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2292 p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
2293 p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
2294 p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
2295 if (ws_timeout)
2297 timeoutaddr = &timeout;
2298 timeout.tv_sec=ws_timeout->tv_sec;
2299 timeout.tv_usec=ws_timeout->tv_usec;
2302 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2304 fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
2305 fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
2307 if (p_except && ws_exceptfds)
2309 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
2310 #define wsfds32 ((WS_fd_set*)ws_exceptfds)
2311 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
2313 for (i = j = 0; i < count; i++)
2315 int fd = exceptfd[i];
2316 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
2318 if( b32 )
2319 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
2320 else
2321 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
2323 if( fd >= 0 ) close(fd);
2324 exceptfd[i] = -1;
2326 if( b32 )
2327 wsfds32->fd_count = j;
2328 else
2329 wsfds16->fd_count = j;
2330 #undef wsfds32
2331 #undef wsfds16
2333 return highfd;
2335 fd_set_unimport(ws_readfds, readfd, b32);
2336 fd_set_unimport(ws_writefds, writefd, b32);
2337 fd_set_unimport(ws_exceptfds, exceptfd, b32);
2338 if( ws_readfds ) ((WS_fd_set*)ws_readfds)->fd_count = 0;
2339 if( ws_writefds ) ((WS_fd_set*)ws_writefds)->fd_count = 0;
2340 if( ws_exceptfds ) ((WS_fd_set*)ws_exceptfds)->fd_count = 0;
2342 if( highfd == 0 ) return 0;
2343 SetLastError(wsaErrno());
2344 return SOCKET_ERROR;
2347 /***********************************************************************
2348 * select (WINSOCK.18)
2350 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
2351 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
2352 struct WS_timeval* timeout)
2354 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2357 /***********************************************************************
2358 * select (WS2_32.18)
2360 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2361 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2362 const struct WS_timeval* timeout)
2364 /* struct timeval is the same for both 32- and 16-bit code */
2365 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2369 /***********************************************************************
2370 * send (WS2_32.19)
2372 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2374 DWORD n;
2375 WSABUF wsabuf;
2377 wsabuf.len = len;
2378 wsabuf.buf = (char*) buf;
2380 if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2381 return SOCKET_ERROR;
2382 else
2383 return n;
2386 /***********************************************************************
2387 * WSASend (WS2_32.72)
2389 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2390 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2391 LPWSAOVERLAPPED lpOverlapped,
2392 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2394 return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2395 NULL, 0, lpOverlapped, lpCompletionRoutine );
2398 /***********************************************************************
2399 * WSASendDisconnect (WS2_32.73)
2401 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2403 return WS_shutdown ( s, SD_SEND );
2407 /***********************************************************************
2408 * WSASendTo (WS2_32.74)
2410 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2411 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2412 const struct WS_sockaddr *to, int tolen,
2413 LPWSAOVERLAPPED lpOverlapped,
2414 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2416 int i, n, fd, err = WSAENOTSOCK, flags, ret;
2417 struct iovec* iovec;
2418 struct ws2_async *wsa;
2419 enum fd_type type;
2421 TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2422 s, lpBuffers, dwBufferCount, dwFlags,
2423 to, tolen, lpOverlapped, lpCompletionRoutine);
2425 fd = _get_sock_fd_type( s, GENERIC_WRITE, &type, &flags );
2426 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
2428 if ( fd == -1 )
2430 err = WSAGetLastError ();
2431 goto error;
2434 iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
2436 if ( !iovec )
2438 err = WSAEFAULT;
2439 goto err_close;
2442 for ( i = 0; i < dwBufferCount; i++ )
2444 iovec[i].iov_base = lpBuffers[i].buf;
2445 iovec[i].iov_len = lpBuffers[i].len;
2448 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2450 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
2451 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2452 lpOverlapped, lpCompletionRoutine );
2453 if ( !wsa )
2455 err = WSAEFAULT;
2456 goto err_free;
2459 if ( ( ret = register_new_async ( &wsa->async )) )
2461 err = NtStatusToWSAError ( ret );
2463 if ( !lpOverlapped )
2464 HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
2465 HeapFree ( GetProcessHeap(), 0, wsa );
2466 goto err_free;
2469 /* Try immediate completion */
2470 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
2472 if ( WSAGetOverlappedResult ( s, lpOverlapped,
2473 lpNumberOfBytesSent, FALSE, &dwFlags) )
2474 return 0;
2476 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
2477 goto error;
2480 WSASetLastError ( WSA_IO_PENDING );
2481 return SOCKET_ERROR;
2484 if (_is_blocking(s))
2486 /* FIXME: exceptfds? */
2487 do_block(fd, 2);
2490 n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2491 if ( n == -1 )
2493 err = wsaErrno();
2494 if ( err == WSAEWOULDBLOCK )
2495 _enable_event (SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2496 goto err_free;
2499 TRACE(" -> %i bytes\n", n);
2500 *lpNumberOfBytesSent = n;
2502 HeapFree ( GetProcessHeap(), 0, iovec );
2503 close ( fd );
2504 return 0;
2506 err_free:
2507 HeapFree ( GetProcessHeap(), 0, iovec );
2509 err_close:
2510 close ( fd );
2512 error:
2513 WARN (" -> ERROR %d\n", err);
2514 WSASetLastError (err);
2515 return SOCKET_ERROR;
2518 /***********************************************************************
2519 * send (WINSOCK.19)
2521 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2523 return WS_send( s, buf, len, flags );
2526 /***********************************************************************
2527 * sendto (WS2_32.20)
2529 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2530 const struct WS_sockaddr *to, int tolen)
2532 DWORD n;
2533 WSABUF wsabuf;
2535 wsabuf.len = len;
2536 wsabuf.buf = (char*) buf;
2538 if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2539 return SOCKET_ERROR;
2540 else
2541 return n;
2544 /***********************************************************************
2545 * sendto (WINSOCK.20)
2547 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2548 struct WS_sockaddr *to, INT16 tolen)
2550 return (INT16)WS_sendto( s, buf, len, flags, to, tolen );
2553 /***********************************************************************
2554 * setsockopt (WS2_32.21)
2556 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2557 const char *optval, int optlen)
2559 int fd;
2561 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
2562 (int) optname, (int) optval, optlen);
2563 /* SO_OPENTYPE does not require a valid socket handle. */
2564 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2566 if (optlen < sizeof(int) || !optval)
2568 SetLastError(WSAEFAULT);
2569 return SOCKET_ERROR;
2571 TlsSetValue( opentype_tls_index, (LPVOID)*(int *)optval );
2572 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2573 return 0;
2576 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2577 * socket. This will either not happen under windows or it is ignored in
2578 * windows (but it works in linux and therefor prevents the game to find
2579 * games outsite the current network) */
2580 if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE )
2582 FIXME("Does windows ignore SO_DONTROUTE?\n");
2583 return 0;
2587 fd = _get_sock_fd(s);
2588 if (fd != -1)
2590 struct linger linger;
2591 int woptval;
2592 struct timeval tval;
2594 /* Is a privileged and useless operation, so we don't. */
2595 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
2596 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2597 return 0;
2600 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2601 /* This is unique to WinSock and takes special conversion */
2602 linger.l_onoff = *((int*)optval) ? 0: 1;
2603 linger.l_linger = 0;
2604 optname=SO_LINGER;
2605 optval = (char*)&linger;
2606 optlen = sizeof(struct linger);
2607 level = SOL_SOCKET;
2608 }else{
2609 if (!convert_sockopt(&level, &optname)) {
2610 ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2611 SetLastError(WSAENOPROTOOPT);
2612 close(fd);
2613 return SOCKET_ERROR;
2615 if (optname == SO_LINGER && optval) {
2616 /* yes, uses unsigned short in both win16/win32 */
2617 linger.l_onoff = ((UINT16*)optval)[0];
2618 linger.l_linger = ((UINT16*)optval)[1];
2619 /* FIXME: what is documented behavior if SO_LINGER optval
2620 is null?? */
2621 optval = (char*)&linger;
2622 optlen = sizeof(struct linger);
2623 } else if (optval && optlen < sizeof(int)){
2624 woptval= *((INT16 *) optval);
2625 optval= (char*) &woptval;
2626 optlen=sizeof(int);
2628 #ifdef SO_RCVTIMEO
2629 if (level == SOL_SOCKET && optname == SO_RCVTIMEO) {
2630 if (optlen == sizeof(UINT32)) {
2631 /* WinSock passes miliseconds instead of struct timeval */
2632 tval.tv_usec = *(PUINT32)optval % 1000;
2633 tval.tv_sec = *(PUINT32)optval / 1000;
2634 /* min of 500 milisec */
2635 if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2636 optlen = sizeof(struct timeval);
2637 optval = (char*)&tval;
2638 } else if (optlen == sizeof(struct timeval)) {
2639 WARN("SO_RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2640 } else {
2641 WARN("SO_RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2642 close(fd);
2643 return 0;
2646 #endif
2647 #ifdef SO_SNDTIMEO
2648 if (level == SOL_SOCKET && optname == SO_SNDTIMEO) {
2649 if (optlen == sizeof(UINT32)) {
2650 /* WinSock passes miliseconds instead of struct timeval */
2651 tval.tv_usec = *(PUINT32)optval % 1000;
2652 tval.tv_sec = *(PUINT32)optval / 1000;
2653 /* min of 500 milisec */
2654 if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2655 optlen = sizeof(struct timeval);
2656 optval = (char*)&tval;
2657 } else if (optlen == sizeof(struct timeval)) {
2658 WARN("SO_SNDTIMEO for %d bytes: assuming unixism\n", optlen);
2659 } else {
2660 WARN("SO_SNDTIMEO for %d bytes is weird: ignored\n", optlen);
2661 close(fd);
2662 return 0;
2665 #endif
2667 if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2668 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2669 close( fd);
2670 return 0;
2673 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2675 close(fd);
2676 return 0;
2678 TRACE("Setting socket error, %d\n", wsaErrno());
2679 SetLastError(wsaErrno());
2680 close(fd);
2682 else SetLastError(WSAENOTSOCK);
2683 return SOCKET_ERROR;
2686 /***********************************************************************
2687 * setsockopt (WINSOCK.21)
2689 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2690 char *optval, INT16 optlen)
2692 if( !optval ) return SOCKET_ERROR;
2693 return (INT16)WS_setsockopt( s, (UINT16)level, optname, optval, optlen );
2697 /***********************************************************************
2698 * shutdown (WS2_32.22)
2700 int WINAPI WS_shutdown(SOCKET s, int how)
2702 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2703 enum fd_type type;
2704 unsigned int clear_flags = 0;
2706 fd = _get_sock_fd_type ( s, 0, &type, &flags );
2707 TRACE("socket %04x, how %i %d %d \n", s, how, type, flags );
2709 if (fd == -1)
2710 return SOCKET_ERROR;
2712 switch( how )
2714 case 0: /* drop receives */
2715 clear_flags |= FD_READ;
2716 break;
2717 case 1: /* drop sends */
2718 clear_flags |= FD_WRITE;
2719 break;
2720 case 2: /* drop all */
2721 clear_flags |= FD_READ|FD_WRITE;
2722 default:
2723 clear_flags |= FD_WINE_LISTENING;
2726 if ( flags & FD_FLAG_OVERLAPPED ) {
2728 switch ( how )
2730 case SD_RECEIVE:
2731 fd0 = fd;
2732 break;
2733 case SD_SEND:
2734 fd1 = fd;
2735 break;
2736 case SD_BOTH:
2737 default:
2738 fd0 = fd;
2739 fd1 = _get_sock_fd ( s );
2742 if ( fd0 != -1 )
2744 err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
2745 if ( err )
2747 close ( fd0 );
2748 goto error;
2751 if ( fd1 != -1 )
2753 err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
2754 if ( err )
2756 close ( fd1 );
2757 goto error;
2761 else /* non-overlapped mode */
2763 if ( shutdown( fd, how ) )
2765 err = wsaErrno ();
2766 close ( fd );
2767 goto error;
2769 close(fd);
2772 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2773 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2774 return 0;
2776 error:
2777 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2778 WSASetLastError ( err );
2779 return SOCKET_ERROR;
2782 /***********************************************************************
2783 * shutdown (WINSOCK.22)
2785 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2787 return (INT16)WS_shutdown( s, how );
2791 /***********************************************************************
2792 * socket (WS2_32.23)
2794 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2796 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2798 return WSASocketA ( af, type, protocol, NULL, 0,
2799 (TlsGetValue(opentype_tls_index) ? 0 : WSA_FLAG_OVERLAPPED) );
2802 /***********************************************************************
2803 * socket (WINSOCK.23)
2805 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2807 return (SOCKET16)WS_socket( af, type, protocol );
2811 /* ----------------------------------- DNS services
2813 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2814 * Also, we have to use wsock32 stubs to convert structures and
2815 * error codes from Unix to WSA, hence there is no direct mapping in
2816 * the relay32/wsock32.spec.
2820 /***********************************************************************
2821 * __ws_gethostbyaddr
2823 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2825 WIN_hostent *retval = NULL;
2827 struct hostent* host;
2828 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2829 char *extrabuf;
2830 int ebufsize=1024;
2831 struct hostent hostentry;
2832 int locerr=ENOBUFS;
2833 host = NULL;
2834 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2835 while(extrabuf) {
2836 int res = gethostbyaddr_r(addr, len, type,
2837 &hostentry, extrabuf, ebufsize, &host, &locerr);
2838 if( res != ERANGE) break;
2839 ebufsize *=2;
2840 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2842 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2843 #else
2844 EnterCriticalSection( &csWSgetXXXbyYYY );
2845 host = gethostbyaddr(addr, len, type);
2846 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2847 #endif
2848 if( host != NULL )
2850 if( WS_dup_he(host, dup_flag) )
2851 retval = he_buffer;
2852 else
2853 SetLastError(WSAENOBUFS);
2855 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2856 HeapFree(GetProcessHeap(),0,extrabuf);
2857 #else
2858 LeaveCriticalSection( &csWSgetXXXbyYYY );
2859 #endif
2860 return retval;
2863 /***********************************************************************
2864 * gethostbyaddr (WINSOCK.51)
2866 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2868 TRACE("ptr %p, len %d, type %d\n", addr, len, type);
2869 if (!__ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR )) return 0;
2870 return he_buffer_seg;
2873 /***********************************************************************
2874 * gethostbyaddr (WS2_32.51)
2876 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len,
2877 int type)
2879 TRACE("ptr %08x, len %d, type %d\n",
2880 (unsigned) addr, len, type);
2881 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2884 /***********************************************************************
2885 * __ws_gethostbyname
2887 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2889 WIN_hostent *retval = NULL;
2890 struct hostent* host;
2891 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2892 char *extrabuf;
2893 int ebufsize=1024;
2894 struct hostent hostentry;
2895 int locerr = ENOBUFS;
2896 host = NULL;
2897 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2898 while(extrabuf) {
2899 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2900 if( res != ERANGE) break;
2901 ebufsize *=2;
2902 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2904 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2905 #else
2906 EnterCriticalSection( &csWSgetXXXbyYYY );
2907 host = gethostbyname(name);
2908 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2909 #endif
2910 if( host != NULL )
2912 if( WS_dup_he(host, dup_flag) )
2913 retval = he_buffer;
2914 else SetLastError(WSAENOBUFS);
2916 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2917 HeapFree(GetProcessHeap(),0,extrabuf);
2918 #else
2919 LeaveCriticalSection( &csWSgetXXXbyYYY );
2920 #endif
2921 return retval;
2924 /***********************************************************************
2925 * gethostbyname (WINSOCK.52)
2927 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2929 TRACE( "%s\n", debugstr_a(name) );
2930 if (!__ws_gethostbyname( name, WS_DUP_SEGPTR )) return 0;
2931 return he_buffer_seg;
2934 /***********************************************************************
2935 * gethostbyname (WS2_32.52)
2937 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2939 TRACE( "%s\n", debugstr_a(name) );
2940 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2944 /***********************************************************************
2945 * __ws_getprotobyname
2947 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2949 WIN_protoent* retval = NULL;
2950 #ifdef HAVE_GETPROTOBYNAME
2951 struct protoent* proto;
2952 EnterCriticalSection( &csWSgetXXXbyYYY );
2953 if( (proto = getprotobyname(name)) != NULL )
2955 if( WS_dup_pe(proto, dup_flag) )
2956 retval = pe_buffer;
2957 else SetLastError(WSAENOBUFS);
2959 else {
2960 MESSAGE("protocol %s not found; You might want to add "
2961 "this to /etc/protocols\n", debugstr_a(name) );
2962 SetLastError(WSANO_DATA);
2964 LeaveCriticalSection( &csWSgetXXXbyYYY );
2965 #endif
2966 return retval;
2969 /***********************************************************************
2970 * getprotobyname (WINSOCK.53)
2972 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2974 TRACE( "%s\n", debugstr_a(name) );
2975 if (!__ws_getprotobyname(name, WS_DUP_SEGPTR)) return 0;
2976 return pe_buffer_seg;
2979 /***********************************************************************
2980 * getprotobyname (WS2_32.53)
2982 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
2984 TRACE( "%s\n", debugstr_a(name) );
2985 return __ws_getprotobyname(name, WS_DUP_LINEAR);
2989 /***********************************************************************
2990 * __ws_getprotobynumber
2992 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2994 WIN_protoent* retval = NULL;
2995 #ifdef HAVE_GETPROTOBYNUMBER
2996 struct protoent* proto;
2997 EnterCriticalSection( &csWSgetXXXbyYYY );
2998 if( (proto = getprotobynumber(number)) != NULL )
3000 if( WS_dup_pe(proto, dup_flag) )
3001 retval = pe_buffer;
3002 else SetLastError(WSAENOBUFS);
3004 else {
3005 MESSAGE("protocol number %d not found; You might want to add "
3006 "this to /etc/protocols\n", number );
3007 SetLastError(WSANO_DATA);
3009 LeaveCriticalSection( &csWSgetXXXbyYYY );
3010 #endif
3011 return retval;
3014 /***********************************************************************
3015 * getprotobynumber (WINSOCK.54)
3017 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
3019 TRACE("%i\n", number);
3020 if (!__ws_getprotobynumber(number, WS_DUP_SEGPTR)) return 0;
3021 return pe_buffer_seg;
3024 /***********************************************************************
3025 * getprotobynumber (WS2_32.54)
3027 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
3029 TRACE("%i\n", number);
3030 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
3034 /***********************************************************************
3035 * __ws_getservbyname
3037 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
3039 WIN_servent* retval = NULL;
3040 struct servent* serv;
3041 int i = wsi_strtolo( name, proto );
3043 if( i ) {
3044 EnterCriticalSection( &csWSgetXXXbyYYY );
3045 serv = getservbyname(local_buffer,
3046 proto && *proto ? (local_buffer + i) : NULL);
3047 if( serv != NULL )
3049 if( WS_dup_se(serv, dup_flag) )
3050 retval = se_buffer;
3051 else SetLastError(WSAENOBUFS);
3053 else {
3054 MESSAGE("service %s protocol %s not found; You might want to add "
3055 "this to /etc/services\n", debugstr_a(local_buffer),
3056 proto ? debugstr_a(local_buffer+i):"*");
3057 SetLastError(WSANO_DATA);
3059 LeaveCriticalSection( &csWSgetXXXbyYYY );
3061 else SetLastError(WSAENOBUFS);
3062 return retval;
3065 /***********************************************************************
3066 * getservbyname (WINSOCK.55)
3068 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
3070 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3071 if (!__ws_getservbyname(name, proto, WS_DUP_SEGPTR)) return 0;
3072 return se_buffer_seg;
3075 /***********************************************************************
3076 * getservbyname (WS2_32.55)
3078 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
3080 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3081 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
3085 /***********************************************************************
3086 * __ws_getservbyport
3088 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
3090 WIN_servent* retval = NULL;
3091 #ifdef HAVE_GETSERVBYPORT
3092 struct servent* serv;
3093 if (!proto || wsi_strtolo( proto, NULL )) {
3094 EnterCriticalSection( &csWSgetXXXbyYYY );
3095 if( (serv = getservbyport(port, proto && *proto ? local_buffer :
3096 NULL)) != NULL ) {
3097 if( WS_dup_se(serv, dup_flag) )
3098 retval = se_buffer;
3099 else SetLastError(WSAENOBUFS);
3101 else {
3102 MESSAGE("service on port %lu protocol %s not found; You might want to add "
3103 "this to /etc/services\n", (unsigned long)ntohl(port),
3104 proto ? debugstr_a(local_buffer) : "*");
3105 SetLastError(WSANO_DATA);
3107 LeaveCriticalSection( &csWSgetXXXbyYYY );
3109 else SetLastError(WSAENOBUFS);
3110 #endif
3111 return retval;
3114 /***********************************************************************
3115 * getservbyport (WINSOCK.56)
3117 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
3119 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3120 if (!__ws_getservbyport(port, proto, WS_DUP_SEGPTR)) return 0;
3121 return se_buffer_seg;
3124 /***********************************************************************
3125 * getservbyport (WS2_32.56)
3127 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
3129 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3130 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
3134 /***********************************************************************
3135 * gethostname (WS2_32.57)
3137 int WINAPI WS_gethostname(char *name, int namelen)
3139 TRACE("name %p, len %d\n", name, namelen);
3141 if (gethostname(name, namelen) == 0)
3143 TRACE("<- '%s'\n", name);
3144 return 0;
3146 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
3147 TRACE("<- ERROR !\n");
3148 return SOCKET_ERROR;
3151 /***********************************************************************
3152 * gethostname (WINSOCK.57)
3154 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
3156 return (INT16)WS_gethostname(name, namelen);
3160 /* ------------------------------------- Windows sockets extensions -- *
3162 * ------------------------------------------------------------------- */
3164 /***********************************************************************
3165 * WSAEnumNetworkEvents (WS2_32.36)
3167 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
3169 int ret;
3171 TRACE("%08x, hEvent %p, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
3173 SERVER_START_REQ( get_socket_event )
3175 req->handle = SOCKET2HANDLE(s);
3176 req->service = TRUE;
3177 req->c_event = hEvent;
3178 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
3179 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
3181 SERVER_END_REQ;
3182 if (!ret) return 0;
3183 SetLastError(WSAEINVAL);
3184 return SOCKET_ERROR;
3187 /***********************************************************************
3188 * WSAEventSelect (WS2_32.39)
3190 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
3192 int ret;
3194 TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
3196 SERVER_START_REQ( set_socket_event )
3198 req->handle = SOCKET2HANDLE(s);
3199 req->mask = lEvent;
3200 req->event = hEvent;
3201 req->window = 0;
3202 req->msg = 0;
3203 ret = wine_server_call( req );
3205 SERVER_END_REQ;
3206 if (!ret) return 0;
3207 SetLastError(WSAEINVAL);
3208 return SOCKET_ERROR;
3211 /**********************************************************************
3212 * WSAGetOverlappedResult (WS2_32.40)
3214 BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
3215 LPDWORD lpcbTransfer, BOOL fWait,
3216 LPDWORD lpdwFlags )
3218 DWORD r;
3220 TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
3221 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
3223 if ( !(lpOverlapped && lpOverlapped->hEvent) )
3225 ERR ( "Invalid pointer\n" );
3226 WSASetLastError (WSA_INVALID_PARAMETER);
3227 return FALSE;
3230 if ( fWait )
3232 while ( WaitForSingleObjectEx (lpOverlapped->hEvent, INFINITE, TRUE) == STATUS_USER_APC );
3234 else if ( lpOverlapped->Internal == STATUS_PENDING )
3236 /* Wait in order to give APCs a chance to run. */
3237 /* This is cheating, so we must set the event again in case of success -
3238 it may be a non-manual reset event. */
3239 while ( (r = WaitForSingleObjectEx (lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
3240 if ( r == WAIT_OBJECT_0 )
3241 NtSetEvent ( lpOverlapped->hEvent, NULL );
3244 if ( lpcbTransfer )
3245 *lpcbTransfer = lpOverlapped->InternalHigh;
3247 if ( lpdwFlags )
3248 *lpdwFlags = lpOverlapped->Offset;
3250 switch ( lpOverlapped->Internal )
3252 case STATUS_SUCCESS:
3253 return TRUE;
3254 case STATUS_PENDING:
3255 WSASetLastError ( WSA_IO_INCOMPLETE );
3256 if (fWait) ERR ("PENDING status after waiting!\n");
3257 return FALSE;
3258 default:
3259 WSASetLastError ( NtStatusToWSAError ( lpOverlapped->Internal ));
3260 return FALSE;
3265 /***********************************************************************
3266 * WSAAsyncSelect (WS2_32.101)
3268 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
3270 int ret;
3272 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3274 SERVER_START_REQ( set_socket_event )
3276 req->handle = SOCKET2HANDLE(s);
3277 req->mask = lEvent;
3278 req->event = 0;
3279 req->window = hWnd;
3280 req->msg = uMsg;
3281 ret = wine_server_call( req );
3283 SERVER_END_REQ;
3284 if (!ret) return 0;
3285 SetLastError(WSAEINVAL);
3286 return SOCKET_ERROR;
3289 /***********************************************************************
3290 * WSAAsyncSelect (WINSOCK.101)
3292 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
3294 return (INT16)WSAAsyncSelect( s, HWND_32(hWnd), wMsg, lEvent );
3297 /***********************************************************************
3298 * WSARecvEx (WINSOCK.1107)
3300 * See description for WSARecvEx()
3302 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags)
3304 FIXME("(WSARecvEx16) partial packet return value not set \n");
3306 return WINSOCK_recv16(s, buf, len, *flags);
3310 /***********************************************************************
3311 * WSACreateEvent (WS2_32.31)
3314 WSAEVENT WINAPI WSACreateEvent(void)
3316 /* Create a manual-reset event, with initial state: unsignealed */
3317 TRACE("\n");
3319 return CreateEventA(NULL, TRUE, FALSE, NULL);
3322 /***********************************************************************
3323 * WSACloseEvent (WS2_32.29)
3326 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3328 TRACE ("event=%p\n", event);
3330 return CloseHandle(event);
3333 /***********************************************************************
3334 * WSASocketA (WS2_32.78)
3337 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3338 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3339 GROUP g, DWORD dwFlags)
3341 SOCKET ret;
3344 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
3345 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3348 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3349 af, type, protocol, lpProtocolInfo, g, dwFlags );
3351 /* hack for WSADuplicateSocket */
3352 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3353 ret = lpProtocolInfo->dwCatalogEntryId;
3354 TRACE("\tgot duplicate %04x\n", ret);
3355 return ret;
3358 /* check the socket family */
3359 switch(af)
3361 #ifdef HAVE_IPX
3362 case WS_AF_IPX: af = AF_IPX;
3363 #endif
3364 case AF_INET:
3365 case AF_UNSPEC:
3366 break;
3367 default:
3368 SetLastError(WSAEAFNOSUPPORT);
3369 return INVALID_SOCKET;
3372 /* check the socket type */
3373 switch(type)
3375 case WS_SOCK_STREAM:
3376 type=SOCK_STREAM;
3377 break;
3378 case WS_SOCK_DGRAM:
3379 type=SOCK_DGRAM;
3380 break;
3381 case WS_SOCK_RAW:
3382 type=SOCK_RAW;
3383 break;
3384 default:
3385 SetLastError(WSAESOCKTNOSUPPORT);
3386 return INVALID_SOCKET;
3389 /* check the protocol type */
3390 if ( protocol < 0 ) /* don't support negative values */
3392 SetLastError(WSAEPROTONOSUPPORT);
3393 return INVALID_SOCKET;
3396 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3397 switch(protocol)
3399 case IPPROTO_TCP:
3400 if (type == SOCK_STREAM) { af = AF_INET; break; }
3401 case IPPROTO_UDP:
3402 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3403 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3406 SERVER_START_REQ( create_socket )
3408 req->family = af;
3409 req->type = type;
3410 req->protocol = protocol;
3411 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3412 req->flags = dwFlags;
3413 req->inherit = TRUE;
3414 set_error( wine_server_call( req ) );
3415 ret = HANDLE2SOCKET( reply->handle );
3417 SERVER_END_REQ;
3418 if (ret)
3420 TRACE("\tcreated %04x\n", ret );
3421 return ret;
3424 if (GetLastError() == WSAEACCES) /* raw socket denied */
3426 if (type == SOCK_RAW)
3427 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3428 else
3429 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3430 SetLastError(WSAESOCKTNOSUPPORT);
3433 WARN("\t\tfailed!\n");
3434 return INVALID_SOCKET;
3438 /***********************************************************************
3439 * __WSAFDIsSet (WINSOCK.151)
3441 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
3443 int i = set->fd_count;
3445 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3447 while (i--)
3448 if (set->fd_array[i] == s) return 1;
3449 return 0;
3452 /***********************************************************************
3453 * __WSAFDIsSet (WS2_32.151)
3455 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3457 int i = set->fd_count;
3459 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3461 while (i--)
3462 if (set->fd_array[i] == s) return 1;
3463 return 0;
3466 /***********************************************************************
3467 * WSAIsBlocking (WINSOCK.114)
3468 * WSAIsBlocking (WS2_32.114)
3470 BOOL WINAPI WSAIsBlocking(void)
3472 /* By default WinSock should set all its sockets to non-blocking mode
3473 * and poll in PeekMessage loop when processing "blocking" ones. This
3474 * function is supposed to tell if the program is in this loop. Our
3475 * blocking calls are truly blocking so we always return FALSE.
3477 * Note: It is allowed to call this function without prior WSAStartup().
3480 TRACE("\n");
3481 return FALSE;
3484 /***********************************************************************
3485 * WSACancelBlockingCall (WINSOCK.113)
3486 * WSACancelBlockingCall (WS2_32.113)
3488 INT WINAPI WSACancelBlockingCall(void)
3490 TRACE("\n");
3491 return 0;
3495 /***********************************************************************
3496 * WSASetBlockingHook (WINSOCK.109)
3498 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
3500 FARPROC16 prev = (FARPROC16)blocking_hook;
3501 blocking_hook = (FARPROC)lpBlockFunc;
3502 TRACE("hook %p\n", lpBlockFunc);
3503 return prev;
3507 /***********************************************************************
3508 * WSASetBlockingHook (WS2_32.109)
3510 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3512 FARPROC prev = blocking_hook;
3513 blocking_hook = lpBlockFunc;
3514 TRACE("hook %p\n", lpBlockFunc);
3515 return prev;
3519 /***********************************************************************
3520 * WSAUnhookBlockingHook (WINSOCK.110)
3522 INT16 WINAPI WSAUnhookBlockingHook16(void)
3524 blocking_hook = NULL;
3525 return 0;
3529 /***********************************************************************
3530 * WSAUnhookBlockingHook (WS2_32.110)
3532 INT WINAPI WSAUnhookBlockingHook(void)
3534 blocking_hook = NULL;
3535 return 0;
3539 /* ----------------------------------- end of API stuff */
3541 /* ----------------------------------- helper functions -
3543 * TODO: Merge WS_dup_..() stuff into one function that
3544 * would operate with a generic structure containing internal
3545 * pointers (via a template of some kind).
3548 static int list_size(char** l, int item_size)
3550 int i,j = 0;
3551 if(l)
3552 { for(i=0;l[i];i++)
3553 j += (item_size) ? item_size : strlen(l[i]) + 1;
3554 j += (i + 1) * sizeof(char*); }
3555 return j;
3558 static int list_dup(char** l_src, char* ref, char* base, int item_size)
3560 /* base is either either equal to ref or 0 or SEGPTR */
3562 char* p = ref;
3563 char** l_to = (char**)ref;
3564 int i,j,k;
3566 for(j=0;l_src[j];j++) ;
3567 p += (j + 1) * sizeof(char*);
3568 for(i=0;i<j;i++)
3569 { l_to[i] = base + (p - ref);
3570 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3571 memcpy(p, l_src[i], k); p += k; }
3572 l_to[i] = NULL;
3573 return (p - ref);
3576 /* ----- hostent */
3578 static int hostent_size(struct hostent* p_he)
3580 int size = 0;
3581 if( p_he )
3582 { size = sizeof(struct hostent);
3583 size += strlen(p_he->h_name) + 1;
3584 size += list_size(p_he->h_aliases, 0);
3585 size += list_size(p_he->h_addr_list, p_he->h_length ); }
3586 return size;
3589 /* duplicate hostent entry
3590 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3591 * Dito for protoent and servent.
3593 static int WS_dup_he(struct hostent* p_he, int flag)
3595 /* Convert hostent structure into ws_hostent so that the data fits
3596 * into local_buffer. Internal pointers can be linear, SEGPTR, or
3597 * relative to local_buffer depending on "flag" value. Returns size
3598 * of the data copied.
3601 int size = hostent_size(p_he);
3602 if( size )
3604 char *p_name,*p_aliases,*p_addr,*p_base,*p;
3605 char *p_to;
3606 struct ws_hostent16 *p_to16;
3607 struct WS_hostent *p_to32;
3609 check_buffer_he(size);
3610 p_to = he_buffer;
3611 p_to16 = he_buffer;
3612 p_to32 = he_buffer;
3614 p = p_to;
3615 p_base = (flag & WS_DUP_SEGPTR) ? (char*)he_buffer_seg : he_buffer;
3616 p += (flag & WS_DUP_SEGPTR) ?
3617 sizeof(struct ws_hostent16) : sizeof(struct WS_hostent);
3618 p_name = p;
3619 strcpy(p, p_he->h_name); p += strlen(p) + 1;
3620 p_aliases = p;
3621 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3622 p_addr = p;
3623 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
3625 if (flag & WS_DUP_SEGPTR) /* Win16 */
3627 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
3628 p_to16->h_length = (INT16)p_he->h_length;
3629 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3630 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3631 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3632 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3634 else /* Win32 */
3636 p_to32->h_addrtype = p_he->h_addrtype;
3637 p_to32->h_length = p_he->h_length;
3638 p_to32->h_name = (p_base + (p_name - p_to));
3639 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3640 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3641 size += (sizeof(struct WS_hostent) - sizeof(struct hostent));
3644 return size;
3647 /* ----- protoent */
3649 static int protoent_size(struct protoent* p_pe)
3651 int size = 0;
3652 if( p_pe )
3653 { size = sizeof(struct protoent);
3654 size += strlen(p_pe->p_name) + 1;
3655 size += list_size(p_pe->p_aliases, 0); }
3656 return size;
3659 static int WS_dup_pe(struct protoent* p_pe, int flag)
3661 int size = protoent_size(p_pe);
3662 if( size )
3664 char *p_to;
3665 struct ws_protoent16 *p_to16;
3666 struct WS_protoent *p_to32;
3667 char *p_name,*p_aliases,*p_base,*p;
3669 check_buffer_pe(size);
3670 p_to = pe_buffer;
3671 p_to16 = pe_buffer;
3672 p_to32 = pe_buffer;
3673 p = p_to;
3674 p_base = (flag & WS_DUP_SEGPTR) ? (char*)pe_buffer_seg : pe_buffer;
3675 p += (flag & WS_DUP_SEGPTR) ?
3676 sizeof(struct ws_protoent16) : sizeof(struct WS_protoent);
3677 p_name = p;
3678 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3679 p_aliases = p;
3680 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3682 if (flag & WS_DUP_SEGPTR) /* Win16 */
3684 p_to16->p_proto = (INT16)p_pe->p_proto;
3685 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3686 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3687 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3689 else /* Win32 */
3691 p_to32->p_proto = p_pe->p_proto;
3692 p_to32->p_name = (p_base) + (p_name - p_to);
3693 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3694 size += (sizeof(struct WS_protoent) - sizeof(struct protoent));
3697 return size;
3700 /* ----- servent */
3702 static int servent_size(struct servent* p_se)
3704 int size = 0;
3705 if( p_se )
3706 { size += sizeof(struct servent);
3707 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3708 size += list_size(p_se->s_aliases, 0); }
3709 return size;
3712 static int WS_dup_se(struct servent* p_se, int flag)
3714 int size = servent_size(p_se);
3715 if( size )
3717 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3718 char *p_to;
3719 struct ws_servent16 *p_to16;
3720 struct WS_servent *p_to32;
3722 check_buffer_se(size);
3723 p_to = se_buffer;
3724 p_to16 = se_buffer;
3725 p_to32 = se_buffer;
3726 p = p_to;
3727 p_base = (flag & WS_DUP_SEGPTR) ? (char*)se_buffer_seg : se_buffer;
3728 p += (flag & WS_DUP_SEGPTR) ?
3729 sizeof(struct ws_servent16) : sizeof(struct WS_servent);
3730 p_name = p;
3731 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3732 p_proto = p;
3733 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3734 p_aliases = p;
3735 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3737 if (flag & WS_DUP_SEGPTR) /* Win16 */
3739 p_to16->s_port = (INT16)p_se->s_port;
3740 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3741 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3742 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3743 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3745 else /* Win32 */
3747 p_to32->s_port = p_se->s_port;
3748 p_to32->s_name = (p_base + (p_name - p_to));
3749 p_to32->s_proto = (p_base + (p_proto - p_to));
3750 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3751 size += (sizeof(struct WS_servent) - sizeof(struct servent));
3754 return size;
3757 /* ----------------------------------- error handling */
3759 UINT16 wsaErrno(void)
3761 int loc_errno = errno;
3762 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3764 switch(loc_errno)
3766 case EINTR: return WSAEINTR;
3767 case EBADF: return WSAEBADF;
3768 case EPERM:
3769 case EACCES: return WSAEACCES;
3770 case EFAULT: return WSAEFAULT;
3771 case EINVAL: return WSAEINVAL;
3772 case EMFILE: return WSAEMFILE;
3773 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3774 case EINPROGRESS: return WSAEINPROGRESS;
3775 case EALREADY: return WSAEALREADY;
3776 case ENOTSOCK: return WSAENOTSOCK;
3777 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3778 case EMSGSIZE: return WSAEMSGSIZE;
3779 case EPROTOTYPE: return WSAEPROTOTYPE;
3780 case ENOPROTOOPT: return WSAENOPROTOOPT;
3781 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3782 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3783 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3784 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3785 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3786 case EADDRINUSE: return WSAEADDRINUSE;
3787 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3788 case ENETDOWN: return WSAENETDOWN;
3789 case ENETUNREACH: return WSAENETUNREACH;
3790 case ENETRESET: return WSAENETRESET;
3791 case ECONNABORTED: return WSAECONNABORTED;
3792 case EPIPE:
3793 case ECONNRESET: return WSAECONNRESET;
3794 case ENOBUFS: return WSAENOBUFS;
3795 case EISCONN: return WSAEISCONN;
3796 case ENOTCONN: return WSAENOTCONN;
3797 case ESHUTDOWN: return WSAESHUTDOWN;
3798 case ETOOMANYREFS: return WSAETOOMANYREFS;
3799 case ETIMEDOUT: return WSAETIMEDOUT;
3800 case ECONNREFUSED: return WSAECONNREFUSED;
3801 case ELOOP: return WSAELOOP;
3802 case ENAMETOOLONG: return WSAENAMETOOLONG;
3803 case EHOSTDOWN: return WSAEHOSTDOWN;
3804 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3805 case ENOTEMPTY: return WSAENOTEMPTY;
3806 #ifdef EPROCLIM
3807 case EPROCLIM: return WSAEPROCLIM;
3808 #endif
3809 #ifdef EUSERS
3810 case EUSERS: return WSAEUSERS;
3811 #endif
3812 #ifdef EDQUOT
3813 case EDQUOT: return WSAEDQUOT;
3814 #endif
3815 #ifdef ESTALE
3816 case ESTALE: return WSAESTALE;
3817 #endif
3818 #ifdef EREMOTE
3819 case EREMOTE: return WSAEREMOTE;
3820 #endif
3822 /* just in case we ever get here and there are no problems */
3823 case 0: return 0;
3824 default:
3825 WARN("Unknown errno %d!\n", loc_errno);
3826 return WSAEOPNOTSUPP;
3830 UINT16 wsaHerrno(int loc_errno)
3833 WARN("h_errno %d.\n", loc_errno);
3835 switch(loc_errno)
3837 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3838 case TRY_AGAIN: return WSATRY_AGAIN;
3839 case NO_RECOVERY: return WSANO_RECOVERY;
3840 case NO_DATA: return WSANO_DATA;
3841 case ENOBUFS: return WSAENOBUFS;
3843 case 0: return 0;
3844 default:
3845 WARN("Unknown h_errno %d!\n", loc_errno);
3846 return WSAEOPNOTSUPP;
3851 /***********************************************************************
3852 * WSARecv (WS2_32.67)
3854 int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3855 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3856 LPWSAOVERLAPPED lpOverlapped,
3857 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3859 return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3860 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3863 /***********************************************************************
3864 * WSARecvFrom (WS2_32.69)
3866 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3867 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3868 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3869 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3872 int i, n, fd, err = WSAENOTSOCK, flags, ret;
3873 struct iovec* iovec;
3874 struct ws2_async *wsa;
3875 enum fd_type type;
3877 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3878 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3879 (lpFromlen ? *lpFromlen : -1L),
3880 lpOverlapped, lpCompletionRoutine);
3882 fd = _get_sock_fd_type( s, GENERIC_READ, &type, &flags );
3883 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
3885 if (fd == -1)
3887 err = WSAGetLastError ();
3888 goto error;
3891 iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3892 if ( !iovec )
3894 err = WSAEFAULT;
3895 goto err_close;
3898 for (i = 0; i < dwBufferCount; i++)
3900 iovec[i].iov_base = lpBuffers[i].buf;
3901 iovec[i].iov_len = lpBuffers[i].len;
3904 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3906 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
3907 lpFlags, lpFrom, lpFromlen,
3908 lpOverlapped, lpCompletionRoutine );
3910 if ( !wsa )
3912 err = WSAEFAULT;
3913 goto err_free;
3916 if ( ( ret = register_new_async ( &wsa->async )) )
3918 err = NtStatusToWSAError ( ret );
3920 if ( !lpOverlapped )
3921 HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
3922 HeapFree ( GetProcessHeap(), 0, wsa );
3923 goto err_free;
3926 /* Try immediate completion */
3927 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
3929 if ( WSAGetOverlappedResult ( s, lpOverlapped,
3930 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3931 return 0;
3933 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
3934 goto error;
3937 WSASetLastError ( WSA_IO_PENDING );
3938 return SOCKET_ERROR;
3941 if ( _is_blocking(s) )
3943 /* block here */
3944 /* FIXME: OOB and exceptfds? */
3945 do_block(fd, 1);
3948 n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3949 if ( n == -1 )
3951 err = wsaErrno();
3952 goto err_free;
3955 TRACE(" -> %i bytes\n", n);
3956 *lpNumberOfBytesRecvd = n;
3958 HeapFree (GetProcessHeap(), 0, iovec);
3959 close(fd);
3960 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3962 return 0;
3964 err_free:
3965 HeapFree (GetProcessHeap(), 0, iovec);
3967 err_close:
3968 close (fd);
3970 error:
3971 WARN(" -> ERROR %d\n", err);
3972 WSASetLastError ( err );
3973 return SOCKET_ERROR;
3976 /***********************************************************************
3977 * WSCInstallProvider (WS2_32.88)
3979 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
3980 LPCWSTR lpszProviderDllPath,
3981 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
3982 DWORD dwNumberOfEntries,
3983 LPINT lpErrno )
3985 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
3986 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
3987 dwNumberOfEntries, lpErrno);
3988 *lpErrno = 0;
3989 return 0;
3993 /***********************************************************************
3994 * WSCDeinstallProvider (WS2_32.83)
3996 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
3998 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
3999 *lpErrno = 0;
4000 return 0;
4004 /***********************************************************************
4005 * WSAAccept (WS2_32.26)
4007 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
4008 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
4011 int ret = 0, size = 0;
4012 WSABUF CallerId, CallerData, CalleeId, CalleeData;
4013 /* QOS SQOS, GQOS; */
4014 GROUP g;
4015 SOCKET cs;
4016 SOCKADDR src_addr, dst_addr;
4018 TRACE("Socket %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
4019 s, addr, addrlen, lpfnCondition, dwCallbackData);
4022 size = sizeof(src_addr);
4023 cs = WS_accept(s, &src_addr, &size);
4025 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
4027 CallerId.buf = (char *)&src_addr;
4028 CallerId.len = sizeof(src_addr);
4030 CallerData.buf = NULL;
4031 CallerData.len = (ULONG)NULL;
4033 WS_getsockname(cs, &dst_addr, &size);
4035 CalleeId.buf = (char *)&dst_addr;
4036 CalleeId.len = sizeof(dst_addr);
4039 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
4040 &CalleeId, &CalleeData, &g, dwCallbackData);
4042 switch (ret)
4044 case CF_ACCEPT:
4045 if (addr && addrlen)
4046 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
4047 return cs;
4048 case CF_DEFER:
4049 SERVER_START_REQ ( set_socket_deferred )
4051 req->handle = SOCKET2HANDLE (s);
4052 req->deferred = SOCKET2HANDLE (cs);
4053 if ( !wine_server_call_err ( req ) )
4055 SetLastError ( WSATRY_AGAIN );
4056 WS_closesocket ( cs );
4059 SERVER_END_REQ;
4060 return SOCKET_ERROR;
4061 case CF_REJECT:
4062 WS_closesocket(cs);
4063 SetLastError(WSAECONNREFUSED);
4064 return SOCKET_ERROR;
4065 default:
4066 FIXME("Unknown return type from Condition function\n");
4067 SetLastError(WSAENOTSOCK);
4068 return SOCKET_ERROR;
4072 /***********************************************************************
4073 * WSAEnumProtocolsA (WS2_32.37)
4075 int WINAPI WSAEnumProtocolsA(LPINT lpiProtocols, LPWSAPROTOCOL_INFOA lpProtocolBuffer, LPDWORD lpdwBufferLength)
4077 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4078 return 0;
4081 /***********************************************************************
4082 * WSAEnumProtocolsW (WS2_32.38)
4084 int WINAPI WSAEnumProtocolsW(LPINT lpiProtocols, LPWSAPROTOCOL_INFOW lpProtocolBuffer, LPDWORD lpdwBufferLength)
4086 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4087 return 0;
4090 /***********************************************************************
4091 * WSADuplicateSocketA (WS2_32.32)
4093 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
4095 HANDLE hProcess;
4097 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
4098 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
4099 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
4100 /* I don't know what the real Windoze does next, this is a hack */
4101 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
4102 * the target use the global duplicate, or we could copy a reference to us to the structure
4103 * and let the target duplicate it from us, but let's do it as simple as possible */
4104 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
4105 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
4106 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
4107 0, FALSE, DUPLICATE_SAME_ACCESS);
4108 CloseHandle(hProcess);
4109 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
4110 return 0;
4113 /***********************************************************************
4114 * WSAInstallServiceClassA (WS2_32.48)
4116 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
4118 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
4119 WSASetLastError(WSAEACCES);
4120 return SOCKET_ERROR;
4123 /***********************************************************************
4124 * WSAInstallServiceClassW (WS2_32.49)
4126 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
4128 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
4129 WSASetLastError(WSAEACCES);
4130 return SOCKET_ERROR;
4133 /***********************************************************************
4134 * WSARemoveServiceClass (WS2_32.70)
4136 int WINAPI WSARemoveServiceClass(LPGUID info)
4138 FIXME("Request to remove service %p\n",info);
4139 WSASetLastError(WSATYPE_NOT_FOUND);
4140 return SOCKET_ERROR;