Stub implementations for WPUCompleteOverlappedRequest,
[wine/dcerpc.git] / dlls / winsock / socket.c
blob0199e824ce1087d0d0030beef72b698a2851a3de
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 <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #ifdef HAVE_SYS_IPC_H
34 # include <sys/ipc.h>
35 #endif
36 #ifdef HAVE_SYS_IOCTL_H
37 # include <sys/ioctl.h>
38 #endif
39 #ifdef HAVE_SYS_FILIO_H
40 # include <sys/filio.h>
41 #endif
42 #ifdef HAVE_SYS_SOCKIO_H
43 # include <sys/sockio.h>
44 #endif
46 #if defined(__EMX__)
47 # include <sys/so_ioctl.h>
48 #endif
50 #ifdef HAVE_SYS_PARAM_H
51 # include <sys/param.h>
52 #endif
54 #ifdef HAVE_SYS_MSG_H
55 # include <sys/msg.h>
56 #endif
57 #ifdef HAVE_SYS_WAIT_H
58 # include <sys/wait.h>
59 #endif
60 #ifdef HAVE_SYS_UIO_H
61 # include <sys/uio.h>
62 #endif
63 #ifdef HAVE_SYS_SOCKET_H
64 #include <sys/socket.h>
65 #endif
66 #ifdef HAVE_NETINET_IN_H
67 # include <netinet/in.h>
68 #endif
69 #ifdef HAVE_NETINET_TCP_H
70 # include <netinet/tcp.h>
71 #endif
72 #ifdef HAVE_ARPA_INET_H
73 # include <arpa/inet.h>
74 #endif
75 #include <ctype.h>
76 #include <fcntl.h>
77 #include <errno.h>
78 #ifdef HAVE_SYS_ERRNO_H
79 #include <sys/errno.h>
80 #endif
81 #ifdef HAVE_NETDB_H
82 #include <netdb.h>
83 #endif
84 #ifdef HAVE_UNISTD_H
85 # include <unistd.h>
86 #endif
87 #include <stdlib.h>
88 #ifdef HAVE_ARPA_NAMESER_H
89 # include <arpa/nameser.h>
90 #endif
91 #ifdef HAVE_RESOLV_H
92 # include <resolv.h>
93 #endif
94 #ifdef HAVE_NET_IF_H
95 # include <net/if.h>
96 #endif
97 #ifdef HAVE_IPX_GNU
98 # include <netipx/ipx.h>
99 # define HAVE_IPX
100 #endif
101 #ifdef HAVE_IPX_LINUX
102 # include <asm/types.h>
103 # include <linux/ipx.h>
104 # define HAVE_IPX
105 #endif
107 #ifdef HAVE_SYS_POLL_H
108 # include <sys/poll.h>
109 #endif
110 #ifdef HAVE_SYS_TIME_H
111 # include <sys/time.h>
112 #endif
114 #define NONAMELESSUNION
115 #define NONAMELESSSTRUCT
116 #include "windef.h"
117 #include "winbase.h"
118 #include "wingdi.h"
119 #include "winuser.h"
120 #include "winerror.h"
121 #include "winnls.h"
122 #include "winsock2.h"
123 #include "mswsock.h"
124 #include "ws2tcpip.h"
125 #include "wsipx.h"
126 #include "winnt.h"
127 #include "iphlpapi.h"
128 #include "thread.h"
129 #include "wine/server.h"
130 #include "wine/debug.h"
131 #include "wine/unicode.h"
133 #ifdef HAVE_IPX
134 # include "wsnwlink.h"
135 #endif
138 #ifdef __FreeBSD__
139 # define sipx_network sipx_addr.x_net
140 # define sipx_node sipx_addr.x_host.c_host
141 #endif /* __FreeBSD__ */
143 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
145 /* critical section to protect some non-rentrant net function */
146 extern CRITICAL_SECTION csWSgetXXXbyYYY;
148 inline static const char *debugstr_sockaddr( const struct WS_sockaddr *a )
150 if (!a) return "(nil)";
151 return wine_dbg_sprintf("{ family %d, address %s, port %d }",
152 ((struct sockaddr_in *)a)->sin_family,
153 inet_ntoa(((struct sockaddr_in *)a)->sin_addr),
154 ntohs(((struct sockaddr_in *)a)->sin_port));
157 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
158 #define SOCKET2HANDLE(s) ((HANDLE)(s))
159 #define HANDLE2SOCKET(h) ((SOCKET)(h))
161 /****************************************************************
162 * Async IO declarations
163 ****************************************************************/
164 #include "async.h"
166 static DWORD ws2_async_get_count (const struct async_private *ovp);
167 static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
168 static void ws2_async_cleanup ( struct async_private *ovp );
170 static struct async_ops ws2_async_ops =
172 ws2_async_get_count,
173 ws2_async_call_completion,
174 ws2_async_cleanup
177 static struct async_ops ws2_nocomp_async_ops =
179 ws2_async_get_count,
180 NULL, /* call_completion */
181 ws2_async_cleanup
184 typedef struct ws2_async
186 async_private async;
187 LPWSAOVERLAPPED user_overlapped;
188 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
189 struct iovec *iovec;
190 int n_iovecs;
191 struct WS_sockaddr *addr;
192 union {
193 int val; /* for send operations */
194 int *ptr; /* for recv operations */
195 } addrlen;
196 DWORD flags;
197 } ws2_async;
199 /****************************************************************/
201 /* ----------------------------------- internal data */
203 /* ws_... struct conversion flags */
205 typedef struct /* WSAAsyncSelect() control struct */
207 HANDLE service, event, sock;
208 HWND hWnd;
209 UINT uMsg;
210 LONG lEvent;
211 } ws_select_info;
213 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
214 #define WS_MAX_UDP_DATAGRAM 1024
215 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
217 /* hostent's, servent's and protent's are stored in one buffer per thread,
218 * as documented on MSDN for the functions that return any of the buffers */
219 struct per_thread_data
221 int opentype;
222 struct WS_hostent *he_buffer;
223 struct WS_servent *se_buffer;
224 struct WS_protoent *pe_buffer;
225 int he_len;
226 int se_len;
227 int pe_len;
230 static DWORD tls_index = TLS_OUT_OF_INDEXES; /* TLS index for per-thread data */
231 static INT num_startup; /* reference counter */
232 static FARPROC blocking_hook = WSA_DefaultBlockingHook;
234 /* function prototypes */
235 static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
236 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe);
237 static struct WS_servent *WS_dup_se(const struct servent* p_se);
239 int WSAIOCTL_GetInterfaceCount(void);
240 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
242 UINT wsaErrno(void);
243 UINT wsaHerrno(int errnr);
245 #define MAP_OPTION(opt) { WS_##opt, opt }
247 static const int ws_sock_map[][2] =
249 MAP_OPTION( SO_DEBUG ),
250 MAP_OPTION( SO_REUSEADDR ),
251 MAP_OPTION( SO_KEEPALIVE ),
252 MAP_OPTION( SO_DONTROUTE ),
253 MAP_OPTION( SO_BROADCAST ),
254 MAP_OPTION( SO_LINGER ),
255 MAP_OPTION( SO_OOBINLINE ),
256 MAP_OPTION( SO_SNDBUF ),
257 MAP_OPTION( SO_RCVBUF ),
258 MAP_OPTION( SO_ERROR ),
259 MAP_OPTION( SO_TYPE ),
260 #ifdef SO_RCVTIMEO
261 MAP_OPTION( SO_RCVTIMEO ),
262 #endif
263 #ifdef SO_SNDTIMEO
264 MAP_OPTION( SO_SNDTIMEO ),
265 #endif
266 { 0, 0 }
269 static const int ws_tcp_map[][2] =
271 #ifdef TCP_NODELAY
272 MAP_OPTION( TCP_NODELAY ),
273 #endif
274 { 0, 0 }
277 static const int ws_ip_map[][2] =
279 MAP_OPTION( IP_MULTICAST_IF ),
280 MAP_OPTION( IP_MULTICAST_TTL ),
281 MAP_OPTION( IP_MULTICAST_LOOP ),
282 MAP_OPTION( IP_ADD_MEMBERSHIP ),
283 MAP_OPTION( IP_DROP_MEMBERSHIP ),
284 MAP_OPTION( IP_OPTIONS ),
285 #ifdef IP_HDRINCL
286 MAP_OPTION( IP_HDRINCL ),
287 #endif
288 MAP_OPTION( IP_TOS ),
289 MAP_OPTION( IP_TTL ),
290 { 0, 0 }
293 inline static DWORD NtStatusToWSAError ( const DWORD status )
295 /* We only need to cover the status codes set by server async request handling */
296 DWORD wserr;
297 switch ( status )
299 case STATUS_SUCCESS: wserr = 0; break;
300 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
301 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
302 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
303 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
304 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
305 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
306 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
307 default:
308 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
309 /* It is not a NT status code but a winsock error */
310 wserr = status;
311 else
313 wserr = RtlNtStatusToDosError( status );
314 FIXME ( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
317 return wserr;
320 /* set last error code from NT status without mapping WSA errors */
321 inline static unsigned int set_error( unsigned int err )
323 if (err)
325 err = NtStatusToWSAError ( err );
326 SetLastError( err );
328 return err;
331 inline static int get_sock_fd( SOCKET s, DWORD access, int *flags )
333 int fd;
334 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, flags ) ))
335 return -1;
336 return fd;
339 inline static void release_sock_fd( SOCKET s, int fd )
341 wine_server_release_fd( SOCKET2HANDLE(s), fd );
344 static void _enable_event( HANDLE s, unsigned int event,
345 unsigned int sstate, unsigned int cstate )
347 SERVER_START_REQ( enable_socket_event )
349 req->handle = s;
350 req->mask = event;
351 req->sstate = sstate;
352 req->cstate = cstate;
353 wine_server_call( req );
355 SERVER_END_REQ;
358 static int _is_blocking(SOCKET s)
360 int ret;
361 SERVER_START_REQ( get_socket_event )
363 req->handle = SOCKET2HANDLE(s);
364 req->service = FALSE;
365 req->c_event = 0;
366 wine_server_call( req );
367 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
369 SERVER_END_REQ;
370 return ret;
373 static unsigned int _get_sock_mask(SOCKET s)
375 unsigned int ret;
376 SERVER_START_REQ( get_socket_event )
378 req->handle = SOCKET2HANDLE(s);
379 req->service = FALSE;
380 req->c_event = 0;
381 wine_server_call( req );
382 ret = reply->mask;
384 SERVER_END_REQ;
385 return ret;
388 static void _sync_sock_state(SOCKET s)
390 /* do a dummy wineserver request in order to let
391 the wineserver run through its select loop once */
392 (void)_is_blocking(s);
395 static int _get_sock_error(SOCKET s, unsigned int bit)
397 int events[FD_MAX_EVENTS];
399 SERVER_START_REQ( get_socket_event )
401 req->handle = SOCKET2HANDLE(s);
402 req->service = FALSE;
403 req->c_event = 0;
404 wine_server_set_reply( req, events, sizeof(events) );
405 wine_server_call( req );
407 SERVER_END_REQ;
408 return events[bit];
411 static struct per_thread_data *get_per_thread_data(void)
413 struct per_thread_data * ptb = TlsGetValue( tls_index );
414 /* lazy initialization */
415 if (!ptb)
417 ptb = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptb) );
418 TlsSetValue( tls_index, ptb );
420 return ptb;
423 static void free_per_thread_data(void)
425 struct per_thread_data * ptb = TlsGetValue( tls_index );
427 if (!ptb) return;
429 /* delete scratch buffers */
430 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
431 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
432 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
433 ptb->he_buffer = NULL;
434 ptb->se_buffer = NULL;
435 ptb->pe_buffer = NULL;
437 HeapFree( GetProcessHeap(), 0, ptb );
440 /***********************************************************************
441 * DllMain (WS2_32.init)
443 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
445 TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
446 switch (fdwReason) {
447 case DLL_PROCESS_ATTACH:
448 tls_index = TlsAlloc();
449 break;
450 case DLL_PROCESS_DETACH:
451 free_per_thread_data();
452 TlsFree( tls_index );
453 num_startup = 0;
454 break;
455 case DLL_THREAD_DETACH:
456 free_per_thread_data();
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 static inline BOOL is_timeout_option( int optname )
516 #ifdef SO_RCVTIMEO
517 if (optname == SO_RCVTIMEO) return TRUE;
518 #endif
519 #ifdef SO_SNDTIMEO
520 if (optname == SO_SNDTIMEO) return TRUE;
521 #endif
522 return FALSE;
525 /* ----------------------------------- Per-thread info (or per-process?) */
527 static char *strdup_lower(const char *str)
529 int i;
530 char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
532 if (ret)
534 for (i = 0; str[i]; i++) ret[i] = tolower(str[i]);
535 ret[i] = 0;
537 else SetLastError(WSAENOBUFS);
538 return ret;
541 static fd_set* fd_set_import( fd_set* fds, const WS_fd_set* wsfds, int access, int* highfd, int lfd[] )
543 /* translate Winsock fd set into local fd set */
544 if( wsfds )
546 unsigned int i;
548 FD_ZERO(fds);
549 for( i = 0; i < wsfds->fd_count; i++ )
551 int s = wsfds->fd_array[i];
552 int fd = get_sock_fd( s, access, NULL );
553 if (fd != -1)
555 lfd[ i ] = fd;
556 if( fd > *highfd ) *highfd = fd;
557 FD_SET(fd, fds);
559 else lfd[ i ] = -1;
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( const fd_set* fds, fd_set* exceptfds, WS_fd_set* wsfds, int lfd[] )
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 int i, j, count = wsfds->fd_count;
587 for( i = 0, j = 0; i < count; i++ )
589 int fd = lfd[i];
590 SOCKET s = wsfds->fd_array[i];
591 if (fd == -1) continue;
592 if( FD_ISSET(fd, fds) )
594 if ( exceptfds && sock_error_p(fd) )
596 FD_SET(fd, exceptfds);
597 num_err++;
599 else wsfds->fd_array[j++] = s;
601 release_sock_fd( s, fd );
603 wsfds->fd_count = j;
605 return num_err;
608 static void fd_set_unimport( WS_fd_set* wsfds, int lfd[] )
610 if ( wsfds )
612 unsigned int i;
614 for( i = 0; i < wsfds->fd_count; i++ )
615 if ( lfd[i] >= 0 ) release_sock_fd( wsfds->fd_array[i], lfd[i] );
616 wsfds->fd_count = 0;
620 /* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option
621 * from an fd and return the value converted to milli seconds
622 * or -1 if there is an infinite time out */
623 static inline int get_rcvsnd_timeo( int fd, int optname)
625 struct timeval tv;
626 int len = sizeof(tv);
627 int ret = getsockopt(fd, SOL_SOCKET, optname, &tv, &len);
628 if( ret >= 0)
629 ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
630 if( ret <= 0 ) /* tv == {0,0} means infinite time out */
631 return -1;
632 return ret;
635 /* macro wrappers for portability */
636 #ifdef SO_RCVTIMEO
637 #define GET_RCVTIMEO(fd) get_rcvsnd_timeo( (fd), SO_RCVTIMEO)
638 #else
639 #define GET_RCVTIMEO(fd) (-1)
640 #endif
642 #ifdef SO_SNDTIMEO
643 #define GET_SNDTIMEO(fd) get_rcvsnd_timeo( (fd), SO_SNDTIMEO)
644 #else
645 #define GET_SNDTIMEO(fd) (-1)
646 #endif
648 /* utility: given an fd, will block until one of the events occurs */
649 static inline int do_block( int fd, int events, int timeout )
651 struct pollfd pfd;
652 int ret;
654 pfd.fd = fd;
655 pfd.events = events;
657 while ((ret = poll(&pfd, 1, timeout)) < 0)
659 if (errno != EINTR)
660 return -1;
662 if( ret == 0 )
663 return 0;
664 return pfd.revents;
668 /* ----------------------------------- API -----
670 * Init / cleanup / error checking.
673 /***********************************************************************
674 * WSAStartup (WS2_32.115)
676 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
678 TRACE("verReq=%x\n", wVersionRequested);
680 if (LOBYTE(wVersionRequested) < 1)
681 return WSAVERNOTSUPPORTED;
683 if (!lpWSAData) return WSAEINVAL;
685 num_startup++;
687 /* that's the whole of the negotiation for now */
688 lpWSAData->wVersion = wVersionRequested;
689 /* return winsock information */
690 lpWSAData->wHighVersion = 0x0202;
691 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
692 strcpy(lpWSAData->szSystemStatus, "Running" );
693 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
694 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
695 /* don't do anything with lpWSAData->lpVendorInfo */
696 /* (some apps don't allocate the space for this field) */
698 TRACE("succeeded\n");
699 return 0;
703 /***********************************************************************
704 * WSACleanup (WS2_32.116)
706 INT WINAPI WSACleanup(void)
708 if (num_startup)
709 return 0;
710 SetLastError(WSANOTINITIALISED);
711 return SOCKET_ERROR;
715 /***********************************************************************
716 * WSAGetLastError (WINSOCK.111)
717 * WSAGetLastError (WS2_32.111)
719 INT WINAPI WSAGetLastError(void)
721 return GetLastError();
724 /***********************************************************************
725 * WSASetLastError (WS2_32.112)
727 void WINAPI WSASetLastError(INT iError) {
728 SetLastError(iError);
731 static struct WS_hostent *check_buffer_he(int size)
733 struct per_thread_data * ptb = get_per_thread_data();
734 if (ptb->he_buffer)
736 if (ptb->he_len >= size ) return ptb->he_buffer;
737 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
739 ptb->he_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->he_len = size) );
740 if (!ptb->he_buffer) SetLastError(WSAENOBUFS);
741 return ptb->he_buffer;
744 static struct WS_servent *check_buffer_se(int size)
746 struct per_thread_data * ptb = get_per_thread_data();
747 if (ptb->se_buffer)
749 if (ptb->se_len >= size ) return ptb->se_buffer;
750 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
752 ptb->se_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->se_len = size) );
753 if (!ptb->se_buffer) SetLastError(WSAENOBUFS);
754 return ptb->se_buffer;
757 static struct WS_protoent *check_buffer_pe(int size)
759 struct per_thread_data * ptb = get_per_thread_data();
760 if (ptb->pe_buffer)
762 if (ptb->pe_len >= size ) return ptb->pe_buffer;
763 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
765 ptb->pe_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->pe_len = size) );
766 if (!ptb->pe_buffer) SetLastError(WSAENOBUFS);
767 return ptb->pe_buffer;
770 /* ----------------------------------- i/o APIs */
772 #ifdef HAVE_IPX
773 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
774 #else
775 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
776 #endif
779 /**********************************************************************/
781 /* Returns the converted address if successful, NULL if it was too small to
782 * start with. Note that the returned pointer may be the original pointer
783 * if no conversion is necessary.
785 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
787 switch (wsaddr->sa_family)
789 #ifdef HAVE_IPX
790 case WS_AF_IPX:
792 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
793 struct sockaddr_ipx* uipx;
795 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
796 return NULL;
798 *uaddrlen=sizeof(struct sockaddr_ipx);
799 uipx=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
800 uipx->sipx_family=AF_IPX;
801 uipx->sipx_port=wsipx->sa_socket;
802 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
803 * in one go
805 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
806 #ifdef IPX_FRAME_NONE
807 uipx->sipx_type=IPX_FRAME_NONE;
808 #endif
809 return (const struct sockaddr*)uipx;
811 #endif
813 default:
814 if (wsaddrlen<sizeof(struct WS_sockaddr))
815 return NULL;
817 /* No conversion needed, just return the original address */
818 *uaddrlen=wsaddrlen;
819 return (const struct sockaddr*)wsaddr;
821 return NULL;
824 /* Allocates a Unix sockaddr structure to receive the data */
825 inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
827 if (wsaddr==NULL)
829 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
831 /* This is not strictly the right thing to do. Hope it works however */
832 *uaddrlen=0;
834 return NULL;
837 if (*wsaddrlen==0)
838 *uaddrlen=0;
839 else
840 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
842 return HeapAlloc(GetProcessHeap(), 0, *uaddrlen);
845 /* Returns 0 if successful, -1 if the buffer is too small */
846 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
848 int res;
850 switch(uaddr->sa_family)
852 #ifdef HAVE_IPX
853 case AF_IPX:
855 struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
856 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
858 res=-1;
859 switch (*wsaddrlen) /* how much can we copy? */
861 default:
862 res=0; /* enough */
863 *wsaddrlen=uaddrlen;
864 wsipx->sa_socket=uipx->sipx_port;
865 /* fall through */
866 case 13:
867 case 12:
868 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
869 /* fall through */
870 case 11:
871 case 10:
872 case 9:
873 case 8:
874 case 7:
875 case 6:
876 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
877 /* fall through */
878 case 5:
879 case 4:
880 case 3:
881 case 2:
882 wsipx->sa_family=WS_AF_IPX;
883 /* fall through */
884 case 1:
885 case 0:
886 /* way too small */
887 break;
890 break;
891 #endif
893 default:
894 /* No conversion needed */
895 memcpy(wsaddr,uaddr,*wsaddrlen);
896 if (*wsaddrlen<uaddrlen) {
897 res=-1;
898 } else {
899 *wsaddrlen=uaddrlen;
900 res=0;
903 return res;
906 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
907 * ws_sockaddr_alloc
909 inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
911 if (uaddr!=(const struct sockaddr*)wsaddr)
912 HeapFree(GetProcessHeap(), 0, (void *)uaddr);
915 /**************************************************************************
916 * Functions for handling overlapped I/O
917 **************************************************************************/
919 static DWORD ws2_async_get_count (const struct async_private *ovp)
921 return ovp->iosb->Information;
924 static void ws2_async_cleanup ( struct async_private *ap )
926 struct ws2_async *as = (struct ws2_async*) ap;
928 TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->async.iosb );
929 if ( !as->user_overlapped )
931 #if 0
932 /* FIXME: I don't think this is really used */
933 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
934 WSACloseEvent ( as->overlapped->hEvent );
935 #endif
936 HeapFree ( GetProcessHeap(), 0, as->async.iosb );
939 HeapFree ( GetProcessHeap(), 0, as->iovec );
940 HeapFree ( GetProcessHeap(), 0, as );
943 static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
945 ws2_async* as = (ws2_async*) data;
947 TRACE ("data: %p\n", as);
949 as->completion_func ( NtStatusToWSAError (as->async.iosb->u.Status),
950 as->async.iosb->Information,
951 as->user_overlapped,
952 as->flags );
953 ws2_async_cleanup ( &as->async );
956 /***********************************************************************
957 * WS2_make_async (INTERNAL)
960 static void WS2_async_recv (async_private *as);
961 static void WS2_async_send (async_private *as);
963 inline static struct ws2_async*
964 WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferCount,
965 LPDWORD lpFlags, struct WS_sockaddr *addr,
966 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
967 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
969 struct ws2_async *wsa = HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async ) );
971 TRACE ( "wsa %p\n", wsa );
973 if (!wsa)
974 return NULL;
976 wsa->async.ops = ( lpCompletionRoutine ? &ws2_async_ops : &ws2_nocomp_async_ops );
977 wsa->async.handle = (HANDLE) s;
978 wsa->async.fd = fd;
979 wsa->async.type = type;
980 switch (type)
982 case ASYNC_TYPE_READ:
983 wsa->flags = *lpFlags;
984 wsa->async.func = WS2_async_recv;
985 wsa->addrlen.ptr = addrlen;
986 break;
987 case ASYNC_TYPE_WRITE:
988 wsa->flags = 0;
989 wsa->async.func = WS2_async_send;
990 wsa->addrlen.val = *addrlen;
991 break;
992 default:
993 ERR ("Invalid async type: %d\n", type);
995 wsa->user_overlapped = lpOverlapped;
996 wsa->completion_func = lpCompletionRoutine;
997 wsa->iovec = iovec;
998 wsa->n_iovecs = dwBufferCount;
999 wsa->addr = addr;
1001 if ( lpOverlapped )
1003 wsa->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
1004 wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
1006 else
1008 wsa->async.iosb = HeapAlloc ( GetProcessHeap(), 0,
1009 sizeof (IO_STATUS_BLOCK) );
1010 if ( !wsa->async.iosb )
1011 goto error;
1012 wsa->async.event = INVALID_HANDLE_VALUE;
1015 wsa->async.iosb->Information = 0;
1016 TRACE ( "wsa %p, ops %p, h %p, ev %p, fd %d, func %p, iosb %p, uov %p, cfunc %p\n",
1017 wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
1018 wsa->async.iosb, wsa->user_overlapped, wsa->completion_func );
1020 return wsa;
1022 error:
1023 TRACE ("Error\n");
1024 HeapFree ( GetProcessHeap(), 0, wsa );
1025 return NULL;
1028 /***********************************************************************
1029 * WS2_recv (INTERNAL)
1031 * Workhorse for both synchronous and asynchronous recv() operations.
1033 static int WS2_recv ( int fd, struct iovec* iov, int count,
1034 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1035 LPDWORD lpFlags )
1037 struct msghdr hdr;
1038 int n;
1039 TRACE ( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
1040 fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
1042 hdr.msg_name = NULL;
1044 if ( lpFrom )
1046 hdr.msg_namelen = *lpFromlen;
1047 hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
1048 if ( !hdr.msg_name )
1050 WSASetLastError ( WSAEFAULT );
1051 n = -1;
1052 goto out;
1055 else
1056 hdr.msg_namelen = 0;
1058 hdr.msg_iov = iov;
1059 hdr.msg_iovlen = count;
1060 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1061 hdr.msg_accrights = NULL;
1062 hdr.msg_accrightslen = 0;
1063 #else
1064 hdr.msg_control = NULL;
1065 hdr.msg_controllen = 0;
1066 hdr.msg_flags = 0;
1067 #endif
1069 if ( (n = recvmsg (fd, &hdr, *lpFlags)) == -1 )
1071 TRACE ( "recvmsg error %d\n", errno);
1072 goto out;
1075 if ( lpFrom &&
1076 ws_sockaddr_u2ws ( hdr.msg_name, hdr.msg_namelen,
1077 lpFrom, lpFromlen ) != 0 )
1079 /* The from buffer was too small, but we read the data
1080 * anyway. Is that really bad?
1082 WSASetLastError ( WSAEFAULT );
1083 WARN ( "Address buffer too small\n" );
1086 out:
1088 ws_sockaddr_free ( hdr.msg_name, lpFrom );
1089 TRACE ("-> %d\n", n);
1090 return n;
1093 /***********************************************************************
1094 * WS2_async_recv (INTERNAL)
1096 * Handler for overlapped recv() operations.
1098 static void WS2_async_recv ( async_private *as )
1100 ws2_async* wsa = (ws2_async*) as;
1101 int result, err;
1103 TRACE ( "async %p\n", wsa );
1105 if ( wsa->async.iosb->u.Status != STATUS_PENDING )
1107 TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
1108 return;
1111 result = WS2_recv ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1112 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1114 if (result >= 0)
1116 wsa->async.iosb->u.Status = STATUS_SUCCESS;
1117 wsa->async.iosb->Information = result;
1118 TRACE ( "received %d bytes\n", result );
1119 _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
1120 return;
1123 err = wsaErrno ();
1124 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1126 wsa->async.iosb->u.Status = STATUS_PENDING;
1127 _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
1128 TRACE ( "still pending\n" );
1130 else
1132 wsa->async.iosb->u.Status = err;
1133 TRACE ( "Error: %x\n", err );
1137 /***********************************************************************
1138 * WS2_send (INTERNAL)
1140 * Workhorse for both synchronous and asynchronous send() operations.
1142 static int WS2_send ( int fd, struct iovec* iov, int count,
1143 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1145 struct msghdr hdr;
1146 int n = -1;
1147 TRACE ( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
1148 fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
1150 hdr.msg_name = NULL;
1152 if ( to )
1154 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
1155 if ( !hdr.msg_name )
1157 WSASetLastError ( WSAEFAULT );
1158 goto out;
1161 #ifdef HAVE_IPX
1162 if(to->sa_family == WS_AF_IPX)
1164 #ifdef SOL_IPX
1165 struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
1166 int val=0;
1167 int len=sizeof(int);
1169 /* The packet type is stored at the ipx socket level; At least the linux kernel seems
1170 * to do something with it in case hdr.msg_name is NULL. Nonetheless can we use it to store
1171 * the packet type and then we can retrieve it using getsockopt. After that we can set the
1172 * ipx type in the sockaddr_opx structure with the stored value.
1174 if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1)
1176 TRACE("ptype: %d (fd:%d)\n", val, fd);
1177 uipx->sipx_type = val;
1179 #endif
1181 #endif
1184 else
1185 hdr.msg_namelen = 0;
1187 hdr.msg_iov = iov;
1188 hdr.msg_iovlen = count;
1189 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1190 hdr.msg_accrights = NULL;
1191 hdr.msg_accrightslen = 0;
1192 #else
1193 hdr.msg_control = NULL;
1194 hdr.msg_controllen = 0;
1195 hdr.msg_flags = 0;
1196 #endif
1198 n = sendmsg (fd, &hdr, dwFlags);
1200 out:
1201 ws_sockaddr_free ( hdr.msg_name, to );
1202 return n;
1205 /***********************************************************************
1206 * WS2_async_send (INTERNAL)
1208 * Handler for overlapped send() operations.
1210 static void WS2_async_send ( async_private *as )
1212 ws2_async* wsa = (ws2_async*) as;
1213 int result, err;
1215 TRACE ( "async %p\n", wsa );
1217 if ( wsa->async.iosb->u.Status != STATUS_PENDING )
1219 TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
1220 return;
1223 result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1224 wsa->addr, wsa->addrlen.val, wsa->flags );
1226 if (result >= 0)
1228 wsa->async.iosb->u.Status = STATUS_SUCCESS;
1229 wsa->async.iosb->Information = result;
1230 TRACE ( "sent %d bytes\n", result );
1231 _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
1232 return;
1235 err = wsaErrno ();
1236 if ( err == WSAEINTR )
1238 wsa->async.iosb->u.Status = STATUS_PENDING;
1239 _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
1240 TRACE ( "still pending\n" );
1242 else
1244 /* We set the status to a winsock error code and check for that
1245 later in NtStatusToWSAError () */
1246 wsa->async.iosb->u.Status = err;
1247 TRACE ( "Error: %x\n", err );
1251 /***********************************************************************
1252 * WS2_async_shutdown (INTERNAL)
1254 * Handler for shutdown() operations on overlapped sockets.
1256 static void WS2_async_shutdown ( async_private *as )
1258 ws2_async* wsa = (ws2_async*) as;
1259 int err = 1;
1261 TRACE ( "async %p %d\n", wsa, wsa->async.type );
1262 switch ( wsa->async.type )
1264 case ASYNC_TYPE_READ:
1265 err = shutdown ( wsa->async.fd, 0 );
1266 break;
1267 case ASYNC_TYPE_WRITE:
1268 err = shutdown ( wsa->async.fd, 1 );
1269 break;
1270 default:
1271 ERR ("invalid type: %d\n", wsa->async.type );
1274 if ( err )
1275 wsa->async.iosb->u.Status = wsaErrno ();
1276 else
1277 wsa->async.iosb->u.Status = STATUS_SUCCESS;
1280 /***********************************************************************
1281 * WS2_register_async_shutdown (INTERNAL)
1283 * Helper function for WS_shutdown() on overlapped sockets.
1285 static int WS2_register_async_shutdown ( SOCKET s, int fd, int type )
1287 struct ws2_async *wsa;
1288 int ret, err = WSAEFAULT;
1289 DWORD dwflags = 0;
1290 int len = 0;
1291 LPWSAOVERLAPPED ovl = HeapAlloc (GetProcessHeap(), 0, sizeof ( WSAOVERLAPPED ));
1293 TRACE ("s %d fd %d type %d\n", s, fd, type);
1294 if (!ovl)
1295 goto out;
1297 ovl->hEvent = WSACreateEvent ();
1298 if ( ovl->hEvent == WSA_INVALID_EVENT )
1299 goto out_free;
1301 wsa = WS2_make_async ( s, fd, type, NULL, 0,
1302 &dwflags, NULL, &len, ovl, NULL );
1303 if ( !wsa )
1304 goto out_close;
1306 /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
1307 wsa->user_overlapped = NULL;
1308 wsa->async.func = WS2_async_shutdown;
1309 if ( (ret = register_new_async ( &wsa->async )) )
1311 err = NtStatusToWSAError ( ret );
1312 goto out;
1314 /* Try immediate completion */
1315 while ( WaitForSingleObjectEx ( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1316 return 0;
1318 out_close:
1319 WSACloseEvent ( ovl->hEvent );
1320 out_free:
1321 HeapFree ( GetProcessHeap(), 0, ovl );
1322 out:
1323 return err;
1326 /***********************************************************************
1327 * accept (WS2_32.1)
1329 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1330 int *addrlen32)
1332 SOCKET as;
1334 TRACE("socket %04x\n", s );
1335 if (_is_blocking(s))
1337 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1338 if (fd == -1) return INVALID_SOCKET;
1339 /* block here */
1340 do_block(fd, POLLIN, -1);
1341 _sync_sock_state(s); /* let wineserver notice connection */
1342 release_sock_fd( s, fd );
1343 /* retrieve any error codes from it */
1344 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1345 /* FIXME: care about the error? */
1347 SERVER_START_REQ( accept_socket )
1349 req->lhandle = SOCKET2HANDLE(s);
1350 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1351 req->inherit = TRUE;
1352 set_error( wine_server_call( req ) );
1353 as = HANDLE2SOCKET( reply->handle );
1355 SERVER_END_REQ;
1356 if (as)
1358 if (addr) WS_getpeername(as, addr, addrlen32);
1359 return as;
1361 return INVALID_SOCKET;
1364 /***********************************************************************
1365 * bind (WS2_32.2)
1367 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1369 int fd = get_sock_fd( s, 0, NULL );
1370 int res = SOCKET_ERROR;
1372 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1374 if (fd != -1)
1376 if (!name || !SUPPORTED_PF(name->sa_family))
1378 SetLastError(WSAEAFNOSUPPORT);
1380 else
1382 const struct sockaddr* uaddr;
1383 int uaddrlen;
1385 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1386 if (uaddr == NULL)
1388 SetLastError(WSAEFAULT);
1390 else
1392 if (bind(fd, uaddr, uaddrlen) < 0)
1394 int loc_errno = errno;
1395 WARN("\tfailure - errno = %i\n", errno);
1396 errno = loc_errno;
1397 switch (errno)
1399 case EBADF:
1400 SetLastError(WSAENOTSOCK);
1401 break;
1402 case EADDRNOTAVAIL:
1403 SetLastError(WSAEINVAL);
1404 break;
1405 default:
1406 SetLastError(wsaErrno());
1407 break;
1410 else
1412 res=0; /* success */
1414 ws_sockaddr_free(uaddr,name);
1417 release_sock_fd( s, fd );
1419 return res;
1422 /***********************************************************************
1423 * closesocket (WS2_32.3)
1425 int WINAPI WS_closesocket(SOCKET s)
1427 TRACE("socket %04x\n", s);
1428 if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1429 return SOCKET_ERROR;
1432 /***********************************************************************
1433 * connect (WS2_32.4)
1435 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1437 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1439 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1441 if (fd != -1)
1443 const struct sockaddr* uaddr;
1444 int uaddrlen;
1446 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1447 if (uaddr == NULL)
1449 SetLastError(WSAEFAULT);
1451 else
1453 int rc;
1455 rc=connect(fd, uaddr, uaddrlen);
1456 ws_sockaddr_free(uaddr,name);
1457 if (rc == 0)
1458 goto connect_success;
1461 if (errno == EINPROGRESS)
1463 /* tell wineserver that a connection is in progress */
1464 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1465 FD_CONNECT|FD_READ|FD_WRITE,
1466 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1467 if (_is_blocking(s))
1469 int result;
1470 /* block here */
1471 do_block(fd, POLLIN | POLLOUT, -1);
1472 _sync_sock_state(s); /* let wineserver notice connection */
1473 /* retrieve any error codes from it */
1474 result = _get_sock_error(s, FD_CONNECT_BIT);
1475 if (result)
1476 SetLastError(result);
1477 else
1479 goto connect_success;
1482 else
1484 SetLastError(WSAEWOULDBLOCK);
1487 else
1489 SetLastError(wsaErrno());
1491 release_sock_fd( s, fd );
1493 return SOCKET_ERROR;
1495 connect_success:
1496 release_sock_fd( s, fd );
1497 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1498 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1499 FD_CONNECT|FD_WINE_LISTENING);
1500 return 0;
1503 /***********************************************************************
1504 * WSAConnect (WS2_32.30)
1506 int WINAPI WSAConnect ( SOCKET s, const struct WS_sockaddr* name, int namelen,
1507 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1508 LPQOS lpSQOS, LPQOS lpGQOS )
1510 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1511 FIXME ("unsupported parameters!\n");
1512 return WS_connect ( s, name, namelen );
1516 /***********************************************************************
1517 * getpeername (WS2_32.5)
1519 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1521 int fd;
1522 int res;
1524 TRACE("socket: %04x, ptr %p, len %08x\n", s, name, *namelen);
1526 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1527 if( (name == NULL) || (namelen == NULL) )
1529 SetLastError( WSAEFAULT );
1530 return SOCKET_ERROR;
1533 fd = get_sock_fd( s, 0, NULL );
1534 res = SOCKET_ERROR;
1536 if (fd != -1)
1538 struct sockaddr* uaddr;
1539 int uaddrlen;
1541 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1542 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1544 SetLastError(wsaErrno());
1546 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1548 /* The buffer was too small */
1549 SetLastError(WSAEFAULT);
1551 else
1553 res=0;
1555 ws_sockaddr_free(uaddr,name);
1556 release_sock_fd( s, fd );
1558 return res;
1561 /***********************************************************************
1562 * getsockname (WS2_32.6)
1564 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1566 int fd;
1567 int res;
1569 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1571 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1572 if( (name == NULL) || (namelen == NULL) )
1574 SetLastError( WSAEFAULT );
1575 return SOCKET_ERROR;
1578 fd = get_sock_fd( s, 0, NULL );
1579 res = SOCKET_ERROR;
1581 if (fd != -1)
1583 struct sockaddr* uaddr;
1584 int uaddrlen;
1586 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1587 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1589 SetLastError(wsaErrno());
1591 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1593 /* The buffer was too small */
1594 SetLastError(WSAEFAULT);
1596 else
1598 res=0;
1600 ws_sockaddr_free(uaddr,name);
1601 release_sock_fd( s, fd );
1603 return res;
1606 /***********************************************************************
1607 * getsockopt (WS2_32.7)
1609 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1610 INT optname, char *optval, INT *optlen)
1612 int fd;
1613 INT ret = 0;
1615 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1616 (int) optname, (int) optval, (int) *optlen);
1617 /* SO_OPENTYPE does not require a valid socket handle. */
1618 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1620 if (!optlen || *optlen < sizeof(int) || !optval)
1622 SetLastError(WSAEFAULT);
1623 return SOCKET_ERROR;
1625 *(int *)optval = get_per_thread_data()->opentype;
1626 *optlen = sizeof(int);
1627 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1628 return 0;
1631 #ifdef HAVE_IPX
1632 if(level == NSPROTO_IPX)
1634 struct WS_sockaddr_ipx addr;
1635 IPX_ADDRESS_DATA *data;
1636 int namelen;
1637 switch(optname)
1639 case IPX_PTYPE:
1640 fd = get_sock_fd( s, 0, NULL );
1641 #ifdef SOL_IPX
1642 if(getsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
1644 return SOCKET_ERROR;
1646 #else
1648 struct ipx val;
1649 socklen_t len=sizeof(struct ipx);
1651 if(getsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, &len) == -1 )
1652 return SOCKET_ERROR;
1653 *optval = (int)val.ipx_pt;
1655 #endif
1656 TRACE("ptype: %d (fd: %d)\n", *(int*)optval, fd);
1657 release_sock_fd( s, fd );
1659 return 0;
1660 case IPX_ADDRESS:
1662 * On a Win2000 system with one network card there are usually three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
1663 * Using this call you can then retrieve info about this all. In case of Linux it is a bit different. Usually you have
1664 * only "one" device active and further it is not possible to query things like the linkspeed.
1666 FIXME("IPX_ADDRESS\n");
1667 namelen = sizeof(struct WS_sockaddr);
1668 memset(&addr, 0, sizeof(struct WS_sockaddr));
1669 WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
1671 data = (IPX_ADDRESS_DATA*)optval;
1672 memcpy(data->nodenum,&addr.sa_nodenum,sizeof(data->nodenum));
1673 memcpy(data->netnum,&addr.sa_netnum,sizeof(data->netnum));
1674 data->adapternum = 0;
1675 data->wan = FALSE; /* We are not on a wan for now .. */
1676 data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
1677 data->maxpkt = 1467; /* This value is the default one, at least on Win2k/WinXP */
1678 data->linkspeed = 100000; /* Set the line speed in 100bit/s to 10 Mbit; note 1MB = 1000kB in this case */
1679 return 0;
1680 case IPX_MAX_ADAPTER_NUM:
1681 FIXME("IPX_MAX_ADAPTER_NUM\n");
1682 *(int*)optval = 1; /* As noted under IPX_ADDRESS we have just one card. */
1684 return 0;
1685 default:
1686 FIXME("IPX optname:%x\n", optname);
1687 return SOCKET_ERROR;
1690 #endif
1692 if( (fd = get_sock_fd( s, 0, NULL )) == -1)
1693 return SOCKET_ERROR;
1695 if (!convert_sockopt(&level, &optname)) {
1696 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1697 ret = SOCKET_ERROR;
1698 } else {
1699 struct timeval tv;
1700 struct linger lingval;
1701 INT len, *plen = optlen;
1702 char *pval = optval;
1703 if(level == SOL_SOCKET && is_timeout_option(optname)) {
1704 len = sizeof(tv);
1705 plen = &len;
1706 pval = (char *) &tv;
1707 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1708 len = sizeof(lingval);
1709 plen = &len;
1710 pval = (char *) &lingval;
1712 if (getsockopt(fd, (int) level, optname, pval, plen) != 0 ) {
1713 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1714 ret = SOCKET_ERROR;
1715 } else if(level == SOL_SOCKET && is_timeout_option(optname)) {
1716 if( *optlen >= sizeof(INT) ) {
1717 *optlen = sizeof(INT);
1718 *(INT*)optval = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1719 } else {
1720 SetLastError(WSAEFAULT);
1721 ret = SOCKET_ERROR;
1723 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1724 if( *optlen >= sizeof( LINGER) ) {
1725 (( LINGER *) optval)->l_onoff = lingval.l_onoff;
1726 (( LINGER *) optval)->l_linger = lingval.l_linger;
1727 } else {
1728 SetLastError(WSAEFAULT);
1729 ret = SOCKET_ERROR;
1733 release_sock_fd( s, fd );
1734 return ret;
1738 /***********************************************************************
1739 * htonl (WINSOCK.8)
1740 * htonl (WS2_32.8)
1742 u_long WINAPI WS_htonl(u_long hostlong)
1744 return htonl(hostlong);
1748 /***********************************************************************
1749 * htons (WINSOCK.9)
1750 * htons (WS2_32.9)
1752 u_short WINAPI WS_htons(u_short hostshort)
1754 return htons(hostshort);
1757 /***********************************************************************
1758 * WSAHtonl (WS2_32.46)
1759 * From MSDN decription of error codes, this function should also
1760 * check if WinSock has been initialized and the socket is a valid
1761 * socket. But why? This function only translates a host byte order
1762 * u_long into a network byte order u_long...
1764 int WINAPI WSAHtonl(SOCKET s, u_long hostlong, u_long *lpnetlong)
1766 if (lpnetlong)
1768 *lpnetlong = htonl(hostlong);
1769 return 0;
1771 WSASetLastError(WSAEFAULT);
1772 return SOCKET_ERROR;
1775 /***********************************************************************
1776 * WSAHtons (WS2_32.47)
1777 * From MSDN decription of error codes, this function should also
1778 * check if WinSock has been initialized and the socket is a valid
1779 * socket. But why? This function only translates a host byte order
1780 * u_short into a network byte order u_short...
1782 int WINAPI WSAHtons(SOCKET s, u_short hostshort, u_short *lpnetshort)
1785 if (lpnetshort)
1787 *lpnetshort = htons(hostshort);
1788 return 0;
1790 WSASetLastError(WSAEFAULT);
1791 return SOCKET_ERROR;
1795 /***********************************************************************
1796 * inet_addr (WINSOCK.10)
1797 * inet_addr (WS2_32.11)
1799 u_long WINAPI WS_inet_addr(const char *cp)
1801 return inet_addr(cp);
1805 /***********************************************************************
1806 * ntohl (WINSOCK.14)
1807 * ntohl (WS2_32.14)
1809 u_long WINAPI WS_ntohl(u_long netlong)
1811 return ntohl(netlong);
1815 /***********************************************************************
1816 * ntohs (WINSOCK.15)
1817 * ntohs (WS2_32.15)
1819 u_short WINAPI WS_ntohs(u_short netshort)
1821 return ntohs(netshort);
1825 /***********************************************************************
1826 * inet_ntoa (WS2_32.12)
1828 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1830 /* use "buffer for dummies" here because some applications have a
1831 * propensity to decode addresses in ws_hostent structure without
1832 * saving them first...
1834 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1836 char* s = inet_ntoa(*((struct in_addr*)&in));
1837 if( s )
1839 strcpy(dbuffer, s);
1840 return dbuffer;
1842 SetLastError(wsaErrno());
1843 return NULL;
1846 /**********************************************************************
1847 * WSAIoctl (WS2_32.50)
1850 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1852 INT WINAPI WSAIoctl (SOCKET s,
1853 DWORD dwIoControlCode,
1854 LPVOID lpvInBuffer,
1855 DWORD cbInBuffer,
1856 LPVOID lpbOutBuffer,
1857 DWORD cbOutBuffer,
1858 LPDWORD lpcbBytesReturned,
1859 LPWSAOVERLAPPED lpOverlapped,
1860 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1862 int fd = get_sock_fd( s, 0, NULL );
1864 if (fd == -1) return SOCKET_ERROR;
1866 TRACE("%d, 0x%08lx, %p, %ld, %p, %ld, %p, %p, %p\n",
1867 s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpbOutBuffer,
1868 cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
1870 switch( dwIoControlCode )
1872 case SIO_GET_INTERFACE_LIST:
1874 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1875 DWORD size, numInt, apiReturn;
1877 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1879 if (!lpbOutBuffer)
1881 release_sock_fd( s, fd );
1882 WSASetLastError(WSAEFAULT);
1883 return SOCKET_ERROR;
1885 if (!lpcbBytesReturned)
1887 release_sock_fd( s, fd );
1888 WSASetLastError(WSAEFAULT);
1889 return SOCKET_ERROR;
1892 apiReturn = GetAdaptersInfo(NULL, &size);
1893 if (apiReturn == ERROR_NO_DATA)
1895 numInt = 0;
1897 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
1899 PIP_ADAPTER_INFO table = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(),0,size);
1901 if (table)
1903 if (GetAdaptersInfo(table, &size) == NO_ERROR)
1905 PIP_ADAPTER_INFO ptr;
1907 if (size*sizeof(INTERFACE_INFO)/sizeof(IP_ADAPTER_INFO) > cbOutBuffer)
1909 WARN("Buffer too small = %lu, cbOutBuffer = %lu\n", size, cbOutBuffer);
1910 HeapFree(GetProcessHeap(),0,table);
1911 release_sock_fd( s, fd );
1912 WSASetLastError(WSAEFAULT);
1913 return (SOCKET_ERROR);
1915 for (ptr = table, numInt = 0; ptr;
1916 ptr = ptr->Next, intArray++, numInt++)
1918 unsigned int addr, mask, bcast;
1919 struct ifreq ifInfo;
1921 /* Socket Status Flags */
1922 strncpy(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
1923 ifInfo.ifr_name[IFNAMSIZ-1] = '\0';
1924 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1926 ERR ("Error obtaining status flags for socket!\n");
1927 HeapFree(GetProcessHeap(),0,table);
1928 release_sock_fd( s, fd );
1929 WSASetLastError(WSAEINVAL);
1930 return (SOCKET_ERROR);
1932 else
1934 /* set flags; the values of IFF_* are not the same
1935 under Linux and Windows, therefore must generate
1936 new flags */
1937 intArray->iiFlags = 0;
1938 if (ifInfo.ifr_flags & IFF_BROADCAST)
1939 intArray->iiFlags |= WS_IFF_BROADCAST;
1940 #ifdef IFF_POINTOPOINT
1941 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
1942 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
1943 #endif
1944 if (ifInfo.ifr_flags & IFF_LOOPBACK)
1945 intArray->iiFlags |= WS_IFF_LOOPBACK;
1946 if (ifInfo.ifr_flags & IFF_UP)
1947 intArray->iiFlags |= WS_IFF_UP;
1948 if (ifInfo.ifr_flags & IFF_MULTICAST)
1949 intArray->iiFlags |= WS_IFF_MULTICAST;
1952 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
1953 mask = inet_addr(ptr->IpAddressList.IpMask.String);
1954 bcast = addr | (addr & !mask);
1955 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1956 intArray->iiAddress.AddressIn.sin_port = 0;
1957 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
1958 addr;
1959 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1960 intArray->iiNetmask.AddressIn.sin_port = 0;
1961 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
1962 mask;
1963 intArray->iiBroadcastAddress.AddressIn.sin_family =
1964 AF_INET;
1965 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
1966 intArray->iiBroadcastAddress.AddressIn.sin_addr.
1967 WS_s_addr = bcast;
1970 else
1972 ERR ("Unable to get interface table!\n");
1973 release_sock_fd( s, fd );
1974 HeapFree(GetProcessHeap(),0,table);
1975 WSASetLastError(WSAEINVAL);
1976 return (SOCKET_ERROR);
1978 HeapFree(GetProcessHeap(),0,table);
1980 else
1982 release_sock_fd( s, fd );
1983 WSASetLastError(WSAEINVAL);
1984 return (SOCKET_ERROR);
1987 else
1989 ERR ("Unable to get interface table!\n");
1990 release_sock_fd( s, fd );
1991 WSASetLastError(WSAEINVAL);
1992 return (SOCKET_ERROR);
1994 /* Calculate the size of the array being returned */
1995 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1996 break;
1999 case SIO_ADDRESS_LIST_CHANGE:
2000 FIXME("-> SIO_ADDRESS_LIST_CHANGE request: stub\n");
2001 /* FIXME: error and return code depend on whether socket was created
2002 * with WSA_FLAG_OVERLAPPED, but there is no easy way to get this */
2003 break;
2005 default:
2006 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2007 release_sock_fd( s, fd );
2008 WSASetLastError(WSAEOPNOTSUPP);
2009 return (SOCKET_ERROR);
2012 /* Function executed with no errors */
2013 release_sock_fd( s, fd );
2014 return (0);
2018 /***********************************************************************
2019 * ioctlsocket (WS2_32.10)
2021 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2023 int fd;
2024 long newcmd = cmd;
2026 TRACE("socket %04x, cmd %08lx, ptr %p\n", s, cmd, argp);
2028 switch( cmd )
2030 case WS_FIONREAD:
2031 newcmd=FIONREAD;
2032 break;
2034 case WS_FIONBIO:
2035 if( _get_sock_mask(s) )
2037 /* AsyncSelect()'ed sockets are always nonblocking */
2038 if (*argp) return 0;
2039 SetLastError(WSAEINVAL);
2040 return SOCKET_ERROR;
2042 fd = get_sock_fd( s, 0, NULL );
2043 if (fd != -1)
2045 int ret;
2046 if (*argp)
2048 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2049 ret = fcntl( fd, F_SETFL, O_NONBLOCK );
2051 else
2053 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2054 ret = fcntl( fd, F_SETFL, 0 );
2056 release_sock_fd( s, fd );
2057 if (!ret) return 0;
2058 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2060 return SOCKET_ERROR;
2062 case WS_SIOCATMARK:
2063 newcmd=SIOCATMARK;
2064 break;
2066 case WS__IOW('f',125,u_long):
2067 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2068 SetLastError(WSAEINVAL);
2069 return SOCKET_ERROR;
2071 case SIOCGIFBRDADDR:
2072 case SIOCGIFNETMASK:
2073 case SIOCGIFADDR:
2074 /* These don't need any special handling. They are used by
2075 WsControl, and are here to suppress an unnecessary warning. */
2076 break;
2078 default:
2079 /* Netscape tries hard to use bogus ioctl 0x667e */
2080 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2081 break;
2084 fd = get_sock_fd( s, 0, NULL );
2085 if (fd != -1)
2087 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2089 release_sock_fd( s, fd );
2090 return 0;
2092 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2093 release_sock_fd( s, fd );
2095 return SOCKET_ERROR;
2098 /***********************************************************************
2099 * listen (WS2_32.13)
2101 int WINAPI WS_listen(SOCKET s, int backlog)
2103 int fd = get_sock_fd( s, GENERIC_READ, NULL );
2105 TRACE("socket %04x, backlog %d\n", s, backlog);
2106 if (fd != -1)
2108 if (listen(fd, backlog) == 0)
2110 release_sock_fd( s, fd );
2111 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2112 FD_WINE_LISTENING,
2113 FD_CONNECT|FD_WINE_CONNECTED);
2114 return 0;
2116 SetLastError(wsaErrno());
2117 release_sock_fd( s, fd );
2119 return SOCKET_ERROR;
2122 /***********************************************************************
2123 * recv (WS2_32.16)
2125 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2127 DWORD n, dwFlags = flags;
2128 WSABUF wsabuf;
2130 wsabuf.len = len;
2131 wsabuf.buf = buf;
2133 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2134 return SOCKET_ERROR;
2135 else
2136 return n;
2139 /***********************************************************************
2140 * recvfrom (WS2_32.17)
2142 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2143 struct WS_sockaddr *from, int *fromlen)
2145 DWORD n, dwFlags = flags;
2146 WSABUF wsabuf;
2148 wsabuf.len = len;
2149 wsabuf.buf = buf;
2151 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2152 return SOCKET_ERROR;
2153 else
2154 return n;
2157 /***********************************************************************
2158 * select (WS2_32.18)
2160 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2161 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2162 const struct WS_timeval* ws_timeout)
2164 int highfd = 0;
2165 fd_set readfds, writefds, exceptfds;
2166 fd_set *p_read, *p_write, *p_except;
2167 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2168 struct timeval timeout, *timeoutaddr = NULL;
2170 TRACE("read %p, write %p, excp %p timeout %p\n",
2171 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2173 p_read = fd_set_import(&readfds, ws_readfds, GENERIC_READ, &highfd, readfd);
2174 p_write = fd_set_import(&writefds, ws_writefds, GENERIC_WRITE, &highfd, writefd);
2175 p_except = fd_set_import(&exceptfds, ws_exceptfds, 0, &highfd, exceptfd);
2176 if (ws_timeout)
2178 timeoutaddr = &timeout;
2179 timeout.tv_sec=ws_timeout->tv_sec;
2180 timeout.tv_usec=ws_timeout->tv_usec;
2183 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2185 fd_set_export(&readfds, p_except, ws_readfds, readfd);
2186 fd_set_export(&writefds, p_except, ws_writefds, writefd);
2188 if (p_except && ws_exceptfds)
2190 unsigned int i, j;
2192 for (i = j = 0; i < ws_exceptfds->fd_count; i++)
2194 int fd = exceptfd[i];
2195 SOCKET s = ws_exceptfds->fd_array[i];
2196 if (fd == -1) continue;
2197 if (FD_ISSET(fd, &exceptfds)) ws_exceptfds->fd_array[j++] = s;
2198 release_sock_fd( s, fd );
2200 ws_exceptfds->fd_count = j;
2202 return highfd;
2204 fd_set_unimport(ws_readfds, readfd);
2205 fd_set_unimport(ws_writefds, writefd);
2206 fd_set_unimport(ws_exceptfds, exceptfd);
2208 if( highfd == 0 ) return 0;
2209 SetLastError(wsaErrno());
2210 return SOCKET_ERROR;
2214 /***********************************************************************
2215 * send (WS2_32.19)
2217 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2219 DWORD n;
2220 WSABUF wsabuf;
2222 wsabuf.len = len;
2223 wsabuf.buf = (char*) buf;
2225 if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2226 return SOCKET_ERROR;
2227 else
2228 return n;
2231 /***********************************************************************
2232 * WSASend (WS2_32.72)
2234 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2235 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2236 LPWSAOVERLAPPED lpOverlapped,
2237 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2239 return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2240 NULL, 0, lpOverlapped, lpCompletionRoutine );
2243 /***********************************************************************
2244 * WSASendDisconnect (WS2_32.73)
2246 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2248 return WS_shutdown ( s, SD_SEND );
2252 /***********************************************************************
2253 * WSASendTo (WS2_32.74)
2255 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2256 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2257 const struct WS_sockaddr *to, int tolen,
2258 LPWSAOVERLAPPED lpOverlapped,
2259 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2261 unsigned int i;
2262 int n, fd, err = WSAENOTSOCK, flags, ret;
2263 struct iovec* iovec;
2264 struct ws2_async *wsa;
2266 TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2267 s, lpBuffers, dwBufferCount, dwFlags,
2268 to, tolen, lpOverlapped, lpCompletionRoutine);
2270 fd = get_sock_fd( s, GENERIC_WRITE, &flags );
2271 TRACE ( "fd=%d, flags=%x\n", fd, flags );
2273 if ( fd == -1 ) return SOCKET_ERROR;
2275 if (flags & FD_FLAG_SEND_SHUTDOWN)
2277 WSASetLastError ( WSAESHUTDOWN );
2278 goto err_close;
2281 if ( !lpNumberOfBytesSent )
2283 err = WSAEFAULT;
2284 goto err_close;
2287 iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
2289 if ( !iovec )
2291 err = WSAEFAULT;
2292 goto err_close;
2295 for ( i = 0; i < dwBufferCount; i++ )
2297 iovec[i].iov_base = lpBuffers[i].buf;
2298 iovec[i].iov_len = lpBuffers[i].len;
2301 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2303 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
2304 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2305 lpOverlapped, lpCompletionRoutine );
2306 if ( !wsa )
2308 err = WSAEFAULT;
2309 goto err_free;
2312 if ( ( ret = register_new_async ( &wsa->async )) )
2314 err = NtStatusToWSAError ( ret );
2316 if ( !lpOverlapped )
2317 HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
2318 HeapFree ( GetProcessHeap(), 0, wsa );
2319 goto err_free;
2322 /* Try immediate completion */
2323 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
2325 if ( WSAGetOverlappedResult ( s, lpOverlapped,
2326 lpNumberOfBytesSent, FALSE, &dwFlags) )
2327 return 0;
2329 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
2330 goto error;
2333 WSASetLastError ( WSA_IO_PENDING );
2334 return SOCKET_ERROR;
2337 if (_is_blocking(s))
2339 /* FIXME: exceptfds? */
2340 int timeout = GET_SNDTIMEO(fd);
2341 if( !do_block(fd, POLLOUT, timeout)) {
2342 err = WSAETIMEDOUT;
2343 goto err_free; /* msdn says a timeout in send is fatal */
2347 n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2348 if ( n == -1 )
2350 err = wsaErrno();
2351 if ( err == WSAEWOULDBLOCK )
2352 _enable_event (SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2353 goto err_free;
2356 TRACE(" -> %i bytes\n", n);
2357 *lpNumberOfBytesSent = n;
2359 HeapFree ( GetProcessHeap(), 0, iovec );
2360 release_sock_fd( s, fd );
2361 return 0;
2363 err_free:
2364 HeapFree ( GetProcessHeap(), 0, iovec );
2366 err_close:
2367 release_sock_fd( s, fd );
2369 error:
2370 WARN (" -> ERROR %d\n", err);
2371 WSASetLastError (err);
2372 return SOCKET_ERROR;
2375 /***********************************************************************
2376 * sendto (WS2_32.20)
2378 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2379 const struct WS_sockaddr *to, int tolen)
2381 DWORD n;
2382 WSABUF wsabuf;
2384 wsabuf.len = len;
2385 wsabuf.buf = (char*) buf;
2387 if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2388 return SOCKET_ERROR;
2389 else
2390 return n;
2393 /***********************************************************************
2394 * setsockopt (WS2_32.21)
2396 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2397 const char *optval, int optlen)
2399 int fd;
2400 int woptval;
2401 struct linger linger;
2402 struct timeval tval;
2404 TRACE("socket: %04x, level %d, name %d, ptr %p, len %d\n",
2405 s, level, optname, optval, optlen);
2407 /* SO_OPENTYPE does not require a valid socket handle. */
2408 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2410 if (optlen < sizeof(int) || !optval)
2412 SetLastError(WSAEFAULT);
2413 return SOCKET_ERROR;
2415 get_per_thread_data()->opentype = *(int *)optval;
2416 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2417 return 0;
2420 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2421 * socket. This will either not happen under windows or it is ignored in
2422 * windows (but it works in linux and therefore prevents the game from
2423 * finding games outside the current network) */
2424 if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE )
2426 FIXME("Does windows ignore SO_DONTROUTE?\n");
2427 return 0;
2430 #ifdef HAVE_IPX
2431 if(level == NSPROTO_IPX)
2433 switch(optname)
2435 case IPX_PTYPE:
2436 fd = get_sock_fd( s, 0, NULL );
2437 TRACE("trying to set IPX_PTYPE: %d (fd: %d)\n", *(int*)optval, fd);
2439 /* We try to set the ipx type on ipx socket level. */
2440 #ifdef SOL_IPX
2441 if(setsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
2443 ERR("IPX: could not set ipx option type; expect weird behaviour\n");
2444 return SOCKET_ERROR;
2446 #else
2448 struct ipx val;
2449 /* Should we retrieve val using a getsockopt call and then
2450 * set the modified one? */
2451 val.ipx_pt = *optval;
2452 setsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, sizeof(struct ipx));
2454 #endif
2455 release_sock_fd( s, fd );
2456 return 0;
2457 case IPX_FILTERPTYPE:
2458 /* Sets the receive filter packet type, at the moment we don't support it */
2459 FIXME("IPX_FILTERPTYPE: %x\n", *optval);
2461 /* Returning 0 is better for now than returning a SOCKET_ERROR */
2462 return 0;
2463 break;
2464 default:
2465 FIXME("opt_name:%x\n", optname);
2466 return SOCKET_ERROR;
2468 return 0;
2470 #endif
2472 /* Is a privileged and useless operation, so we don't. */
2473 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET))
2475 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2476 return 0;
2479 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2480 /* This is unique to WinSock and takes special conversion */
2481 linger.l_onoff = *((int*)optval) ? 0: 1;
2482 linger.l_linger = 0;
2483 optname=SO_LINGER;
2484 optval = (char*)&linger;
2485 optlen = sizeof(struct linger);
2486 level = SOL_SOCKET;
2488 else
2490 if (!convert_sockopt(&level, &optname)) {
2491 ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2492 SetLastError(WSAENOPROTOOPT);
2493 return SOCKET_ERROR;
2495 if (optname == SO_LINGER && optval) {
2496 linger.l_onoff = ((LINGER*)optval)->l_onoff;
2497 linger.l_linger = ((LINGER*)optval)->l_linger;
2498 /* FIXME: what is documented behavior if SO_LINGER optval
2499 is null?? */
2500 optval = (char*)&linger;
2501 optlen = sizeof(struct linger);
2503 else if (optval && optlen < sizeof(int))
2505 woptval= *((INT16 *) optval);
2506 optval= (char*) &woptval;
2507 optlen=sizeof(int);
2509 if (level == SOL_SOCKET && is_timeout_option(optname))
2511 if (optlen == sizeof(UINT32)) {
2512 /* WinSock passes miliseconds instead of struct timeval */
2513 tval.tv_usec = (*(PUINT32)optval % 1000) * 1000;
2514 tval.tv_sec = *(PUINT32)optval / 1000;
2515 /* min of 500 milisec */
2516 if (tval.tv_sec == 0 && tval.tv_usec < 500000)
2517 tval.tv_usec = 500000;
2518 optlen = sizeof(struct timeval);
2519 optval = (char*)&tval;
2520 } else if (optlen == sizeof(struct timeval)) {
2521 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2522 } else {
2523 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2524 return 0;
2527 if (level == SOL_SOCKET && optname == SO_RCVBUF && *(int*)optval < 2048)
2529 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2530 return 0;
2535 fd = get_sock_fd( s, 0, NULL );
2536 if (fd == -1) return SOCKET_ERROR;
2538 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2540 release_sock_fd( s, fd );
2541 return 0;
2543 TRACE("Setting socket error, %d\n", wsaErrno());
2544 SetLastError(wsaErrno());
2545 release_sock_fd( s, fd );
2546 return SOCKET_ERROR;
2549 /***********************************************************************
2550 * shutdown (WS2_32.22)
2552 int WINAPI WS_shutdown(SOCKET s, int how)
2554 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2555 unsigned int clear_flags = 0;
2557 fd = get_sock_fd( s, 0, &flags );
2558 TRACE("socket %04x, how %i %x\n", s, how, flags );
2560 if (fd == -1)
2561 return SOCKET_ERROR;
2563 switch( how )
2565 case 0: /* drop receives */
2566 clear_flags |= FD_READ;
2567 break;
2568 case 1: /* drop sends */
2569 clear_flags |= FD_WRITE;
2570 break;
2571 case 2: /* drop all */
2572 clear_flags |= FD_READ|FD_WRITE;
2573 default:
2574 clear_flags |= FD_WINE_LISTENING;
2577 if ( flags & FD_FLAG_OVERLAPPED ) {
2579 switch ( how )
2581 case SD_RECEIVE:
2582 fd0 = fd;
2583 break;
2584 case SD_SEND:
2585 fd1 = fd;
2586 break;
2587 case SD_BOTH:
2588 default:
2589 fd0 = fd;
2590 fd1 = get_sock_fd ( s, 0, NULL );
2591 break;
2594 if ( fd0 != -1 )
2596 err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
2597 if ( err )
2599 release_sock_fd( s, fd0 );
2600 goto error;
2603 if ( fd1 != -1 )
2605 err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
2606 if ( err )
2608 release_sock_fd( s, fd1 );
2609 goto error;
2613 else /* non-overlapped mode */
2615 if ( shutdown( fd, how ) )
2617 err = wsaErrno ();
2618 release_sock_fd( s, fd );
2619 goto error;
2621 release_sock_fd( s, fd );
2624 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2625 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2626 return 0;
2628 error:
2629 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2630 WSASetLastError ( err );
2631 return SOCKET_ERROR;
2634 /***********************************************************************
2635 * socket (WS2_32.23)
2637 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2639 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2641 return WSASocketA ( af, type, protocol, NULL, 0,
2642 get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
2646 /***********************************************************************
2647 * gethostbyaddr (WS2_32.51)
2649 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
2651 struct WS_hostent *retval = NULL;
2652 struct hostent* host;
2654 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2655 char *extrabuf;
2656 int ebufsize=1024;
2657 struct hostent hostentry;
2658 int locerr=ENOBUFS;
2659 host = NULL;
2660 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2661 while(extrabuf) {
2662 int res = gethostbyaddr_r(addr, len, type,
2663 &hostentry, extrabuf, ebufsize, &host, &locerr);
2664 if( res != ERANGE) break;
2665 ebufsize *=2;
2666 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2668 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2669 #else
2670 EnterCriticalSection( &csWSgetXXXbyYYY );
2671 host = gethostbyaddr(addr, len, type);
2672 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2673 #endif
2674 if( host != NULL ) retval = WS_dup_he(host);
2675 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2676 HeapFree(GetProcessHeap(),0,extrabuf);
2677 #else
2678 LeaveCriticalSection( &csWSgetXXXbyYYY );
2679 #endif
2680 TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
2681 return retval;
2684 /***********************************************************************
2685 * gethostbyname (WS2_32.52)
2687 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2689 struct WS_hostent *retval = NULL;
2690 struct hostent* host;
2691 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2692 char *extrabuf;
2693 int ebufsize=1024;
2694 struct hostent hostentry;
2695 int locerr = ENOBUFS;
2696 #endif
2697 char buf[100];
2698 if( !name) {
2699 name = buf;
2700 if( gethostname( buf, 100) == -1) {
2701 SetLastError( WSAENOBUFS); /* appropriate ? */
2702 return retval;
2705 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2706 host = NULL;
2707 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2708 while(extrabuf) {
2709 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2710 if( res != ERANGE) break;
2711 ebufsize *=2;
2712 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2714 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2715 #else
2716 EnterCriticalSection( &csWSgetXXXbyYYY );
2717 host = gethostbyname(name);
2718 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2719 #endif
2720 if (host) retval = WS_dup_he(host);
2721 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2722 HeapFree(GetProcessHeap(),0,extrabuf);
2723 #else
2724 LeaveCriticalSection( &csWSgetXXXbyYYY );
2725 #endif
2726 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2727 return retval;
2731 /***********************************************************************
2732 * getprotobyname (WS2_32.53)
2734 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
2736 struct WS_protoent* retval = NULL;
2737 #ifdef HAVE_GETPROTOBYNAME
2738 struct protoent* proto;
2739 EnterCriticalSection( &csWSgetXXXbyYYY );
2740 if( (proto = getprotobyname(name)) != NULL )
2742 retval = WS_dup_pe(proto);
2744 else {
2745 MESSAGE("protocol %s not found; You might want to add "
2746 "this to /etc/protocols\n", debugstr_a(name) );
2747 SetLastError(WSANO_DATA);
2749 LeaveCriticalSection( &csWSgetXXXbyYYY );
2750 #endif
2751 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2752 return retval;
2756 /***********************************************************************
2757 * getprotobynumber (WS2_32.54)
2759 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
2761 struct WS_protoent* retval = NULL;
2762 #ifdef HAVE_GETPROTOBYNUMBER
2763 struct protoent* proto;
2764 EnterCriticalSection( &csWSgetXXXbyYYY );
2765 if( (proto = getprotobynumber(number)) != NULL )
2767 retval = WS_dup_pe(proto);
2769 else {
2770 MESSAGE("protocol number %d not found; You might want to add "
2771 "this to /etc/protocols\n", number );
2772 SetLastError(WSANO_DATA);
2774 LeaveCriticalSection( &csWSgetXXXbyYYY );
2775 #endif
2776 TRACE("%i ret %p\n", number, retval);
2777 return retval;
2781 /***********************************************************************
2782 * getservbyname (WS2_32.55)
2784 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
2786 struct WS_servent* retval = NULL;
2787 struct servent* serv;
2788 char *name_str;
2789 char *proto_str = NULL;
2791 if (!(name_str = strdup_lower(name))) return NULL;
2793 if (proto && *proto)
2795 if (!(proto_str = strdup_lower(proto)))
2797 HeapFree( GetProcessHeap(), 0, name_str );
2798 return NULL;
2802 EnterCriticalSection( &csWSgetXXXbyYYY );
2803 serv = getservbyname(name_str, proto_str);
2804 if( serv != NULL )
2806 retval = WS_dup_se(serv);
2808 else SetLastError(WSANO_DATA);
2809 LeaveCriticalSection( &csWSgetXXXbyYYY );
2810 HeapFree( GetProcessHeap(), 0, proto_str );
2811 HeapFree( GetProcessHeap(), 0, name_str );
2812 TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
2813 return retval;
2817 /***********************************************************************
2818 * getservbyport (WS2_32.56)
2820 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
2822 struct WS_servent* retval = NULL;
2823 #ifdef HAVE_GETSERVBYPORT
2824 struct servent* serv;
2825 char *proto_str = NULL;
2827 if (proto && *proto)
2829 if (!(proto_str = strdup_lower(proto))) return NULL;
2831 EnterCriticalSection( &csWSgetXXXbyYYY );
2832 if( (serv = getservbyport(port, proto_str)) != NULL ) {
2833 retval = WS_dup_se(serv);
2835 else SetLastError(WSANO_DATA);
2836 LeaveCriticalSection( &csWSgetXXXbyYYY );
2837 HeapFree( GetProcessHeap(), 0, proto_str );
2838 #endif
2839 TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
2840 return retval;
2844 /***********************************************************************
2845 * gethostname (WS2_32.57)
2847 int WINAPI WS_gethostname(char *name, int namelen)
2849 TRACE("name %p, len %d\n", name, namelen);
2851 if (gethostname(name, namelen) == 0)
2853 TRACE("<- '%s'\n", name);
2854 return 0;
2856 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2857 TRACE("<- ERROR !\n");
2858 return SOCKET_ERROR;
2862 /* ------------------------------------- Windows sockets extensions -- *
2864 * ------------------------------------------------------------------- */
2866 /***********************************************************************
2867 * WSAEnumNetworkEvents (WS2_32.36)
2869 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2871 int ret;
2873 TRACE("%08x, hEvent %p, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2875 SERVER_START_REQ( get_socket_event )
2877 req->handle = SOCKET2HANDLE(s);
2878 req->service = TRUE;
2879 req->c_event = hEvent;
2880 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
2881 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
2883 SERVER_END_REQ;
2884 if (!ret) return 0;
2885 SetLastError(WSAEINVAL);
2886 return SOCKET_ERROR;
2889 /***********************************************************************
2890 * WSAEventSelect (WS2_32.39)
2892 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, long lEvent)
2894 int ret;
2896 TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
2898 SERVER_START_REQ( set_socket_event )
2900 req->handle = SOCKET2HANDLE(s);
2901 req->mask = lEvent;
2902 req->event = hEvent;
2903 req->window = 0;
2904 req->msg = 0;
2905 ret = wine_server_call( req );
2907 SERVER_END_REQ;
2908 if (!ret) return 0;
2909 SetLastError(WSAEINVAL);
2910 return SOCKET_ERROR;
2913 /**********************************************************************
2914 * WSAGetOverlappedResult (WS2_32.40)
2916 BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
2917 LPDWORD lpcbTransfer, BOOL fWait,
2918 LPDWORD lpdwFlags )
2920 DWORD r;
2922 TRACE ( "socket %04x ovl %p trans %p, wait %d flags %p\n",
2923 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
2925 if ( !(lpOverlapped && lpOverlapped->hEvent) )
2927 ERR ( "Invalid pointer\n" );
2928 WSASetLastError (WSA_INVALID_PARAMETER);
2929 return FALSE;
2932 if ( fWait )
2934 while ( WaitForSingleObjectEx (lpOverlapped->hEvent, INFINITE, TRUE) == STATUS_USER_APC );
2936 else if ( lpOverlapped->Internal == STATUS_PENDING )
2938 /* Wait in order to give APCs a chance to run. */
2939 /* This is cheating, so we must set the event again in case of success -
2940 it may be a non-manual reset event. */
2941 while ( (r = WaitForSingleObjectEx (lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
2942 if ( r == WAIT_OBJECT_0 )
2943 NtSetEvent ( lpOverlapped->hEvent, NULL );
2946 if ( lpcbTransfer )
2947 *lpcbTransfer = lpOverlapped->InternalHigh;
2949 if ( lpdwFlags )
2950 *lpdwFlags = lpOverlapped->Offset;
2952 switch ( lpOverlapped->Internal )
2954 case STATUS_SUCCESS:
2955 return TRUE;
2956 case STATUS_PENDING:
2957 WSASetLastError ( WSA_IO_INCOMPLETE );
2958 if (fWait) ERR ("PENDING status after waiting!\n");
2959 return FALSE;
2960 default:
2961 WSASetLastError ( NtStatusToWSAError ( lpOverlapped->Internal ));
2962 return FALSE;
2967 /***********************************************************************
2968 * WSAAsyncSelect (WS2_32.101)
2970 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, long lEvent)
2972 int ret;
2974 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
2976 SERVER_START_REQ( set_socket_event )
2978 req->handle = SOCKET2HANDLE(s);
2979 req->mask = lEvent;
2980 req->event = 0;
2981 req->window = hWnd;
2982 req->msg = uMsg;
2983 ret = wine_server_call( req );
2985 SERVER_END_REQ;
2986 if (!ret) return 0;
2987 SetLastError(WSAEINVAL);
2988 return SOCKET_ERROR;
2991 /***********************************************************************
2992 * WSACreateEvent (WS2_32.31)
2995 WSAEVENT WINAPI WSACreateEvent(void)
2997 /* Create a manual-reset event, with initial state: unsignaled */
2998 TRACE("\n");
3000 return CreateEventW(NULL, TRUE, FALSE, NULL);
3003 /***********************************************************************
3004 * WSACloseEvent (WS2_32.29)
3007 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3009 TRACE ("event=%p\n", event);
3011 return CloseHandle(event);
3014 /***********************************************************************
3015 * WSASocketA (WS2_32.78)
3018 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3019 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3020 GROUP g, DWORD dwFlags)
3022 INT len;
3023 WSAPROTOCOL_INFOW info;
3025 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3026 af, type, protocol, lpProtocolInfo, g, dwFlags);
3028 if (!lpProtocolInfo) return WSASocketW(af, type, protocol, NULL, g, dwFlags);
3030 memcpy(&info, lpProtocolInfo, FIELD_OFFSET(WSAPROTOCOL_INFOW, szProtocol));
3031 len = MultiByteToWideChar(CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3032 info.szProtocol, WSAPROTOCOL_LEN * sizeof(WCHAR) + 1);
3034 if (!len)
3036 WSASetLastError( WSAEINVAL);
3037 return SOCKET_ERROR;
3040 return WSASocketW(af, type, protocol, &info, g, dwFlags);
3043 /***********************************************************************
3044 * WSASocketW (WS2_32.79)
3047 SOCKET WINAPI WSASocketW(int af, int type, int protocol,
3048 LPWSAPROTOCOL_INFOW lpProtocolInfo,
3049 GROUP g, DWORD dwFlags)
3051 SOCKET ret;
3054 FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
3055 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3058 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3059 af, type, protocol, lpProtocolInfo, g, dwFlags );
3061 /* hack for WSADuplicateSocket */
3062 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3063 ret = lpProtocolInfo->dwCatalogEntryId;
3064 TRACE("\tgot duplicate %04x\n", ret);
3065 return ret;
3068 /* check the socket family */
3069 switch(af)
3071 #ifdef HAVE_IPX
3072 case WS_AF_IPX: af = AF_IPX;
3073 #endif
3074 case AF_INET:
3075 case AF_UNSPEC:
3076 break;
3077 default:
3078 SetLastError(WSAEAFNOSUPPORT);
3079 return INVALID_SOCKET;
3082 /* check the socket type */
3083 switch(type)
3085 case WS_SOCK_STREAM:
3086 type=SOCK_STREAM;
3087 break;
3088 case WS_SOCK_DGRAM:
3089 type=SOCK_DGRAM;
3090 break;
3091 case WS_SOCK_RAW:
3092 type=SOCK_RAW;
3093 break;
3094 default:
3095 SetLastError(WSAESOCKTNOSUPPORT);
3096 return INVALID_SOCKET;
3099 /* check the protocol type */
3100 if ( protocol < 0 ) /* don't support negative values */
3102 SetLastError(WSAEPROTONOSUPPORT);
3103 return INVALID_SOCKET;
3106 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3107 switch(protocol)
3109 case IPPROTO_TCP:
3110 if (type == SOCK_STREAM) { af = AF_INET; break; }
3111 case IPPROTO_UDP:
3112 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3113 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3116 SERVER_START_REQ( create_socket )
3118 req->family = af;
3119 req->type = type;
3120 req->protocol = protocol;
3121 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3122 req->flags = dwFlags;
3123 req->inherit = TRUE;
3124 set_error( wine_server_call( req ) );
3125 ret = HANDLE2SOCKET( reply->handle );
3127 SERVER_END_REQ;
3128 if (ret)
3130 TRACE("\tcreated %04x\n", ret );
3131 return ret;
3134 if (GetLastError() == WSAEACCES) /* raw socket denied */
3136 if (type == SOCK_RAW)
3137 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3138 else
3139 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3140 SetLastError(WSAESOCKTNOSUPPORT);
3143 WARN("\t\tfailed!\n");
3144 return INVALID_SOCKET;
3147 /***********************************************************************
3148 * WSAJoinLeaf (WS2_32.58)
3151 SOCKET WINAPI WSAJoinLeaf(
3152 SOCKET s,
3153 const struct WS_sockaddr *addr,
3154 int addrlen,
3155 LPWSABUF lpCallerData,
3156 LPWSABUF lpCalleeData,
3157 LPQOS lpSQOS,
3158 LPQOS lpGQOS,
3159 DWORD dwFlags)
3161 FIXME("stub.\n");
3162 return INVALID_SOCKET;
3165 /***********************************************************************
3166 * __WSAFDIsSet (WS2_32.151)
3168 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3170 int i = set->fd_count;
3172 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3174 while (i--)
3175 if (set->fd_array[i] == s) return 1;
3176 return 0;
3179 /***********************************************************************
3180 * WSAIsBlocking (WINSOCK.114)
3181 * WSAIsBlocking (WS2_32.114)
3183 BOOL WINAPI WSAIsBlocking(void)
3185 /* By default WinSock should set all its sockets to non-blocking mode
3186 * and poll in PeekMessage loop when processing "blocking" ones. This
3187 * function is supposed to tell if the program is in this loop. Our
3188 * blocking calls are truly blocking so we always return FALSE.
3190 * Note: It is allowed to call this function without prior WSAStartup().
3193 TRACE("\n");
3194 return FALSE;
3197 /***********************************************************************
3198 * WSACancelBlockingCall (WINSOCK.113)
3199 * WSACancelBlockingCall (WS2_32.113)
3201 INT WINAPI WSACancelBlockingCall(void)
3203 TRACE("\n");
3204 return 0;
3207 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
3209 FIXME("How was this called?\n");
3210 return x();
3214 /***********************************************************************
3215 * WSASetBlockingHook (WS2_32.109)
3217 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3219 FARPROC prev = blocking_hook;
3220 blocking_hook = lpBlockFunc;
3221 TRACE("hook %p\n", lpBlockFunc);
3222 return prev;
3226 /***********************************************************************
3227 * WSAUnhookBlockingHook (WS2_32.110)
3229 INT WINAPI WSAUnhookBlockingHook(void)
3231 blocking_hook = WSA_DefaultBlockingHook;
3232 return 0;
3236 /* ----------------------------------- end of API stuff */
3238 /* ----------------------------------- helper functions -
3240 * TODO: Merge WS_dup_..() stuff into one function that
3241 * would operate with a generic structure containing internal
3242 * pointers (via a template of some kind).
3245 static int list_size(char** l, int item_size)
3247 int i,j = 0;
3248 if(l)
3249 { for(i=0;l[i];i++)
3250 j += (item_size) ? item_size : strlen(l[i]) + 1;
3251 j += (i + 1) * sizeof(char*); }
3252 return j;
3255 static int list_dup(char** l_src, char** l_to, int item_size)
3257 char *p;
3258 int i;
3260 for (i = 0; l_src[i]; i++) ;
3261 p = (char *)(l_to + i + 1);
3262 for (i = 0; l_src[i]; i++)
3264 int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3265 memcpy(p, l_src[i], count);
3266 l_to[i] = p;
3267 p += count;
3269 l_to[i] = NULL;
3270 return (p - (char *)l_to);
3273 /* ----- hostent */
3275 /* duplicate hostent entry
3276 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3277 * Dito for protoent and servent.
3279 static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
3281 char *p;
3282 struct WS_hostent *p_to;
3284 int size = (sizeof(*p_he) +
3285 strlen(p_he->h_name) + 1 +
3286 list_size(p_he->h_aliases, 0) +
3287 list_size(p_he->h_addr_list, p_he->h_length));
3289 if (!(p_to = check_buffer_he(size))) return NULL;
3290 p_to->h_addrtype = p_he->h_addrtype;
3291 p_to->h_length = p_he->h_length;
3293 p = (char *)(p_to + 1);
3294 p_to->h_name = p;
3295 strcpy(p, p_he->h_name);
3296 p += strlen(p) + 1;
3298 p_to->h_aliases = (char **)p;
3299 p += list_dup(p_he->h_aliases, p_to->h_aliases, 0);
3301 p_to->h_addr_list = (char **)p;
3302 list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length);
3303 return p_to;
3306 /* ----- protoent */
3308 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe)
3310 char *p;
3311 struct WS_protoent *p_to;
3313 int size = (sizeof(*p_pe) +
3314 strlen(p_pe->p_name) + 1 +
3315 list_size(p_pe->p_aliases, 0));
3317 if (!(p_to = check_buffer_pe(size))) return NULL;
3318 p_to->p_proto = p_pe->p_proto;
3320 p = (char *)(p_to + 1);
3321 p_to->p_name = p;
3322 strcpy(p, p_pe->p_name);
3323 p += strlen(p) + 1;
3325 p_to->p_aliases = (char **)p;
3326 list_dup(p_pe->p_aliases, p_to->p_aliases, 0);
3327 return p_to;
3330 /* ----- servent */
3332 static struct WS_servent *WS_dup_se(const struct servent* p_se)
3334 char *p;
3335 struct WS_servent *p_to;
3337 int size = (sizeof(*p_se) +
3338 strlen(p_se->s_proto) + 1 +
3339 strlen(p_se->s_name) + 1 +
3340 list_size(p_se->s_aliases, 0));
3342 if (!(p_to = check_buffer_se(size))) return NULL;
3343 p_to->s_port = p_se->s_port;
3345 p = (char *)(p_to + 1);
3346 p_to->s_name = p;
3347 strcpy(p, p_se->s_name);
3348 p += strlen(p) + 1;
3350 p_to->s_proto = p;
3351 strcpy(p, p_se->s_proto);
3352 p += strlen(p) + 1;
3354 p_to->s_aliases = (char **)p;
3355 list_dup(p_se->s_aliases, p_to->s_aliases, 0);
3356 return p_to;
3359 /* ----------------------------------- error handling */
3361 UINT wsaErrno(void)
3363 int loc_errno = errno;
3364 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3366 switch(loc_errno)
3368 case EINTR: return WSAEINTR;
3369 case EBADF: return WSAEBADF;
3370 case EPERM:
3371 case EACCES: return WSAEACCES;
3372 case EFAULT: return WSAEFAULT;
3373 case EINVAL: return WSAEINVAL;
3374 case EMFILE: return WSAEMFILE;
3375 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3376 case EINPROGRESS: return WSAEINPROGRESS;
3377 case EALREADY: return WSAEALREADY;
3378 case ENOTSOCK: return WSAENOTSOCK;
3379 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3380 case EMSGSIZE: return WSAEMSGSIZE;
3381 case EPROTOTYPE: return WSAEPROTOTYPE;
3382 case ENOPROTOOPT: return WSAENOPROTOOPT;
3383 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3384 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3385 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3386 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3387 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3388 case EADDRINUSE: return WSAEADDRINUSE;
3389 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3390 case ENETDOWN: return WSAENETDOWN;
3391 case ENETUNREACH: return WSAENETUNREACH;
3392 case ENETRESET: return WSAENETRESET;
3393 case ECONNABORTED: return WSAECONNABORTED;
3394 case EPIPE:
3395 case ECONNRESET: return WSAECONNRESET;
3396 case ENOBUFS: return WSAENOBUFS;
3397 case EISCONN: return WSAEISCONN;
3398 case ENOTCONN: return WSAENOTCONN;
3399 case ESHUTDOWN: return WSAESHUTDOWN;
3400 case ETOOMANYREFS: return WSAETOOMANYREFS;
3401 case ETIMEDOUT: return WSAETIMEDOUT;
3402 case ECONNREFUSED: return WSAECONNREFUSED;
3403 case ELOOP: return WSAELOOP;
3404 case ENAMETOOLONG: return WSAENAMETOOLONG;
3405 case EHOSTDOWN: return WSAEHOSTDOWN;
3406 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3407 case ENOTEMPTY: return WSAENOTEMPTY;
3408 #ifdef EPROCLIM
3409 case EPROCLIM: return WSAEPROCLIM;
3410 #endif
3411 #ifdef EUSERS
3412 case EUSERS: return WSAEUSERS;
3413 #endif
3414 #ifdef EDQUOT
3415 case EDQUOT: return WSAEDQUOT;
3416 #endif
3417 #ifdef ESTALE
3418 case ESTALE: return WSAESTALE;
3419 #endif
3420 #ifdef EREMOTE
3421 case EREMOTE: return WSAEREMOTE;
3422 #endif
3424 /* just in case we ever get here and there are no problems */
3425 case 0: return 0;
3426 default:
3427 WARN("Unknown errno %d!\n", loc_errno);
3428 return WSAEOPNOTSUPP;
3432 UINT wsaHerrno(int loc_errno)
3435 WARN("h_errno %d.\n", loc_errno);
3437 switch(loc_errno)
3439 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3440 case TRY_AGAIN: return WSATRY_AGAIN;
3441 case NO_RECOVERY: return WSANO_RECOVERY;
3442 case NO_DATA: return WSANO_DATA;
3443 case ENOBUFS: return WSAENOBUFS;
3445 case 0: return 0;
3446 default:
3447 WARN("Unknown h_errno %d!\n", loc_errno);
3448 return WSAEOPNOTSUPP;
3453 /***********************************************************************
3454 * WSARecv (WS2_32.67)
3456 int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3457 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3458 LPWSAOVERLAPPED lpOverlapped,
3459 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3461 return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3462 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3465 /***********************************************************************
3466 * WSARecvFrom (WS2_32.69)
3468 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3469 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3470 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3471 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3474 unsigned int i;
3475 int n, fd, err = WSAENOTSOCK, flags, ret;
3476 struct iovec* iovec;
3477 struct ws2_async *wsa;
3479 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3480 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3481 (lpFromlen ? *lpFromlen : -1L),
3482 lpOverlapped, lpCompletionRoutine);
3484 fd = get_sock_fd( s, GENERIC_READ, &flags );
3485 TRACE ( "fd=%d, flags=%x\n", fd, flags );
3487 if (fd == -1) return SOCKET_ERROR;
3489 if (flags & FD_FLAG_RECV_SHUTDOWN)
3491 WSASetLastError ( WSAESHUTDOWN );
3492 goto err_close;
3495 iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3496 if ( !iovec )
3498 err = WSAEFAULT;
3499 goto err_close;
3502 for (i = 0; i < dwBufferCount; i++)
3504 iovec[i].iov_base = lpBuffers[i].buf;
3505 iovec[i].iov_len = lpBuffers[i].len;
3508 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3510 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
3511 lpFlags, lpFrom, lpFromlen,
3512 lpOverlapped, lpCompletionRoutine );
3514 if ( !wsa )
3516 err = WSAEFAULT;
3517 goto err_free;
3520 if ( ( ret = register_new_async ( &wsa->async )) )
3522 err = NtStatusToWSAError ( ret );
3524 if ( !lpOverlapped )
3525 HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
3526 HeapFree ( GetProcessHeap(), 0, wsa );
3527 goto err_free;
3530 /* Try immediate completion */
3531 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
3533 if ( WSAGetOverlappedResult ( s, lpOverlapped,
3534 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3535 return 0;
3537 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
3538 goto error;
3541 WSASetLastError ( WSA_IO_PENDING );
3542 return SOCKET_ERROR;
3545 if ( _is_blocking(s) )
3547 /* block here */
3548 /* FIXME: OOB and exceptfds? */
3549 int timeout = GET_RCVTIMEO(fd);
3550 if( !do_block(fd, POLLIN, timeout)) {
3551 err = WSAETIMEDOUT;
3552 /* a timeout is not fatal */
3553 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3554 goto err_free;
3558 n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3559 if ( n == -1 )
3561 err = wsaErrno();
3562 goto err_free;
3565 TRACE(" -> %i bytes\n", n);
3566 *lpNumberOfBytesRecvd = n;
3568 HeapFree (GetProcessHeap(), 0, iovec);
3569 release_sock_fd( s, fd );
3570 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3572 return 0;
3574 err_free:
3575 HeapFree (GetProcessHeap(), 0, iovec);
3577 err_close:
3578 release_sock_fd( s, fd );
3580 error:
3581 WARN(" -> ERROR %d\n", err);
3582 WSASetLastError ( err );
3583 return SOCKET_ERROR;
3586 /***********************************************************************
3587 * WSCInstallProvider (WS2_32.88)
3589 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
3590 LPCWSTR lpszProviderDllPath,
3591 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
3592 DWORD dwNumberOfEntries,
3593 LPINT lpErrno )
3595 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
3596 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
3597 dwNumberOfEntries, lpErrno);
3598 *lpErrno = 0;
3599 return 0;
3603 /***********************************************************************
3604 * WSCDeinstallProvider (WS2_32.83)
3606 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
3608 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
3609 *lpErrno = 0;
3610 return 0;
3614 /***********************************************************************
3615 * WSAAccept (WS2_32.26)
3617 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
3618 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
3621 int ret = 0, size = 0;
3622 WSABUF CallerId, CallerData, CalleeId, CalleeData;
3623 /* QOS SQOS, GQOS; */
3624 GROUP g;
3625 SOCKET cs;
3626 SOCKADDR src_addr, dst_addr;
3628 TRACE("Socket %04x, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
3629 s, addr, addrlen, lpfnCondition, dwCallbackData);
3632 size = sizeof(src_addr);
3633 cs = WS_accept(s, &src_addr, &size);
3635 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
3637 CallerId.buf = (char *)&src_addr;
3638 CallerId.len = sizeof(src_addr);
3640 CallerData.buf = NULL;
3641 CallerData.len = (ULONG)NULL;
3643 WS_getsockname(cs, &dst_addr, &size);
3645 CalleeId.buf = (char *)&dst_addr;
3646 CalleeId.len = sizeof(dst_addr);
3649 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
3650 &CalleeId, &CalleeData, &g, dwCallbackData);
3652 switch (ret)
3654 case CF_ACCEPT:
3655 if (addr && addrlen)
3656 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
3657 return cs;
3658 case CF_DEFER:
3659 SERVER_START_REQ ( set_socket_deferred )
3661 req->handle = SOCKET2HANDLE (s);
3662 req->deferred = SOCKET2HANDLE (cs);
3663 if ( !wine_server_call_err ( req ) )
3665 SetLastError ( WSATRY_AGAIN );
3666 WS_closesocket ( cs );
3669 SERVER_END_REQ;
3670 return SOCKET_ERROR;
3671 case CF_REJECT:
3672 WS_closesocket(cs);
3673 SetLastError(WSAECONNREFUSED);
3674 return SOCKET_ERROR;
3675 default:
3676 FIXME("Unknown return type from Condition function\n");
3677 SetLastError(WSAENOTSOCK);
3678 return SOCKET_ERROR;
3682 /***********************************************************************
3683 * WSADuplicateSocketA (WS2_32.32)
3685 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
3687 HANDLE hProcess;
3689 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3690 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3691 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
3692 /* I don't know what the real Windoze does next, this is a hack */
3693 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
3694 * the target use the global duplicate, or we could copy a reference to us to the structure
3695 * and let the target duplicate it from us, but let's do it as simple as possible */
3696 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3697 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3698 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3699 0, FALSE, DUPLICATE_SAME_ACCESS);
3700 CloseHandle(hProcess);
3701 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3702 return 0;
3705 /***********************************************************************
3706 * WSADuplicateSocketW (WS2_32.33)
3708 int WINAPI WSADuplicateSocketW( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo )
3710 HANDLE hProcess;
3712 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3714 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3715 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3716 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3717 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3718 0, FALSE, DUPLICATE_SAME_ACCESS);
3719 CloseHandle(hProcess);
3720 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3721 return 0;
3724 /***********************************************************************
3725 * WSAInstallServiceClassA (WS2_32.48)
3727 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
3729 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
3730 WSASetLastError(WSAEACCES);
3731 return SOCKET_ERROR;
3734 /***********************************************************************
3735 * WSAInstallServiceClassW (WS2_32.49)
3737 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
3739 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
3740 WSASetLastError(WSAEACCES);
3741 return SOCKET_ERROR;
3744 /***********************************************************************
3745 * WSARemoveServiceClass (WS2_32.70)
3747 int WINAPI WSARemoveServiceClass(LPGUID info)
3749 FIXME("Request to remove service %p\n",info);
3750 WSASetLastError(WSATYPE_NOT_FOUND);
3751 return SOCKET_ERROR;
3754 /***********************************************************************
3755 * WSAStringToAddressA (WS2_32.80)
3757 INT WINAPI WSAStringToAddressA(LPSTR AddressString,
3758 INT AddressFamily,
3759 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3760 LPSOCKADDR lpAddress,
3761 LPINT lpAddressLength)
3763 INT res=0;
3764 LONG inetaddr;
3765 LPSTR workBuffer=NULL,ptrPort;
3767 TRACE( "(%s, %x, %p, %p, %p)\n", AddressString, AddressFamily, lpProtocolInfo,
3768 lpAddress, lpAddressLength );
3770 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
3772 if (AddressString)
3774 workBuffer = HeapAlloc( GetProcessHeap(), 0, strlen(AddressString)+1 );
3775 if (workBuffer)
3777 strcpy(workBuffer,AddressString);
3778 switch (AddressFamily)
3780 case AF_INET:
3781 /* caller wants to know the size of the socket buffer */
3782 if (*lpAddressLength < sizeof(SOCKADDR_IN))
3784 *lpAddressLength = sizeof(SOCKADDR_IN);
3785 res = WSAEFAULT;
3787 else
3789 /* caller wants to translate an AdressString into a SOCKADDR */
3790 if (lpAddress)
3792 memset(lpAddress,0,sizeof(SOCKADDR_IN));
3793 ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET;
3794 ptrPort = strchr(workBuffer,':');
3795 if (ptrPort)
3797 ((LPSOCKADDR_IN)lpAddress)->sin_port = (u_short)atoi(ptrPort+1);
3798 *ptrPort = '\0';
3800 else
3801 ((LPSOCKADDR_IN)lpAddress)->sin_port = 0;
3802 inetaddr = inet_addr(workBuffer);
3803 if (inetaddr != INADDR_NONE)
3805 ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr;
3806 res = 0;
3808 else
3809 res = WSAEINVAL;
3812 if (lpProtocolInfo)
3813 FIXME("(%s, %x, %p, %p, %p) - ProtocolInfo not implemented!\n",
3814 AddressString, AddressFamily,
3815 lpProtocolInfo, lpAddress, lpAddressLength);
3817 break;
3818 default:
3819 FIXME("(%s, %x, %p, %p, %p) - AddressFamiliy not implemented!\n",
3820 AddressString, AddressFamily,
3821 lpProtocolInfo, lpAddress, lpAddressLength);
3823 HeapFree( GetProcessHeap(), 0, workBuffer );
3825 else
3826 res = WSA_NOT_ENOUGH_MEMORY;
3828 else
3829 res = WSAEINVAL;
3831 if (!res) return 0;
3832 WSASetLastError(res);
3833 return SOCKET_ERROR;
3836 /***********************************************************************
3837 * WSAStringToAddressW (WS2_32.81)
3839 * Does anybody know if this functions allows to use hebrew/arabic/chinese... digits?
3840 * If this should be the case, it would be required to map these digits
3841 * to Unicode digits (0-9) using FoldString first.
3843 INT WINAPI WSAStringToAddressW(LPWSTR AddressString,
3844 INT AddressFamily,
3845 LPWSAPROTOCOL_INFOW lpProtocolInfo,
3846 LPSOCKADDR lpAddress,
3847 LPINT lpAddressLength)
3849 INT sBuffer,res=0;
3850 LPSTR workBuffer=NULL;
3851 WSAPROTOCOL_INFOA infoA;
3852 LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL;
3854 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_w(AddressString), AddressFamily, lpProtocolInfo,
3855 lpAddress, lpAddressLength );
3857 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
3859 /* if ProtocolInfo is available - convert to ANSI variant */
3860 if (lpProtocolInfo)
3862 lpProtoInfoA = &infoA;
3863 memcpy( lpProtoInfoA, lpProtocolInfo, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
3865 if (!WideCharToMultiByte( CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3866 lpProtoInfoA->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL ))
3868 WSASetLastError( WSAEINVAL);
3869 return SOCKET_ERROR;
3873 if (AddressString)
3875 /* Translate AddressString to ANSI code page - assumes that only
3876 standard digits 0-9 are used with this API call */
3877 sBuffer = WideCharToMultiByte( CP_ACP, 0, AddressString, -1, NULL, 0, NULL, NULL );
3878 workBuffer = HeapAlloc( GetProcessHeap(), 0, sBuffer );
3880 if (workBuffer)
3882 WideCharToMultiByte( CP_ACP, 0, AddressString, -1, workBuffer, sBuffer, NULL, NULL );
3883 res = WSAStringToAddressA(workBuffer,AddressFamily,lpProtoInfoA,
3884 lpAddress,lpAddressLength);
3885 HeapFree( GetProcessHeap(), 0, workBuffer );
3886 return res;
3888 else
3889 res = WSA_NOT_ENOUGH_MEMORY;
3891 else
3892 res = WSAEINVAL;
3894 WSASetLastError(res);
3895 return SOCKET_ERROR;
3898 /***********************************************************************
3899 * WSAAddressToStringA (WS2_32.27)
3901 * See WSAAddressToStringW
3903 INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len,
3904 LPWSAPROTOCOL_INFOA info, LPSTR string,
3905 LPDWORD lenstr )
3907 INT size;
3908 CHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
3909 CHAR *p;
3911 TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
3913 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
3914 if (!string || !lenstr) return SOCKET_ERROR;
3916 /* sin_family is garanteed to be the first u_short */
3917 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
3919 sprintf( buffer, "%u.%u.%u.%u:%u",
3920 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
3921 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
3922 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
3923 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
3924 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
3926 p = strchr( buffer, ':' );
3927 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
3929 size = strlen( buffer );
3931 if (*lenstr < size)
3933 *lenstr = size;
3934 return SOCKET_ERROR;
3937 strcpy( string, buffer );
3938 return 0;
3941 /***********************************************************************
3942 * WSAAddressToStringW (WS2_32.28)
3944 * Convert a sockaddr address into a readable address string.
3946 * PARAMS
3947 * sockaddr [I] Pointer to a sockaddr structure.
3948 * len [I] Size of the sockaddr structure.
3949 * info [I] Pointer to a WSAPROTOCOL_INFOW structure (optional).
3950 * string [I/O] Pointer to a buffer to receive the address string.
3951 * lenstr [I/O] Size of the receive buffer in WCHARs.
3953 * RETURNS
3954 * Success: 0
3955 * Failure: SOCKET_ERROR
3957 * NOTES
3958 * The 'info' parameter is ignored.
3960 * BUGS
3961 * Only supports AF_INET addresses.
3963 INT WINAPI WSAAddressToStringW( LPSOCKADDR sockaddr, DWORD len,
3964 LPWSAPROTOCOL_INFOW info, LPWSTR string,
3965 LPDWORD lenstr )
3967 INT size;
3968 WCHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
3969 static const WCHAR format[] = { '%','u','.','%','u','.','%','u','.','%','u',':','%','u',0 };
3970 WCHAR *p;
3972 TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
3974 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
3975 if (!string || !lenstr) return SOCKET_ERROR;
3977 /* sin_family is garanteed to be the first u_short */
3978 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
3980 sprintfW( buffer, format,
3981 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
3982 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
3983 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
3984 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
3985 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
3987 p = strchrW( buffer, ':' );
3988 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
3990 size = lstrlenW( buffer );
3992 if (*lenstr < size)
3994 *lenstr = size;
3995 return SOCKET_ERROR;
3998 lstrcpyW( string, buffer );
3999 return 0;
4002 /***********************************************************************
4003 * WSAEnumNameSpaceProvidersA (WS2_32.34)
4005 INT WINAPI WSAEnumNameSpaceProvidersA( LPDWORD len, LPWSANAMESPACE_INFOA buffer )
4007 FIXME( "(%p %p) Stub!\n", len, buffer );
4008 return 0;
4011 /***********************************************************************
4012 * WSAEnumNameSpaceProvidersW (WS2_32.35)
4014 INT WINAPI WSAEnumNameSpaceProvidersW( LPDWORD len, LPWSANAMESPACE_INFOW buffer )
4016 FIXME( "(%p %p) Stub!\n", len, buffer );
4017 return 0;
4020 /***********************************************************************
4021 * WSAGetQOSByName (WS2_32.41)
4023 BOOL WINAPI WSAGetQOSByName( SOCKET s, LPWSABUF lpQOSName, LPQOS lpQOS )
4025 FIXME( "(0x%04x %p %p) Stub!\n", s, lpQOSName, lpQOS );
4026 return FALSE;
4029 /***********************************************************************
4030 * WSAGetServiceClassInfoA (WS2_32.42)
4032 INT WINAPI WSAGetServiceClassInfoA( LPGUID provider, LPGUID service, LPDWORD len,
4033 LPWSASERVICECLASSINFOA info )
4035 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4036 len, info );
4037 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4038 return SOCKET_ERROR;
4041 /***********************************************************************
4042 * WSAGetServiceClassInfoW (WS2_32.43)
4044 INT WINAPI WSAGetServiceClassInfoW( LPGUID provider, LPGUID service, LPDWORD len,
4045 LPWSASERVICECLASSINFOW info )
4047 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4048 len, info );
4049 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4050 return SOCKET_ERROR;
4053 /***********************************************************************
4054 * WSAGetServiceClassNameByClassIdA (WS2_32.44)
4056 INT WINAPI WSAGetServiceClassNameByClassIdA( LPGUID class, LPSTR service, LPDWORD len )
4058 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4059 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4060 return SOCKET_ERROR;
4063 /***********************************************************************
4064 * WSAGetServiceClassNameByClassIdW (WS2_32.45)
4066 INT WINAPI WSAGetServiceClassNameByClassIdW( LPGUID class, LPWSTR service, LPDWORD len )
4068 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4069 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4070 return SOCKET_ERROR;
4073 /***********************************************************************
4074 * WSALookupServiceBeginA (WS2_32.59)
4076 INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
4077 DWORD dwControlFlags,
4078 LPHANDLE lphLookup)
4080 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4081 lphLookup);
4082 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4083 return SOCKET_ERROR;
4086 /***********************************************************************
4087 * WSALookupServiceBeginW (WS2_32.60)
4089 INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
4090 DWORD dwControlFlags,
4091 LPHANDLE lphLookup)
4093 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4094 lphLookup);
4095 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4096 return SOCKET_ERROR;
4099 /***********************************************************************
4100 * WSALookupServiceBeginW (WS2_32.61)
4102 INT WINAPI WSALookupServiceEnd( HANDLE lookup )
4104 FIXME("(%p) Stub!\n", lookup );
4105 return 0;
4108 /***********************************************************************
4109 * WSALookupServiceNextA (WS2_32.62)
4111 INT WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETA results )
4113 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4114 return 0;
4117 /***********************************************************************
4118 * WSALookupServiceNextW (WS2_32.63)
4120 INT WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETW results )
4122 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4123 return 0;
4126 /***********************************************************************
4127 * WSANtohl (WS2_32.64)
4129 INT WINAPI WSANtohl( SOCKET s, u_long netlong, u_long* lphostlong )
4131 TRACE( "(0x%04x 0x%08lx %p)\n", s, netlong, lphostlong );
4133 if (!lphostlong) return WSAEFAULT;
4135 *lphostlong = ntohl( netlong );
4136 return 0;
4139 /***********************************************************************
4140 * WSANtohs (WS2_32.65)
4142 INT WINAPI WSANtohs( SOCKET s, u_short netshort, u_short* lphostshort )
4144 TRACE( "(0x%04x 0x%08x %p)\n", s, netshort, lphostshort );
4146 if (!lphostshort) return WSAEFAULT;
4148 *lphostshort = ntohs( netshort );
4149 return 0;
4152 /***********************************************************************
4153 * WSAProviderConfigChange (WS2_32.66)
4155 INT WINAPI WSAProviderConfigChange( LPHANDLE handle, LPWSAOVERLAPPED overlapped,
4156 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
4158 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
4159 return SOCKET_ERROR;
4162 /***********************************************************************
4163 * WSARecvDisconnect (WS2_32.68)
4165 INT WINAPI WSARecvDisconnect( SOCKET s, LPWSABUF disconnectdata )
4167 TRACE( "(0x%04x %p)\n", s, disconnectdata );
4169 return WS_shutdown( s, 0 );
4172 /***********************************************************************
4173 * WSASetServiceA (WS2_32.76)
4175 INT WINAPI WSASetServiceA( LPWSAQUERYSETA query, WSAESETSERVICEOP operation, DWORD flags )
4177 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4178 return 0;
4181 /***********************************************************************
4182 * WSASetServiceW (WS2_32.77)
4184 INT WINAPI WSASetServiceW( LPWSAQUERYSETW query, WSAESETSERVICEOP operation, DWORD flags )
4186 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4187 return 0;
4190 /***********************************************************************
4191 * WSCEnableNSProvider (WS2_32.84)
4193 INT WINAPI WSCEnableNSProvider( LPGUID provider, BOOL enable )
4195 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
4196 return 0;
4199 /***********************************************************************
4200 * WSCGetProviderPath (WS2_32.86)
4202 INT WINAPI WSCGetProviderPath( LPGUID provider, LPWSTR path, LPINT len, LPINT errno )
4204 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errno );
4206 if (!errno || !provider || !len) return WSAEFAULT;
4208 *errno = WSAEINVAL;
4209 return SOCKET_ERROR;
4212 /***********************************************************************
4213 * WSCInstallNameSpace (WS2_32.87)
4215 INT WINAPI WSCInstallNameSpace( LPWSTR identifier, LPWSTR path, DWORD namespace,
4216 DWORD version, LPGUID provider )
4218 FIXME( "(%s %s 0x%08lx 0x%08lx %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
4219 namespace, version, debugstr_guid(provider) );
4220 return 0;
4223 /***********************************************************************
4224 * WSCUnInstallNameSpace (WS2_32.89)
4226 INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
4228 FIXME("(%p) Stub!\n", lpProviderId);
4229 return NO_ERROR;
4232 /***********************************************************************
4233 * WSCWriteProviderOrder (WS2_32.91)
4235 INT WINAPI WSCWriteProviderOrder( LPDWORD entry, DWORD number )
4237 FIXME("(%p 0x%08lx) Stub!\n", entry, number);
4238 return 0;