Remove stdlib.h inclusion if winsock.h is included.
[wine/dcerpc.git] / dlls / winsock / socket.c
blobc4f652b48d9d801d4aa789a35ebe740ee294d41f
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 # ifdef HAVE_ASM_TYPES_H
103 # include <asm/types.h>
104 # endif
105 # include <linux/ipx.h>
106 # define HAVE_IPX
107 #endif
109 #ifdef HAVE_POLL_H
110 #include <poll.h>
111 #endif
112 #ifdef HAVE_SYS_POLL_H
113 # include <sys/poll.h>
114 #endif
115 #ifdef HAVE_SYS_TIME_H
116 # include <sys/time.h>
117 #endif
119 #define NONAMELESSUNION
120 #define NONAMELESSSTRUCT
121 #include "windef.h"
122 #include "winbase.h"
123 #include "wingdi.h"
124 #include "winuser.h"
125 #include "winerror.h"
126 #include "winnls.h"
127 #include "winsock2.h"
128 #include "mswsock.h"
129 #include "ws2tcpip.h"
130 #include "wsipx.h"
131 #include "winnt.h"
132 #include "iphlpapi.h"
133 #include "thread.h"
134 #include "wine/server.h"
135 #include "wine/debug.h"
136 #include "ntstatus.h"
137 #include "wine/unicode.h"
139 #ifdef HAVE_IPX
140 # include "wsnwlink.h"
141 #endif
144 #ifdef __FreeBSD__
145 # define sipx_network sipx_addr.x_net
146 # define sipx_node sipx_addr.x_host.c_host
147 #endif /* __FreeBSD__ */
149 #ifndef INADDR_NONE
150 #define INADDR_NONE ~0UL
151 #endif
153 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
155 /* critical section to protect some non-rentrant net function */
156 extern CRITICAL_SECTION csWSgetXXXbyYYY;
158 inline static const char *debugstr_sockaddr( const struct WS_sockaddr *a )
160 if (!a) return "(nil)";
161 return wine_dbg_sprintf("{ family %d, address %s, port %d }",
162 ((struct sockaddr_in *)a)->sin_family,
163 inet_ntoa(((struct sockaddr_in *)a)->sin_addr),
164 ntohs(((struct sockaddr_in *)a)->sin_port));
167 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
168 #define SOCKET2HANDLE(s) ((HANDLE)(s))
169 #define HANDLE2SOCKET(h) ((SOCKET)(h))
171 /****************************************************************
172 * Async IO declarations
173 ****************************************************************/
175 typedef struct ws2_async
177 HANDLE hSocket;
178 enum ws2_mode {ws2m_read, ws2m_write, ws2m_sd_read, ws2m_sd_write} mode;
179 LPWSAOVERLAPPED user_overlapped;
180 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
181 struct iovec *iovec;
182 int n_iovecs;
183 struct WS_sockaddr *addr;
184 union
186 int val; /* for send operations */
187 int *ptr; /* for recv operations */
188 } addrlen;
189 DWORD flags;
190 int fd;
191 HANDLE event;
192 } ws2_async;
194 /****************************************************************/
196 /* ----------------------------------- internal data */
198 /* ws_... struct conversion flags */
200 typedef struct /* WSAAsyncSelect() control struct */
202 HANDLE service, event, sock;
203 HWND hWnd;
204 UINT uMsg;
205 LONG lEvent;
206 } ws_select_info;
208 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
209 #define WS_MAX_UDP_DATAGRAM 1024
210 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
212 /* hostent's, servent's and protent's are stored in one buffer per thread,
213 * as documented on MSDN for the functions that return any of the buffers */
214 struct per_thread_data
216 int opentype;
217 struct WS_hostent *he_buffer;
218 struct WS_servent *se_buffer;
219 struct WS_protoent *pe_buffer;
220 int he_len;
221 int se_len;
222 int pe_len;
225 static INT num_startup; /* reference counter */
226 static FARPROC blocking_hook = WSA_DefaultBlockingHook;
228 /* function prototypes */
229 static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
230 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe);
231 static struct WS_servent *WS_dup_se(const struct servent* p_se);
233 int WSAIOCTL_GetInterfaceCount(void);
234 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
236 UINT wsaErrno(void);
237 UINT wsaHerrno(int errnr);
239 #define MAP_OPTION(opt) { WS_##opt, opt }
241 static const int ws_sock_map[][2] =
243 MAP_OPTION( SO_DEBUG ),
244 MAP_OPTION( SO_REUSEADDR ),
245 MAP_OPTION( SO_KEEPALIVE ),
246 MAP_OPTION( SO_DONTROUTE ),
247 MAP_OPTION( SO_BROADCAST ),
248 MAP_OPTION( SO_LINGER ),
249 MAP_OPTION( SO_OOBINLINE ),
250 MAP_OPTION( SO_SNDBUF ),
251 MAP_OPTION( SO_RCVBUF ),
252 MAP_OPTION( SO_ERROR ),
253 MAP_OPTION( SO_TYPE ),
254 #ifdef SO_RCVTIMEO
255 MAP_OPTION( SO_RCVTIMEO ),
256 #endif
257 #ifdef SO_SNDTIMEO
258 MAP_OPTION( SO_SNDTIMEO ),
259 #endif
260 { 0, 0 }
263 static const int ws_tcp_map[][2] =
265 #ifdef TCP_NODELAY
266 MAP_OPTION( TCP_NODELAY ),
267 #endif
268 { 0, 0 }
271 static const int ws_ip_map[][2] =
273 MAP_OPTION( IP_MULTICAST_IF ),
274 MAP_OPTION( IP_MULTICAST_TTL ),
275 MAP_OPTION( IP_MULTICAST_LOOP ),
276 MAP_OPTION( IP_ADD_MEMBERSHIP ),
277 MAP_OPTION( IP_DROP_MEMBERSHIP ),
278 MAP_OPTION( IP_OPTIONS ),
279 #ifdef IP_HDRINCL
280 MAP_OPTION( IP_HDRINCL ),
281 #endif
282 MAP_OPTION( IP_TOS ),
283 MAP_OPTION( IP_TTL ),
284 { 0, 0 }
287 inline static DWORD NtStatusToWSAError( const DWORD status )
289 /* We only need to cover the status codes set by server async request handling */
290 DWORD wserr;
291 switch ( status )
293 case STATUS_SUCCESS: wserr = 0; break;
294 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
295 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
296 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
297 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
298 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
299 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
300 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
301 default:
302 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
303 /* It is not a NT status code but a winsock error */
304 wserr = status;
305 else
307 wserr = RtlNtStatusToDosError( status );
308 FIXME( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
311 return wserr;
314 /* set last error code from NT status without mapping WSA errors */
315 inline static unsigned int set_error( unsigned int err )
317 if (err)
319 err = NtStatusToWSAError( err );
320 SetLastError( err );
322 return err;
325 inline static int get_sock_fd( SOCKET s, DWORD access, int *flags )
327 int fd;
328 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, flags ) ))
329 return -1;
330 return fd;
333 inline static void release_sock_fd( SOCKET s, int fd )
335 wine_server_release_fd( SOCKET2HANDLE(s), fd );
338 static void _enable_event( HANDLE s, unsigned int event,
339 unsigned int sstate, unsigned int cstate )
341 SERVER_START_REQ( enable_socket_event )
343 req->handle = s;
344 req->mask = event;
345 req->sstate = sstate;
346 req->cstate = cstate;
347 wine_server_call( req );
349 SERVER_END_REQ;
352 static int _is_blocking(SOCKET s)
354 int ret;
355 SERVER_START_REQ( get_socket_event )
357 req->handle = SOCKET2HANDLE(s);
358 req->service = FALSE;
359 req->c_event = 0;
360 wine_server_call( req );
361 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
363 SERVER_END_REQ;
364 return ret;
367 static unsigned int _get_sock_mask(SOCKET s)
369 unsigned int ret;
370 SERVER_START_REQ( get_socket_event )
372 req->handle = SOCKET2HANDLE(s);
373 req->service = FALSE;
374 req->c_event = 0;
375 wine_server_call( req );
376 ret = reply->mask;
378 SERVER_END_REQ;
379 return ret;
382 static void _sync_sock_state(SOCKET s)
384 /* do a dummy wineserver request in order to let
385 the wineserver run through its select loop once */
386 (void)_is_blocking(s);
389 static int _get_sock_error(SOCKET s, unsigned int bit)
391 int events[FD_MAX_EVENTS];
393 SERVER_START_REQ( get_socket_event )
395 req->handle = SOCKET2HANDLE(s);
396 req->service = FALSE;
397 req->c_event = 0;
398 wine_server_set_reply( req, events, sizeof(events) );
399 wine_server_call( req );
401 SERVER_END_REQ;
402 return events[bit];
405 static struct per_thread_data *get_per_thread_data(void)
407 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
408 /* lazy initialization */
409 if (!ptb)
411 ptb = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptb) );
412 NtCurrentTeb()->WinSockData = ptb;
414 return ptb;
417 static void free_per_thread_data(void)
419 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
421 if (!ptb) return;
423 /* delete scratch buffers */
424 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
425 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
426 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
427 ptb->he_buffer = NULL;
428 ptb->se_buffer = NULL;
429 ptb->pe_buffer = NULL;
431 HeapFree( GetProcessHeap(), 0, ptb );
432 NtCurrentTeb()->WinSockData = NULL;
435 /***********************************************************************
436 * DllMain (WS2_32.init)
438 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
440 TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
441 switch (fdwReason) {
442 case DLL_PROCESS_ATTACH:
443 break;
444 case DLL_PROCESS_DETACH:
445 free_per_thread_data();
446 num_startup = 0;
447 break;
448 case DLL_THREAD_DETACH:
449 free_per_thread_data();
450 break;
452 return TRUE;
455 /***********************************************************************
456 * convert_sockopt()
458 * Converts socket flags from Windows format.
459 * Return 1 if converted, 0 if not (error).
461 static int convert_sockopt(INT *level, INT *optname)
463 int i;
464 switch (*level)
466 case WS_SOL_SOCKET:
467 *level = SOL_SOCKET;
468 for(i=0; ws_sock_map[i][0]; i++)
470 if( ws_sock_map[i][0] == *optname )
472 *optname = ws_sock_map[i][1];
473 return 1;
476 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
477 break;
478 case WS_IPPROTO_TCP:
479 *level = IPPROTO_TCP;
480 for(i=0; ws_tcp_map[i][0]; i++)
482 if ( ws_tcp_map[i][0] == *optname )
484 *optname = ws_tcp_map[i][1];
485 return 1;
488 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
489 break;
490 case WS_IPPROTO_IP:
491 *level = IPPROTO_IP;
492 for(i=0; ws_ip_map[i][0]; i++)
494 if (ws_ip_map[i][0] == *optname )
496 *optname = ws_ip_map[i][1];
497 return 1;
500 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
501 break;
502 default: FIXME("Unimplemented or unknown socket level\n");
504 return 0;
507 static inline BOOL is_timeout_option( int optname )
509 #ifdef SO_RCVTIMEO
510 if (optname == SO_RCVTIMEO) return TRUE;
511 #endif
512 #ifdef SO_SNDTIMEO
513 if (optname == SO_SNDTIMEO) return TRUE;
514 #endif
515 return FALSE;
518 /* ----------------------------------- Per-thread info (or per-process?) */
520 static char *strdup_lower(const char *str)
522 int i;
523 char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
525 if (ret)
527 for (i = 0; str[i]; i++) ret[i] = tolower(str[i]);
528 ret[i] = 0;
530 else SetLastError(WSAENOBUFS);
531 return ret;
534 static fd_set* fd_set_import( fd_set* fds, const WS_fd_set* wsfds, int access, int* highfd, int lfd[] )
536 /* translate Winsock fd set into local fd set */
537 if( wsfds )
539 unsigned int i;
541 FD_ZERO(fds);
542 for( i = 0; i < wsfds->fd_count; i++ )
544 int s = wsfds->fd_array[i];
545 int fd = get_sock_fd( s, access, NULL );
546 if (fd != -1)
548 lfd[ i ] = fd;
549 if( fd > *highfd ) *highfd = fd;
550 FD_SET(fd, fds);
552 else lfd[ i ] = -1;
554 return fds;
556 return NULL;
559 inline static int sock_error_p(int s)
561 unsigned int optval, optlen;
563 optlen = sizeof(optval);
564 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
565 if (optval) WARN("\t[%i] error: %d\n", s, optval);
566 return optval != 0;
569 static int fd_set_export( const fd_set* fds, fd_set* exceptfds, WS_fd_set* wsfds, int lfd[] )
571 int num_err = 0;
573 /* translate local fd set into Winsock fd set, adding
574 * errors to exceptfds (only if app requested it) */
576 if( wsfds )
578 int i, j, count = wsfds->fd_count;
580 for( i = 0, j = 0; i < count; i++ )
582 int fd = lfd[i];
583 SOCKET s = wsfds->fd_array[i];
584 if (fd == -1) continue;
585 if( FD_ISSET(fd, fds) )
587 if ( exceptfds && sock_error_p(fd) )
589 FD_SET(fd, exceptfds);
590 num_err++;
592 else wsfds->fd_array[j++] = s;
594 release_sock_fd( s, fd );
596 wsfds->fd_count = j;
598 return num_err;
601 static void fd_set_unimport( WS_fd_set* wsfds, int lfd[] )
603 if ( wsfds )
605 unsigned int i;
607 for ( i = 0; i < wsfds->fd_count; i++ )
608 if ( lfd[i] >= 0 ) release_sock_fd( wsfds->fd_array[i], lfd[i] );
609 wsfds->fd_count = 0;
613 /* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option
614 * from an fd and return the value converted to milli seconds
615 * or -1 if there is an infinite time out */
616 static inline int get_rcvsnd_timeo( int fd, int optname)
618 struct timeval tv;
619 int len = sizeof(tv);
620 int ret = getsockopt(fd, SOL_SOCKET, optname, &tv, &len);
621 if( ret >= 0)
622 ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
623 if( ret <= 0 ) /* tv == {0,0} means infinite time out */
624 return -1;
625 return ret;
628 /* macro wrappers for portability */
629 #ifdef SO_RCVTIMEO
630 #define GET_RCVTIMEO(fd) get_rcvsnd_timeo( (fd), SO_RCVTIMEO)
631 #else
632 #define GET_RCVTIMEO(fd) (-1)
633 #endif
635 #ifdef SO_SNDTIMEO
636 #define GET_SNDTIMEO(fd) get_rcvsnd_timeo( (fd), SO_SNDTIMEO)
637 #else
638 #define GET_SNDTIMEO(fd) (-1)
639 #endif
641 /* utility: given an fd, will block until one of the events occurs */
642 static inline int do_block( int fd, int events, int timeout )
644 struct pollfd pfd;
645 int ret;
647 pfd.fd = fd;
648 pfd.events = events;
650 while ((ret = poll(&pfd, 1, timeout)) < 0)
652 if (errno != EINTR)
653 return -1;
655 if( ret == 0 )
656 return 0;
657 return pfd.revents;
661 /* ----------------------------------- API -----
663 * Init / cleanup / error checking.
666 /***********************************************************************
667 * WSAStartup (WS2_32.115)
669 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
671 TRACE("verReq=%x\n", wVersionRequested);
673 if (LOBYTE(wVersionRequested) < 1)
674 return WSAVERNOTSUPPORTED;
676 if (!lpWSAData) return WSAEINVAL;
678 num_startup++;
680 /* that's the whole of the negotiation for now */
681 lpWSAData->wVersion = wVersionRequested;
682 /* return winsock information */
683 lpWSAData->wHighVersion = 0x0202;
684 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
685 strcpy(lpWSAData->szSystemStatus, "Running" );
686 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
687 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
688 /* don't do anything with lpWSAData->lpVendorInfo */
689 /* (some apps don't allocate the space for this field) */
691 TRACE("succeeded\n");
692 return 0;
696 /***********************************************************************
697 * WSACleanup (WS2_32.116)
699 INT WINAPI WSACleanup(void)
701 if (num_startup)
702 return 0;
703 SetLastError(WSANOTINITIALISED);
704 return SOCKET_ERROR;
708 /***********************************************************************
709 * WSAGetLastError (WINSOCK.111)
710 * WSAGetLastError (WS2_32.111)
712 INT WINAPI WSAGetLastError(void)
714 return GetLastError();
717 /***********************************************************************
718 * WSASetLastError (WS2_32.112)
720 void WINAPI WSASetLastError(INT iError) {
721 SetLastError(iError);
724 static struct WS_hostent *check_buffer_he(int size)
726 struct per_thread_data * ptb = get_per_thread_data();
727 if (ptb->he_buffer)
729 if (ptb->he_len >= size ) return ptb->he_buffer;
730 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
732 ptb->he_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->he_len = size) );
733 if (!ptb->he_buffer) SetLastError(WSAENOBUFS);
734 return ptb->he_buffer;
737 static struct WS_servent *check_buffer_se(int size)
739 struct per_thread_data * ptb = get_per_thread_data();
740 if (ptb->se_buffer)
742 if (ptb->se_len >= size ) return ptb->se_buffer;
743 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
745 ptb->se_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->se_len = size) );
746 if (!ptb->se_buffer) SetLastError(WSAENOBUFS);
747 return ptb->se_buffer;
750 static struct WS_protoent *check_buffer_pe(int size)
752 struct per_thread_data * ptb = get_per_thread_data();
753 if (ptb->pe_buffer)
755 if (ptb->pe_len >= size ) return ptb->pe_buffer;
756 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
758 ptb->pe_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->pe_len = size) );
759 if (!ptb->pe_buffer) SetLastError(WSAENOBUFS);
760 return ptb->pe_buffer;
763 /* ----------------------------------- i/o APIs */
765 #ifdef HAVE_IPX
766 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
767 #else
768 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
769 #endif
772 /**********************************************************************/
774 /* Returns the converted address if successful, NULL if it was too small to
775 * start with. Note that the returned pointer may be the original pointer
776 * if no conversion is necessary.
778 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
780 switch (wsaddr->sa_family)
782 #ifdef HAVE_IPX
783 case WS_AF_IPX:
785 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
786 struct sockaddr_ipx* uipx;
788 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
789 return NULL;
791 *uaddrlen=sizeof(struct sockaddr_ipx);
792 uipx=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
793 uipx->sipx_family=AF_IPX;
794 uipx->sipx_port=wsipx->sa_socket;
795 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
796 * in one go
798 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
799 #ifdef IPX_FRAME_NONE
800 uipx->sipx_type=IPX_FRAME_NONE;
801 #endif
802 return (const struct sockaddr*)uipx;
804 #endif
806 default:
807 if (wsaddrlen<sizeof(struct WS_sockaddr))
808 return NULL;
810 /* No conversion needed, just return the original address */
811 *uaddrlen=wsaddrlen;
812 return (const struct sockaddr*)wsaddr;
816 /* Allocates a Unix sockaddr structure to receive the data */
817 inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
819 if (wsaddr==NULL)
821 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
823 /* This is not strictly the right thing to do. Hope it works however */
824 *uaddrlen=0;
826 return NULL;
829 if (*wsaddrlen==0)
830 *uaddrlen=0;
831 else
832 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
834 return HeapAlloc(GetProcessHeap(), 0, *uaddrlen);
837 /* Returns 0 if successful, -1 if the buffer is too small */
838 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
840 int res;
842 switch(uaddr->sa_family)
844 #ifdef HAVE_IPX
845 case AF_IPX:
847 struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
848 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
850 res=-1;
851 switch (*wsaddrlen) /* how much can we copy? */
853 default:
854 res=0; /* enough */
855 *wsaddrlen=uaddrlen;
856 wsipx->sa_socket=uipx->sipx_port;
857 /* fall through */
858 case 13:
859 case 12:
860 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
861 /* fall through */
862 case 11:
863 case 10:
864 case 9:
865 case 8:
866 case 7:
867 case 6:
868 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
869 /* fall through */
870 case 5:
871 case 4:
872 case 3:
873 case 2:
874 wsipx->sa_family=WS_AF_IPX;
875 /* fall through */
876 case 1:
877 case 0:
878 /* way too small */
879 break;
882 break;
883 #endif
885 default:
886 /* No conversion needed */
887 memcpy(wsaddr,uaddr,*wsaddrlen);
888 if (*wsaddrlen<uaddrlen) {
889 res=-1;
890 } else {
891 *wsaddrlen=uaddrlen;
892 res=0;
895 return res;
898 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
899 * ws_sockaddr_alloc
901 inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
903 if (uaddr!=(const struct sockaddr*)wsaddr)
904 HeapFree(GetProcessHeap(), 0, (void *)uaddr);
907 /**************************************************************************
908 * Functions for handling overlapped I/O
909 **************************************************************************/
911 static void CALLBACK ws2_async_terminate(ws2_async* as, IO_STATUS_BLOCK* iosb)
913 TRACE( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, iosb );
915 wine_server_release_fd( as->hSocket, as->fd );
916 if ( as->event != INVALID_HANDLE_VALUE )
917 NtSetEvent( as->event, NULL );
919 if (as->completion_func)
920 as->completion_func( NtStatusToWSAError (iosb->u.Status),
921 iosb->Information, as->user_overlapped, as->flags );
922 if ( !as->user_overlapped )
924 #if 0
925 /* FIXME: I don't think this is really used */
926 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
927 WSACloseEvent( as->overlapped->hEvent );
928 #endif
929 HeapFree( GetProcessHeap(), 0, iosb );
932 HeapFree( GetProcessHeap(), 0, as->iovec );
933 HeapFree( GetProcessHeap(), 0, as );
936 /***********************************************************************
937 * WS2_make_async (INTERNAL)
940 static void WINAPI WS2_async_recv(void*, IO_STATUS_BLOCK*, ULONG);
941 static void WINAPI WS2_async_send(void*, IO_STATUS_BLOCK*, ULONG);
942 static void WINAPI WS2_async_shutdown( void*, IO_STATUS_BLOCK*, ULONG);
944 inline static struct ws2_async*
945 WS2_make_async(SOCKET s, int fd, enum ws2_mode mode, struct iovec *iovec, DWORD dwBufferCount,
946 LPDWORD lpFlags, struct WS_sockaddr *addr,
947 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
948 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
949 IO_STATUS_BLOCK **piosb)
951 struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof( ws2_async ) );
953 TRACE( "wsa %p\n", wsa );
955 if (!wsa)
956 return NULL;
958 wsa->hSocket = (HANDLE) s;
959 wsa->mode = mode;
960 switch (mode)
962 case ws2m_read:
963 case ws2m_sd_read:
964 wsa->flags = *lpFlags;
965 wsa->addrlen.ptr = addrlen;
966 break;
967 case ws2m_write:
968 case ws2m_sd_write:
969 wsa->flags = 0;
970 wsa->addrlen.val = *addrlen;
971 break;
972 default:
973 ERR("Invalid async mode: %d\n", mode);
975 wsa->user_overlapped = lpOverlapped;
976 wsa->completion_func = lpCompletionRoutine;
977 wsa->iovec = iovec;
978 wsa->n_iovecs = dwBufferCount;
979 wsa->addr = addr;
980 wsa->fd = fd;
981 wsa->event = INVALID_HANDLE_VALUE;
983 if ( lpOverlapped )
985 *piosb = (IO_STATUS_BLOCK*)lpOverlapped;
986 if (!lpCompletionRoutine)
988 wsa->event = lpOverlapped->hEvent;
989 NtResetEvent(wsa->event, NULL);
992 else if (!(*piosb = HeapAlloc( GetProcessHeap(), 0, sizeof(IO_STATUS_BLOCK))))
993 goto error;
995 (*piosb)->Information = 0;
996 (*piosb)->u.Status = STATUS_PENDING;
997 TRACE( "wsa %p, h %p, ev %p, fd %d, iosb %p, uov %p, cfunc %p\n",
998 wsa, wsa->hSocket, wsa->event, wsa->fd,
999 *piosb, wsa->user_overlapped, wsa->completion_func );
1001 return wsa;
1003 error:
1004 TRACE("Error\n");
1005 HeapFree( GetProcessHeap(), 0, wsa );
1006 return NULL;
1009 static ULONG ws2_queue_async(struct ws2_async* wsa, IO_STATUS_BLOCK* iosb)
1011 PIO_APC_ROUTINE apc;
1012 int type;
1013 NTSTATUS status;
1015 switch (wsa->mode)
1017 case ws2m_read: apc = WS2_async_recv; type = ASYNC_TYPE_READ; break;
1018 case ws2m_write: apc = WS2_async_send; type = ASYNC_TYPE_WRITE; break;
1019 case ws2m_sd_read: apc = WS2_async_shutdown; type = ASYNC_TYPE_READ; break;
1020 case ws2m_sd_write: apc = WS2_async_shutdown; type = ASYNC_TYPE_WRITE; break;
1021 default: FIXME("Unknown internal mode (%d)\n", wsa->mode); return STATUS_INVALID_PARAMETER;
1024 SERVER_START_REQ( register_async )
1026 req->handle = wsa->hSocket;
1027 req->io_apc = apc;
1028 req->io_sb = iosb;
1029 req->io_user = wsa;
1030 req->type = type;
1031 req->count = iosb->Information;
1032 status = wine_server_call( req );
1034 SERVER_END_REQ;
1036 if ( status ) iosb->u.Status = status;
1037 if ( iosb->u.Status != STATUS_PENDING )
1039 /* Note: we get here a non zero status when we couldn't queue the async
1040 * in the server. Therefore, we simply terminate the async.
1042 status = iosb->u.Status;
1043 ws2_async_terminate(wsa, iosb);
1044 return status;
1046 NtCurrentTeb()->num_async_io++;
1047 return STATUS_SUCCESS;
1050 /***********************************************************************
1051 * WS2_recv (INTERNAL)
1053 * Workhorse for both synchronous and asynchronous recv() operations.
1055 static int WS2_recv( int fd, struct iovec* iov, int count,
1056 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1057 LPDWORD lpFlags )
1059 struct msghdr hdr;
1060 int n;
1061 TRACE( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
1062 fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
1064 hdr.msg_name = NULL;
1066 if ( lpFrom )
1068 hdr.msg_namelen = *lpFromlen;
1069 hdr.msg_name = ws_sockaddr_alloc( lpFrom, lpFromlen, &hdr.msg_namelen );
1070 if ( !hdr.msg_name )
1072 WSASetLastError( WSAEFAULT );
1073 n = -1;
1074 goto out;
1077 else
1078 hdr.msg_namelen = 0;
1080 hdr.msg_iov = iov;
1081 hdr.msg_iovlen = count;
1082 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1083 hdr.msg_accrights = NULL;
1084 hdr.msg_accrightslen = 0;
1085 #else
1086 hdr.msg_control = NULL;
1087 hdr.msg_controllen = 0;
1088 hdr.msg_flags = 0;
1089 #endif
1091 if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 )
1093 TRACE( "recvmsg error %d\n", errno);
1094 goto out;
1097 if ( lpFrom &&
1098 ws_sockaddr_u2ws( hdr.msg_name, hdr.msg_namelen,
1099 lpFrom, lpFromlen ) != 0 )
1101 /* The from buffer was too small, but we read the data
1102 * anyway. Is that really bad?
1104 WSASetLastError( WSAEFAULT );
1105 WARN( "Address buffer too small\n" );
1108 out:
1110 ws_sockaddr_free( hdr.msg_name, lpFrom );
1111 TRACE("-> %d\n", n);
1112 return n;
1115 /***********************************************************************
1116 * WS2_async_recv (INTERNAL)
1118 * Handler for overlapped recv() operations.
1120 static void WINAPI WS2_async_recv( void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
1122 ws2_async* wsa = (ws2_async*) ovp;
1123 int result, err;
1125 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1127 switch (status)
1129 case STATUS_ALERTED:
1130 result = WS2_recv( wsa->fd, wsa->iovec, wsa->n_iovecs,
1131 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1132 if (result >= 0)
1134 iosb->u.Status = STATUS_SUCCESS;
1135 iosb->Information = result;
1136 TRACE( "received %d bytes\n", result );
1137 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1139 else
1141 err = wsaErrno();
1142 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1144 iosb->u.Status = STATUS_PENDING;
1145 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1146 TRACE( "still pending\n" );
1148 else
1150 iosb->u.Status = err; /* FIXME: is this correct ???? */
1151 TRACE( "Error: %x\n", err );
1154 if (iosb->u.Status == STATUS_PENDING)
1155 ws2_queue_async(wsa, iosb);
1156 else
1157 ws2_async_terminate(wsa, iosb);
1158 break;
1159 default:
1160 FIXME( "status: %ld\n", status );
1161 iosb->u.Status = status;
1162 ws2_async_terminate(wsa, iosb);
1163 return;
1167 /***********************************************************************
1168 * WS2_send (INTERNAL)
1170 * Workhorse for both synchronous and asynchronous send() operations.
1172 static int WS2_send( int fd, struct iovec* iov, int count,
1173 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1175 struct msghdr hdr;
1176 int n = -1;
1177 TRACE( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
1178 fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
1180 hdr.msg_name = NULL;
1182 if ( to )
1184 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u( to, tolen, &hdr.msg_namelen );
1185 if ( !hdr.msg_name )
1187 WSASetLastError( WSAEFAULT );
1188 goto out;
1191 #ifdef HAVE_IPX
1192 if(to->sa_family == WS_AF_IPX)
1194 #ifdef SOL_IPX
1195 struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
1196 int val=0;
1197 int len=sizeof(int);
1199 /* The packet type is stored at the ipx socket level; At least the linux kernel seems
1200 * to do something with it in case hdr.msg_name is NULL. Nonetheless can we use it to store
1201 * the packet type and then we can retrieve it using getsockopt. After that we can set the
1202 * ipx type in the sockaddr_opx structure with the stored value.
1204 if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1)
1206 TRACE("ptype: %d (fd:%d)\n", val, fd);
1207 uipx->sipx_type = val;
1209 #endif
1211 #endif
1214 else
1215 hdr.msg_namelen = 0;
1217 hdr.msg_iov = iov;
1218 hdr.msg_iovlen = count;
1219 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1220 hdr.msg_accrights = NULL;
1221 hdr.msg_accrightslen = 0;
1222 #else
1223 hdr.msg_control = NULL;
1224 hdr.msg_controllen = 0;
1225 hdr.msg_flags = 0;
1226 #endif
1228 n = sendmsg(fd, &hdr, dwFlags);
1230 out:
1231 ws_sockaddr_free( hdr.msg_name, to );
1232 return n;
1235 /***********************************************************************
1236 * WS2_async_send (INTERNAL)
1238 * Handler for overlapped send() operations.
1240 static void WINAPI WS2_async_send(void* as, IO_STATUS_BLOCK* iosb, ULONG status)
1242 ws2_async* wsa = (ws2_async*) as;
1243 int result;
1245 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1247 switch (status)
1249 case STATUS_ALERTED:
1250 if (iosb->u.Status != STATUS_PENDING) FIXME("wrong %08lx\n", iosb->u.Status);
1251 /* check to see if the data is ready (non-blocking) */
1252 result = WS2_send( wsa->fd, wsa->iovec, wsa->n_iovecs,
1253 wsa->addr, wsa->addrlen.val, wsa->flags );
1255 if (result >= 0)
1257 iosb->u.Status = STATUS_SUCCESS;
1258 iosb->Information = result;
1259 TRACE( "sent %d bytes\n", result );
1260 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1262 else
1264 int err = wsaErrno();
1265 if ( err == WSAEINTR )
1267 iosb->u.Status = STATUS_PENDING;
1268 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1269 TRACE( "still pending\n" );
1271 else
1273 /* We set the status to a winsock error code and check for that
1274 later in NtStatusToWSAError () */
1275 iosb->u.Status = err;
1276 TRACE( "Error: %x\n", err );
1279 if (iosb->u.Status == STATUS_PENDING)
1280 ws2_queue_async(wsa, iosb);
1281 else
1282 ws2_async_terminate(wsa, iosb);
1283 break;
1284 default:
1285 FIXME( "status: %ld\n", status );
1286 iosb->u.Status = status;
1287 ws2_async_terminate(wsa, iosb);
1288 return;
1293 /***********************************************************************
1294 * WS2_async_shutdown (INTERNAL)
1296 * Handler for shutdown() operations on overlapped sockets.
1298 static void WINAPI WS2_async_shutdown( void* as, PIO_STATUS_BLOCK iosb, ULONG status )
1300 ws2_async* wsa = (ws2_async*) as;
1301 int err = 1;
1303 TRACE( "async %p %d\n", wsa, wsa->mode );
1304 switch (status)
1306 case STATUS_ALERTED:
1307 switch ( wsa->mode )
1309 case ws2m_sd_read: err = shutdown( wsa->fd, 0 ); break;
1310 case ws2m_sd_write: err = shutdown( wsa->fd, 1 ); break;
1311 default: ERR("invalid mode: %d\n", wsa->mode );
1313 iosb->u.Status = err ? wsaErrno() : STATUS_SUCCESS;
1314 if (iosb->u.Status == STATUS_PENDING)
1315 ws2_queue_async(wsa, iosb);
1316 else
1317 ws2_async_terminate(wsa, iosb);
1318 break;
1319 default:
1320 iosb->u.Status = status;
1321 ws2_async_terminate(wsa, iosb);
1322 break;
1327 /***********************************************************************
1328 * WS2_register_async_shutdown (INTERNAL)
1330 * Helper function for WS_shutdown() on overlapped sockets.
1332 static int WS2_register_async_shutdown( SOCKET s, int fd, enum ws2_mode mode )
1334 struct ws2_async *wsa;
1335 int ret, err = WSAEFAULT;
1336 DWORD dwflags = 0;
1337 int len = 0;
1338 LPWSAOVERLAPPED ovl = HeapAlloc(GetProcessHeap(), 0, sizeof( WSAOVERLAPPED ));
1339 IO_STATUS_BLOCK *iosb = NULL;
1341 TRACE("s %d fd %d mode %d\n", s, fd, mode);
1342 if (!ovl)
1343 goto out;
1345 ovl->hEvent = WSACreateEvent();
1346 if ( ovl->hEvent == WSA_INVALID_EVENT )
1347 goto out_free;
1349 wsa = WS2_make_async( s, fd, mode, NULL, 0,
1350 &dwflags, NULL, &len, ovl, NULL, &iosb );
1351 if ( !wsa )
1352 goto out_close;
1354 /* Hack: this will cause ws2_async_terminate() to free the overlapped structure */
1355 wsa->user_overlapped = NULL;
1356 if ( (ret = ws2_queue_async( wsa, iosb )) )
1358 err = NtStatusToWSAError( ret );
1359 goto out;
1361 /* Try immediate completion */
1362 while ( WaitForSingleObjectEx( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1363 return 0;
1365 out_close:
1366 WSACloseEvent( ovl->hEvent );
1367 out_free:
1368 HeapFree( GetProcessHeap(), 0, ovl );
1369 out:
1370 return err;
1373 /***********************************************************************
1374 * accept (WS2_32.1)
1376 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1377 int *addrlen32)
1379 SOCKET as;
1381 TRACE("socket %04x\n", s );
1382 if (_is_blocking(s))
1384 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1385 if (fd == -1) return INVALID_SOCKET;
1386 /* block here */
1387 do_block(fd, POLLIN, -1);
1388 _sync_sock_state(s); /* let wineserver notice connection */
1389 release_sock_fd( s, fd );
1390 /* retrieve any error codes from it */
1391 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1392 /* FIXME: care about the error? */
1394 SERVER_START_REQ( accept_socket )
1396 req->lhandle = SOCKET2HANDLE(s);
1397 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1398 req->inherit = TRUE;
1399 set_error( wine_server_call( req ) );
1400 as = HANDLE2SOCKET( reply->handle );
1402 SERVER_END_REQ;
1403 if (as)
1405 if (addr) WS_getpeername(as, addr, addrlen32);
1406 return as;
1408 return INVALID_SOCKET;
1411 /***********************************************************************
1412 * bind (WS2_32.2)
1414 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1416 int fd = get_sock_fd( s, 0, NULL );
1417 int res = SOCKET_ERROR;
1419 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1421 if (fd != -1)
1423 if (!name || !SUPPORTED_PF(name->sa_family))
1425 SetLastError(WSAEAFNOSUPPORT);
1427 else
1429 const struct sockaddr* uaddr;
1430 int uaddrlen;
1432 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1433 if (uaddr == NULL)
1435 SetLastError(WSAEFAULT);
1437 else
1439 if (bind(fd, uaddr, uaddrlen) < 0)
1441 int loc_errno = errno;
1442 WARN("\tfailure - errno = %i\n", errno);
1443 errno = loc_errno;
1444 switch (errno)
1446 case EBADF:
1447 SetLastError(WSAENOTSOCK);
1448 break;
1449 case EADDRNOTAVAIL:
1450 SetLastError(WSAEINVAL);
1451 break;
1452 default:
1453 SetLastError(wsaErrno());
1454 break;
1457 else
1459 res=0; /* success */
1461 ws_sockaddr_free(uaddr,name);
1464 release_sock_fd( s, fd );
1466 return res;
1469 /***********************************************************************
1470 * closesocket (WS2_32.3)
1472 int WINAPI WS_closesocket(SOCKET s)
1474 TRACE("socket %04x\n", s);
1475 if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1476 return SOCKET_ERROR;
1479 /***********************************************************************
1480 * connect (WS2_32.4)
1482 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1484 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1486 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1488 if (fd != -1)
1490 const struct sockaddr* uaddr;
1491 int uaddrlen;
1493 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1494 if (uaddr == NULL)
1496 SetLastError(WSAEFAULT);
1498 else
1500 int rc;
1502 rc=connect(fd, uaddr, uaddrlen);
1503 ws_sockaddr_free(uaddr,name);
1504 if (rc == 0)
1505 goto connect_success;
1508 if (errno == EINPROGRESS)
1510 /* tell wineserver that a connection is in progress */
1511 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1512 FD_CONNECT|FD_READ|FD_WRITE,
1513 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1514 if (_is_blocking(s))
1516 int result;
1517 /* block here */
1518 do_block(fd, POLLIN | POLLOUT, -1);
1519 _sync_sock_state(s); /* let wineserver notice connection */
1520 /* retrieve any error codes from it */
1521 result = _get_sock_error(s, FD_CONNECT_BIT);
1522 if (result)
1523 SetLastError(result);
1524 else
1526 goto connect_success;
1529 else
1531 SetLastError(WSAEWOULDBLOCK);
1534 else
1536 SetLastError(wsaErrno());
1538 release_sock_fd( s, fd );
1540 return SOCKET_ERROR;
1542 connect_success:
1543 release_sock_fd( s, fd );
1544 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1545 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1546 FD_CONNECT|FD_WINE_LISTENING);
1547 return 0;
1550 /***********************************************************************
1551 * WSAConnect (WS2_32.30)
1553 int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
1554 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1555 LPQOS lpSQOS, LPQOS lpGQOS )
1557 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1558 FIXME("unsupported parameters!\n");
1559 return WS_connect( s, name, namelen );
1563 /***********************************************************************
1564 * getpeername (WS2_32.5)
1566 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1568 int fd;
1569 int res;
1571 TRACE("socket: %04x, ptr %p, len %08x\n", s, name, *namelen);
1573 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1574 if( (name == NULL) || (namelen == NULL) )
1576 SetLastError( WSAEFAULT );
1577 return SOCKET_ERROR;
1580 fd = get_sock_fd( s, 0, NULL );
1581 res = SOCKET_ERROR;
1583 if (fd != -1)
1585 struct sockaddr* uaddr;
1586 int uaddrlen;
1588 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1589 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1591 SetLastError(wsaErrno());
1593 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1595 /* The buffer was too small */
1596 SetLastError(WSAEFAULT);
1598 else
1600 res=0;
1602 ws_sockaddr_free(uaddr,name);
1603 release_sock_fd( s, fd );
1605 return res;
1608 /***********************************************************************
1609 * getsockname (WS2_32.6)
1611 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1613 int fd;
1614 int res;
1616 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1618 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1619 if( (name == NULL) || (namelen == NULL) )
1621 SetLastError( WSAEFAULT );
1622 return SOCKET_ERROR;
1625 fd = get_sock_fd( s, 0, NULL );
1626 res = SOCKET_ERROR;
1628 if (fd != -1)
1630 struct sockaddr* uaddr;
1631 int uaddrlen;
1633 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1634 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1636 SetLastError(wsaErrno());
1638 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1640 /* The buffer was too small */
1641 SetLastError(WSAEFAULT);
1643 else
1645 res=0;
1647 ws_sockaddr_free(uaddr,name);
1648 release_sock_fd( s, fd );
1650 return res;
1653 /***********************************************************************
1654 * getsockopt (WS2_32.7)
1656 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1657 INT optname, char *optval, INT *optlen)
1659 int fd;
1660 INT ret = 0;
1662 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1663 (int) optname, (int) optval, (int) *optlen);
1664 /* SO_OPENTYPE does not require a valid socket handle. */
1665 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1667 if (!optlen || *optlen < sizeof(int) || !optval)
1669 SetLastError(WSAEFAULT);
1670 return SOCKET_ERROR;
1672 *(int *)optval = get_per_thread_data()->opentype;
1673 *optlen = sizeof(int);
1674 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1675 return 0;
1678 #ifdef HAVE_IPX
1679 if(level == NSPROTO_IPX)
1681 struct WS_sockaddr_ipx addr;
1682 IPX_ADDRESS_DATA *data;
1683 int namelen;
1684 switch(optname)
1686 case IPX_PTYPE:
1687 fd = get_sock_fd( s, 0, NULL );
1688 #ifdef SOL_IPX
1689 if(getsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
1691 return SOCKET_ERROR;
1693 #else
1695 struct ipx val;
1696 socklen_t len=sizeof(struct ipx);
1698 if(getsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, &len) == -1 )
1699 return SOCKET_ERROR;
1700 *optval = (int)val.ipx_pt;
1702 #endif
1703 TRACE("ptype: %d (fd: %d)\n", *(int*)optval, fd);
1704 release_sock_fd( s, fd );
1706 return 0;
1707 case IPX_ADDRESS:
1709 * On a Win2000 system with one network card there are usually three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
1710 * Using this call you can then retrieve info about this all. In case of Linux it is a bit different. Usually you have
1711 * only "one" device active and further it is not possible to query things like the linkspeed.
1713 FIXME("IPX_ADDRESS\n");
1714 namelen = sizeof(struct WS_sockaddr_ipx);
1715 memset(&addr, 0, sizeof(struct WS_sockaddr_ipx));
1716 WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
1718 data = (IPX_ADDRESS_DATA*)optval;
1719 memcpy(data->nodenum,&addr.sa_nodenum,sizeof(data->nodenum));
1720 memcpy(data->netnum,&addr.sa_netnum,sizeof(data->netnum));
1721 data->adapternum = 0;
1722 data->wan = FALSE; /* We are not on a wan for now .. */
1723 data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
1724 data->maxpkt = 1467; /* This value is the default one, at least on Win2k/WinXP */
1725 data->linkspeed = 100000; /* Set the line speed in 100bit/s to 10 Mbit; note 1MB = 1000kB in this case */
1726 return 0;
1727 case IPX_MAX_ADAPTER_NUM:
1728 FIXME("IPX_MAX_ADAPTER_NUM\n");
1729 *(int*)optval = 1; /* As noted under IPX_ADDRESS we have just one card. */
1731 return 0;
1732 default:
1733 FIXME("IPX optname:%x\n", optname);
1734 return SOCKET_ERROR;
1737 #endif
1739 if( (fd = get_sock_fd( s, 0, NULL )) == -1)
1740 return SOCKET_ERROR;
1742 if (!convert_sockopt(&level, &optname)) {
1743 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1744 ret = SOCKET_ERROR;
1745 } else {
1746 struct timeval tv;
1747 struct linger lingval;
1748 INT len, *plen = optlen;
1749 char *pval = optval;
1750 if(level == SOL_SOCKET && is_timeout_option(optname)) {
1751 len = sizeof(tv);
1752 plen = &len;
1753 pval = (char *) &tv;
1754 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1755 len = sizeof(lingval);
1756 plen = &len;
1757 pval = (char *) &lingval;
1759 if (getsockopt(fd, (int) level, optname, pval, plen) != 0 ) {
1760 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1761 ret = SOCKET_ERROR;
1762 } else if(level == SOL_SOCKET && is_timeout_option(optname)) {
1763 if( *optlen >= sizeof(INT) ) {
1764 *optlen = sizeof(INT);
1765 *(INT*)optval = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1766 } else {
1767 SetLastError(WSAEFAULT);
1768 ret = SOCKET_ERROR;
1770 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1771 if( *optlen >= sizeof( LINGER) ) {
1772 (( LINGER *) optval)->l_onoff = lingval.l_onoff;
1773 (( LINGER *) optval)->l_linger = lingval.l_linger;
1774 } else {
1775 SetLastError(WSAEFAULT);
1776 ret = SOCKET_ERROR;
1780 release_sock_fd( s, fd );
1781 return ret;
1785 /***********************************************************************
1786 * htonl (WINSOCK.8)
1787 * htonl (WS2_32.8)
1789 u_long WINAPI WS_htonl(u_long hostlong)
1791 return htonl(hostlong);
1795 /***********************************************************************
1796 * htons (WINSOCK.9)
1797 * htons (WS2_32.9)
1799 u_short WINAPI WS_htons(u_short hostshort)
1801 return htons(hostshort);
1804 /***********************************************************************
1805 * WSAHtonl (WS2_32.46)
1806 * From MSDN decription of error codes, this function should also
1807 * check if WinSock has been initialized and the socket is a valid
1808 * socket. But why? This function only translates a host byte order
1809 * u_long into a network byte order u_long...
1811 int WINAPI WSAHtonl(SOCKET s, u_long hostlong, u_long *lpnetlong)
1813 if (lpnetlong)
1815 *lpnetlong = htonl(hostlong);
1816 return 0;
1818 WSASetLastError(WSAEFAULT);
1819 return SOCKET_ERROR;
1822 /***********************************************************************
1823 * WSAHtons (WS2_32.47)
1824 * From MSDN decription of error codes, this function should also
1825 * check if WinSock has been initialized and the socket is a valid
1826 * socket. But why? This function only translates a host byte order
1827 * u_short into a network byte order u_short...
1829 int WINAPI WSAHtons(SOCKET s, u_short hostshort, u_short *lpnetshort)
1832 if (lpnetshort)
1834 *lpnetshort = htons(hostshort);
1835 return 0;
1837 WSASetLastError(WSAEFAULT);
1838 return SOCKET_ERROR;
1842 /***********************************************************************
1843 * inet_addr (WINSOCK.10)
1844 * inet_addr (WS2_32.11)
1846 u_long WINAPI WS_inet_addr(const char *cp)
1848 return inet_addr(cp);
1852 /***********************************************************************
1853 * ntohl (WINSOCK.14)
1854 * ntohl (WS2_32.14)
1856 u_long WINAPI WS_ntohl(u_long netlong)
1858 return ntohl(netlong);
1862 /***********************************************************************
1863 * ntohs (WINSOCK.15)
1864 * ntohs (WS2_32.15)
1866 u_short WINAPI WS_ntohs(u_short netshort)
1868 return ntohs(netshort);
1872 /***********************************************************************
1873 * inet_ntoa (WS2_32.12)
1875 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1877 /* use "buffer for dummies" here because some applications have a
1878 * propensity to decode addresses in ws_hostent structure without
1879 * saving them first...
1881 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1883 char* s = inet_ntoa(*((struct in_addr*)&in));
1884 if( s )
1886 strcpy(dbuffer, s);
1887 return dbuffer;
1889 SetLastError(wsaErrno());
1890 return NULL;
1893 /**********************************************************************
1894 * WSAIoctl (WS2_32.50)
1897 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1899 INT WINAPI WSAIoctl(SOCKET s,
1900 DWORD dwIoControlCode,
1901 LPVOID lpvInBuffer,
1902 DWORD cbInBuffer,
1903 LPVOID lpbOutBuffer,
1904 DWORD cbOutBuffer,
1905 LPDWORD lpcbBytesReturned,
1906 LPWSAOVERLAPPED lpOverlapped,
1907 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1909 int fd = get_sock_fd( s, 0, NULL );
1911 if (fd == -1) return SOCKET_ERROR;
1913 TRACE("%d, 0x%08lx, %p, %ld, %p, %ld, %p, %p, %p\n",
1914 s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpbOutBuffer,
1915 cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
1917 switch( dwIoControlCode )
1919 case SIO_GET_INTERFACE_LIST:
1921 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1922 DWORD size, numInt, apiReturn;
1924 TRACE("-> SIO_GET_INTERFACE_LIST request\n");
1926 if (!lpbOutBuffer)
1928 release_sock_fd( s, fd );
1929 WSASetLastError(WSAEFAULT);
1930 return SOCKET_ERROR;
1932 if (!lpcbBytesReturned)
1934 release_sock_fd( s, fd );
1935 WSASetLastError(WSAEFAULT);
1936 return SOCKET_ERROR;
1939 apiReturn = GetAdaptersInfo(NULL, &size);
1940 if (apiReturn == ERROR_NO_DATA)
1942 numInt = 0;
1944 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
1946 PIP_ADAPTER_INFO table = HeapAlloc(GetProcessHeap(),0,size);
1948 if (table)
1950 if (GetAdaptersInfo(table, &size) == NO_ERROR)
1952 PIP_ADAPTER_INFO ptr;
1954 if (size*sizeof(INTERFACE_INFO)/sizeof(IP_ADAPTER_INFO) > cbOutBuffer)
1956 WARN("Buffer too small = %lu, cbOutBuffer = %lu\n", size, cbOutBuffer);
1957 HeapFree(GetProcessHeap(),0,table);
1958 release_sock_fd( s, fd );
1959 WSASetLastError(WSAEFAULT);
1960 return SOCKET_ERROR;
1962 for (ptr = table, numInt = 0; ptr;
1963 ptr = ptr->Next, intArray++, numInt++)
1965 unsigned int addr, mask, bcast;
1966 struct ifreq ifInfo;
1968 /* Socket Status Flags */
1969 lstrcpynA(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
1970 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1972 ERR("Error obtaining status flags for socket!\n");
1973 HeapFree(GetProcessHeap(),0,table);
1974 release_sock_fd( s, fd );
1975 WSASetLastError(WSAEINVAL);
1976 return SOCKET_ERROR;
1978 else
1980 /* set flags; the values of IFF_* are not the same
1981 under Linux and Windows, therefore must generate
1982 new flags */
1983 intArray->iiFlags = 0;
1984 if (ifInfo.ifr_flags & IFF_BROADCAST)
1985 intArray->iiFlags |= WS_IFF_BROADCAST;
1986 #ifdef IFF_POINTOPOINT
1987 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
1988 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
1989 #endif
1990 if (ifInfo.ifr_flags & IFF_LOOPBACK)
1991 intArray->iiFlags |= WS_IFF_LOOPBACK;
1992 if (ifInfo.ifr_flags & IFF_UP)
1993 intArray->iiFlags |= WS_IFF_UP;
1994 if (ifInfo.ifr_flags & IFF_MULTICAST)
1995 intArray->iiFlags |= WS_IFF_MULTICAST;
1998 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
1999 mask = inet_addr(ptr->IpAddressList.IpMask.String);
2000 bcast = addr | (addr & !mask);
2001 intArray->iiAddress.AddressIn.sin_family = AF_INET;
2002 intArray->iiAddress.AddressIn.sin_port = 0;
2003 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
2004 addr;
2005 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2006 intArray->iiNetmask.AddressIn.sin_port = 0;
2007 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
2008 mask;
2009 intArray->iiBroadcastAddress.AddressIn.sin_family =
2010 AF_INET;
2011 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
2012 intArray->iiBroadcastAddress.AddressIn.sin_addr.
2013 WS_s_addr = bcast;
2016 else
2018 ERR("Unable to get interface table!\n");
2019 release_sock_fd( s, fd );
2020 HeapFree(GetProcessHeap(),0,table);
2021 WSASetLastError(WSAEINVAL);
2022 return SOCKET_ERROR;
2024 HeapFree(GetProcessHeap(),0,table);
2026 else
2028 release_sock_fd( s, fd );
2029 WSASetLastError(WSAEINVAL);
2030 return SOCKET_ERROR;
2033 else
2035 ERR("Unable to get interface table!\n");
2036 release_sock_fd( s, fd );
2037 WSASetLastError(WSAEINVAL);
2038 return SOCKET_ERROR;
2040 /* Calculate the size of the array being returned */
2041 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2042 break;
2045 case SIO_ADDRESS_LIST_CHANGE:
2046 FIXME("-> SIO_ADDRESS_LIST_CHANGE request: stub\n");
2047 /* FIXME: error and return code depend on whether socket was created
2048 * with WSA_FLAG_OVERLAPPED, but there is no easy way to get this */
2049 break;
2051 default:
2052 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2053 release_sock_fd( s, fd );
2054 WSASetLastError(WSAEOPNOTSUPP);
2055 return SOCKET_ERROR;
2058 /* Function executed with no errors */
2059 release_sock_fd( s, fd );
2060 return 0;
2064 /***********************************************************************
2065 * ioctlsocket (WS2_32.10)
2067 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2069 int fd;
2070 long newcmd = cmd;
2072 TRACE("socket %04x, cmd %08lx, ptr %p\n", s, cmd, argp);
2074 switch( cmd )
2076 case WS_FIONREAD:
2077 newcmd=FIONREAD;
2078 break;
2080 case WS_FIONBIO:
2081 if( _get_sock_mask(s) )
2083 /* AsyncSelect()'ed sockets are always nonblocking */
2084 if (*argp) return 0;
2085 SetLastError(WSAEINVAL);
2086 return SOCKET_ERROR;
2088 fd = get_sock_fd( s, 0, NULL );
2089 if (fd != -1)
2091 int ret;
2092 if (*argp)
2094 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2095 ret = fcntl( fd, F_SETFL, O_NONBLOCK );
2097 else
2099 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2100 ret = fcntl( fd, F_SETFL, 0 );
2102 release_sock_fd( s, fd );
2103 if (!ret) return 0;
2104 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2106 return SOCKET_ERROR;
2108 case WS_SIOCATMARK:
2109 newcmd=SIOCATMARK;
2110 break;
2112 case WS__IOW('f',125,u_long):
2113 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2114 SetLastError(WSAEINVAL);
2115 return SOCKET_ERROR;
2117 case SIOCGIFBRDADDR:
2118 case SIOCGIFNETMASK:
2119 case SIOCGIFADDR:
2120 /* These don't need any special handling. They are used by
2121 WsControl, and are here to suppress an unnecessary warning. */
2122 break;
2124 default:
2125 /* Netscape tries hard to use bogus ioctl 0x667e */
2126 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2127 break;
2130 fd = get_sock_fd( s, 0, NULL );
2131 if (fd != -1)
2133 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2135 release_sock_fd( s, fd );
2136 return 0;
2138 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2139 release_sock_fd( s, fd );
2141 return SOCKET_ERROR;
2144 /***********************************************************************
2145 * listen (WS2_32.13)
2147 int WINAPI WS_listen(SOCKET s, int backlog)
2149 int fd = get_sock_fd( s, GENERIC_READ, NULL );
2151 TRACE("socket %04x, backlog %d\n", s, backlog);
2152 if (fd != -1)
2154 if (listen(fd, backlog) == 0)
2156 release_sock_fd( s, fd );
2157 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2158 FD_WINE_LISTENING,
2159 FD_CONNECT|FD_WINE_CONNECTED);
2160 return 0;
2162 SetLastError(wsaErrno());
2163 release_sock_fd( s, fd );
2165 return SOCKET_ERROR;
2168 /***********************************************************************
2169 * recv (WS2_32.16)
2171 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2173 DWORD n, dwFlags = flags;
2174 WSABUF wsabuf;
2176 wsabuf.len = len;
2177 wsabuf.buf = buf;
2179 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2180 return SOCKET_ERROR;
2181 else
2182 return n;
2185 /***********************************************************************
2186 * recvfrom (WS2_32.17)
2188 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2189 struct WS_sockaddr *from, int *fromlen)
2191 DWORD n, dwFlags = flags;
2192 WSABUF wsabuf;
2194 wsabuf.len = len;
2195 wsabuf.buf = buf;
2197 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2198 return SOCKET_ERROR;
2199 else
2200 return n;
2203 /***********************************************************************
2204 * select (WS2_32.18)
2206 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2207 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2208 const struct WS_timeval* ws_timeout)
2210 int highfd = 0;
2211 fd_set readfds, writefds, exceptfds;
2212 fd_set *p_read, *p_write, *p_except;
2213 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2214 struct timeval timeout, *timeoutaddr = NULL;
2216 TRACE("read %p, write %p, excp %p timeout %p\n",
2217 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2219 p_read = fd_set_import(&readfds, ws_readfds, GENERIC_READ, &highfd, readfd);
2220 p_write = fd_set_import(&writefds, ws_writefds, GENERIC_WRITE, &highfd, writefd);
2221 p_except = fd_set_import(&exceptfds, ws_exceptfds, 0, &highfd, exceptfd);
2222 if (ws_timeout)
2224 timeoutaddr = &timeout;
2225 timeout.tv_sec=ws_timeout->tv_sec;
2226 timeout.tv_usec=ws_timeout->tv_usec;
2229 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2231 fd_set_export(&readfds, p_except, ws_readfds, readfd);
2232 fd_set_export(&writefds, p_except, ws_writefds, writefd);
2234 if (p_except && ws_exceptfds)
2236 unsigned int i, j;
2238 for (i = j = 0; i < ws_exceptfds->fd_count; i++)
2240 int fd = exceptfd[i];
2241 SOCKET s = ws_exceptfds->fd_array[i];
2242 if (fd == -1) continue;
2243 if (FD_ISSET(fd, &exceptfds)) ws_exceptfds->fd_array[j++] = s;
2244 release_sock_fd( s, fd );
2246 ws_exceptfds->fd_count = j;
2248 return highfd;
2250 fd_set_unimport(ws_readfds, readfd);
2251 fd_set_unimport(ws_writefds, writefd);
2252 fd_set_unimport(ws_exceptfds, exceptfd);
2254 if( highfd == 0 ) return 0;
2255 SetLastError(wsaErrno());
2256 return SOCKET_ERROR;
2260 /***********************************************************************
2261 * send (WS2_32.19)
2263 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2265 DWORD n;
2266 WSABUF wsabuf;
2268 wsabuf.len = len;
2269 wsabuf.buf = (char*) buf;
2271 if ( WSASendTo( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2272 return SOCKET_ERROR;
2273 else
2274 return n;
2277 /***********************************************************************
2278 * WSASend (WS2_32.72)
2280 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2281 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2282 LPWSAOVERLAPPED lpOverlapped,
2283 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2285 return WSASendTo( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2286 NULL, 0, lpOverlapped, lpCompletionRoutine );
2289 /***********************************************************************
2290 * WSASendDisconnect (WS2_32.73)
2292 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2294 return WS_shutdown( s, SD_SEND );
2298 /***********************************************************************
2299 * WSASendTo (WS2_32.74)
2301 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2302 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2303 const struct WS_sockaddr *to, int tolen,
2304 LPWSAOVERLAPPED lpOverlapped,
2305 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2307 unsigned int i;
2308 int n, fd, err = WSAENOTSOCK, flags, ret;
2309 struct iovec* iovec;
2310 struct ws2_async *wsa;
2311 IO_STATUS_BLOCK* iosb;
2313 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2314 s, lpBuffers, dwBufferCount, dwFlags,
2315 to, tolen, lpOverlapped, lpCompletionRoutine);
2317 fd = get_sock_fd( s, GENERIC_WRITE, &flags );
2318 TRACE( "fd=%d, flags=%x\n", fd, flags );
2320 if ( fd == -1 ) return SOCKET_ERROR;
2322 if (flags & FD_FLAG_SEND_SHUTDOWN)
2324 WSASetLastError( WSAESHUTDOWN );
2325 goto err_close;
2328 if ( !lpNumberOfBytesSent )
2330 err = WSAEFAULT;
2331 goto err_close;
2334 iovec = HeapAlloc(GetProcessHeap(), 0, dwBufferCount * sizeof(struct iovec) );
2336 if ( !iovec )
2338 err = WSAEFAULT;
2339 goto err_close;
2342 for ( i = 0; i < dwBufferCount; i++ )
2344 iovec[i].iov_base = lpBuffers[i].buf;
2345 iovec[i].iov_len = lpBuffers[i].len;
2348 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2350 wsa = WS2_make_async( s, fd, ws2m_write, iovec, dwBufferCount,
2351 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2352 lpOverlapped, lpCompletionRoutine, &iosb );
2353 if ( !wsa )
2355 err = WSAEFAULT;
2356 goto err_free;
2359 if ( ( ret = ws2_queue_async( wsa, iosb ) ) )
2361 err = NtStatusToWSAError( ret );
2363 if ( !lpOverlapped )
2364 HeapFree( GetProcessHeap(), 0, iosb );
2365 HeapFree( GetProcessHeap(), 0, wsa );
2366 goto err_free;
2369 /* Try immediate completion */
2370 if ( lpOverlapped )
2372 if ( WSAGetOverlappedResult( s, lpOverlapped,
2373 lpNumberOfBytesSent, FALSE, &dwFlags) )
2374 return 0;
2376 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
2377 goto error;
2380 WSASetLastError( WSA_IO_PENDING );
2381 return SOCKET_ERROR;
2384 if (_is_blocking(s))
2386 /* FIXME: exceptfds? */
2387 int timeout = GET_SNDTIMEO(fd);
2388 if( !do_block(fd, POLLOUT, timeout)) {
2389 err = WSAETIMEDOUT;
2390 goto err_free; /* msdn says a timeout in send is fatal */
2394 n = WS2_send( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2395 if ( n == -1 )
2397 err = wsaErrno();
2398 if ( err == WSAEWOULDBLOCK )
2399 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2400 goto err_free;
2403 TRACE(" -> %i bytes\n", n);
2404 *lpNumberOfBytesSent = n;
2406 HeapFree( GetProcessHeap(), 0, iovec );
2407 release_sock_fd( s, fd );
2408 return 0;
2410 err_free:
2411 HeapFree( GetProcessHeap(), 0, iovec );
2413 err_close:
2414 release_sock_fd( s, fd );
2416 error:
2417 WARN(" -> ERROR %d\n", err);
2418 WSASetLastError(err);
2419 return SOCKET_ERROR;
2422 /***********************************************************************
2423 * sendto (WS2_32.20)
2425 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2426 const struct WS_sockaddr *to, int tolen)
2428 DWORD n;
2429 WSABUF wsabuf;
2431 wsabuf.len = len;
2432 wsabuf.buf = (char*) buf;
2434 if ( WSASendTo(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2435 return SOCKET_ERROR;
2436 else
2437 return n;
2440 /***********************************************************************
2441 * setsockopt (WS2_32.21)
2443 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2444 const char *optval, int optlen)
2446 int fd;
2447 int woptval;
2448 struct linger linger;
2449 struct timeval tval;
2451 TRACE("socket: %04x, level %d, name %d, ptr %p, len %d\n",
2452 s, level, optname, optval, optlen);
2454 /* SO_OPENTYPE does not require a valid socket handle. */
2455 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2457 if (optlen < sizeof(int) || !optval)
2459 SetLastError(WSAEFAULT);
2460 return SOCKET_ERROR;
2462 get_per_thread_data()->opentype = *(int *)optval;
2463 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2464 return 0;
2467 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2468 * socket. This will either not happen under windows or it is ignored in
2469 * windows (but it works in linux and therefore prevents the game from
2470 * finding games outside the current network) */
2471 if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE )
2473 FIXME("Does windows ignore SO_DONTROUTE?\n");
2474 return 0;
2477 #ifdef HAVE_IPX
2478 if(level == NSPROTO_IPX)
2480 switch(optname)
2482 case IPX_PTYPE:
2483 fd = get_sock_fd( s, 0, NULL );
2484 TRACE("trying to set IPX_PTYPE: %d (fd: %d)\n", *(int*)optval, fd);
2486 /* We try to set the ipx type on ipx socket level. */
2487 #ifdef SOL_IPX
2488 if(setsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
2490 ERR("IPX: could not set ipx option type; expect weird behaviour\n");
2491 return SOCKET_ERROR;
2493 #else
2495 struct ipx val;
2496 /* Should we retrieve val using a getsockopt call and then
2497 * set the modified one? */
2498 val.ipx_pt = *optval;
2499 setsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, sizeof(struct ipx));
2501 #endif
2502 release_sock_fd( s, fd );
2503 return 0;
2504 case IPX_FILTERPTYPE:
2505 /* Sets the receive filter packet type, at the moment we don't support it */
2506 FIXME("IPX_FILTERPTYPE: %x\n", *optval);
2508 /* Returning 0 is better for now than returning a SOCKET_ERROR */
2509 return 0;
2510 default:
2511 FIXME("opt_name:%x\n", optname);
2512 return SOCKET_ERROR;
2514 return 0;
2516 #endif
2518 /* Is a privileged and useless operation, so we don't. */
2519 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET))
2521 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2522 return 0;
2525 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2526 /* This is unique to WinSock and takes special conversion */
2527 linger.l_onoff = *((int*)optval) ? 0: 1;
2528 linger.l_linger = 0;
2529 optname=SO_LINGER;
2530 optval = (char*)&linger;
2531 optlen = sizeof(struct linger);
2532 level = SOL_SOCKET;
2534 else
2536 if (!convert_sockopt(&level, &optname)) {
2537 ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2538 SetLastError(WSAENOPROTOOPT);
2539 return SOCKET_ERROR;
2541 if (optname == SO_LINGER && optval) {
2542 linger.l_onoff = ((LINGER*)optval)->l_onoff;
2543 linger.l_linger = ((LINGER*)optval)->l_linger;
2544 /* FIXME: what is documented behavior if SO_LINGER optval
2545 is null?? */
2546 optval = (char*)&linger;
2547 optlen = sizeof(struct linger);
2549 else if (optval && optlen < sizeof(int))
2551 woptval= *((INT16 *) optval);
2552 optval= (char*) &woptval;
2553 optlen=sizeof(int);
2555 if (level == SOL_SOCKET && is_timeout_option(optname))
2557 if (optlen == sizeof(UINT32)) {
2558 /* WinSock passes miliseconds instead of struct timeval */
2559 tval.tv_usec = (*(PUINT32)optval % 1000) * 1000;
2560 tval.tv_sec = *(PUINT32)optval / 1000;
2561 /* min of 500 milisec */
2562 if (tval.tv_sec == 0 && tval.tv_usec < 500000)
2563 tval.tv_usec = 500000;
2564 optlen = sizeof(struct timeval);
2565 optval = (char*)&tval;
2566 } else if (optlen == sizeof(struct timeval)) {
2567 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2568 } else {
2569 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2570 return 0;
2573 if (level == SOL_SOCKET && optname == SO_RCVBUF && *(int*)optval < 2048)
2575 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2576 return 0;
2581 fd = get_sock_fd( s, 0, NULL );
2582 if (fd == -1) return SOCKET_ERROR;
2584 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2586 release_sock_fd( s, fd );
2587 return 0;
2589 TRACE("Setting socket error, %d\n", wsaErrno());
2590 SetLastError(wsaErrno());
2591 release_sock_fd( s, fd );
2592 return SOCKET_ERROR;
2595 /***********************************************************************
2596 * shutdown (WS2_32.22)
2598 int WINAPI WS_shutdown(SOCKET s, int how)
2600 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2601 unsigned int clear_flags = 0;
2603 fd = get_sock_fd( s, 0, &flags );
2604 TRACE("socket %04x, how %i %x\n", s, how, flags );
2606 if (fd == -1)
2607 return SOCKET_ERROR;
2609 switch( how )
2611 case 0: /* drop receives */
2612 clear_flags |= FD_READ;
2613 break;
2614 case 1: /* drop sends */
2615 clear_flags |= FD_WRITE;
2616 break;
2617 case 2: /* drop all */
2618 clear_flags |= FD_READ|FD_WRITE;
2619 default:
2620 clear_flags |= FD_WINE_LISTENING;
2623 if ( flags & FD_FLAG_OVERLAPPED ) {
2625 switch ( how )
2627 case SD_RECEIVE:
2628 fd0 = fd;
2629 break;
2630 case SD_SEND:
2631 fd1 = fd;
2632 break;
2633 case SD_BOTH:
2634 default:
2635 fd0 = fd;
2636 fd1 = get_sock_fd( s, 0, NULL );
2637 break;
2640 if ( fd0 != -1 )
2642 err = WS2_register_async_shutdown( s, fd0, ws2m_sd_read );
2643 if ( err )
2645 release_sock_fd( s, fd0 );
2646 goto error;
2649 if ( fd1 != -1 )
2651 err = WS2_register_async_shutdown( s, fd1, ws2m_sd_write );
2652 if ( err )
2654 release_sock_fd( s, fd1 );
2655 goto error;
2659 else /* non-overlapped mode */
2661 if ( shutdown( fd, how ) )
2663 err = wsaErrno();
2664 release_sock_fd( s, fd );
2665 goto error;
2667 release_sock_fd( s, fd );
2670 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2671 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2672 return 0;
2674 error:
2675 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2676 WSASetLastError( err );
2677 return SOCKET_ERROR;
2680 /***********************************************************************
2681 * socket (WS2_32.23)
2683 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2685 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2687 return WSASocketA( af, type, protocol, NULL, 0,
2688 get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
2692 /***********************************************************************
2693 * gethostbyaddr (WS2_32.51)
2695 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
2697 struct WS_hostent *retval = NULL;
2698 struct hostent* host;
2700 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2701 char *extrabuf;
2702 int ebufsize=1024;
2703 struct hostent hostentry;
2704 int locerr=ENOBUFS;
2705 host = NULL;
2706 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2707 while(extrabuf) {
2708 int res = gethostbyaddr_r(addr, len, type,
2709 &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 = gethostbyaddr(addr, len, type);
2718 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2719 #endif
2720 if( host != NULL ) 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("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
2727 return retval;
2730 /***********************************************************************
2731 * gethostbyname (WS2_32.52)
2733 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2735 struct WS_hostent *retval = NULL;
2736 struct hostent* host;
2737 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2738 char *extrabuf;
2739 int ebufsize=1024;
2740 struct hostent hostentry;
2741 int locerr = ENOBUFS;
2742 #endif
2743 char buf[100];
2744 if( !name) {
2745 name = buf;
2746 if( gethostname( buf, 100) == -1) {
2747 SetLastError( WSAENOBUFS); /* appropriate ? */
2748 return retval;
2751 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2752 host = NULL;
2753 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2754 while(extrabuf) {
2755 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2756 if( res != ERANGE) break;
2757 ebufsize *=2;
2758 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2760 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2761 #else
2762 EnterCriticalSection( &csWSgetXXXbyYYY );
2763 host = gethostbyname(name);
2764 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2765 #endif
2766 if (host) retval = WS_dup_he(host);
2767 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2768 HeapFree(GetProcessHeap(),0,extrabuf);
2769 #else
2770 LeaveCriticalSection( &csWSgetXXXbyYYY );
2771 #endif
2772 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2773 return retval;
2777 /***********************************************************************
2778 * getprotobyname (WS2_32.53)
2780 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
2782 struct WS_protoent* retval = NULL;
2783 #ifdef HAVE_GETPROTOBYNAME
2784 struct protoent* proto;
2785 EnterCriticalSection( &csWSgetXXXbyYYY );
2786 if( (proto = getprotobyname(name)) != NULL )
2788 retval = WS_dup_pe(proto);
2790 else {
2791 MESSAGE("protocol %s not found; You might want to add "
2792 "this to /etc/protocols\n", debugstr_a(name) );
2793 SetLastError(WSANO_DATA);
2795 LeaveCriticalSection( &csWSgetXXXbyYYY );
2796 #endif
2797 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2798 return retval;
2802 /***********************************************************************
2803 * getprotobynumber (WS2_32.54)
2805 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
2807 struct WS_protoent* retval = NULL;
2808 #ifdef HAVE_GETPROTOBYNUMBER
2809 struct protoent* proto;
2810 EnterCriticalSection( &csWSgetXXXbyYYY );
2811 if( (proto = getprotobynumber(number)) != NULL )
2813 retval = WS_dup_pe(proto);
2815 else {
2816 MESSAGE("protocol number %d not found; You might want to add "
2817 "this to /etc/protocols\n", number );
2818 SetLastError(WSANO_DATA);
2820 LeaveCriticalSection( &csWSgetXXXbyYYY );
2821 #endif
2822 TRACE("%i ret %p\n", number, retval);
2823 return retval;
2827 /***********************************************************************
2828 * getservbyname (WS2_32.55)
2830 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
2832 struct WS_servent* retval = NULL;
2833 struct servent* serv;
2834 char *name_str;
2835 char *proto_str = NULL;
2837 if (!(name_str = strdup_lower(name))) return NULL;
2839 if (proto && *proto)
2841 if (!(proto_str = strdup_lower(proto)))
2843 HeapFree( GetProcessHeap(), 0, name_str );
2844 return NULL;
2848 EnterCriticalSection( &csWSgetXXXbyYYY );
2849 serv = getservbyname(name_str, proto_str);
2850 if( serv != NULL )
2852 retval = WS_dup_se(serv);
2854 else SetLastError(WSANO_DATA);
2855 LeaveCriticalSection( &csWSgetXXXbyYYY );
2856 HeapFree( GetProcessHeap(), 0, proto_str );
2857 HeapFree( GetProcessHeap(), 0, name_str );
2858 TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
2859 return retval;
2863 /***********************************************************************
2864 * getservbyport (WS2_32.56)
2866 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
2868 struct WS_servent* retval = NULL;
2869 #ifdef HAVE_GETSERVBYPORT
2870 struct servent* serv;
2871 char *proto_str = NULL;
2873 if (proto && *proto)
2875 if (!(proto_str = strdup_lower(proto))) return NULL;
2877 EnterCriticalSection( &csWSgetXXXbyYYY );
2878 if( (serv = getservbyport(port, proto_str)) != NULL ) {
2879 retval = WS_dup_se(serv);
2881 else SetLastError(WSANO_DATA);
2882 LeaveCriticalSection( &csWSgetXXXbyYYY );
2883 HeapFree( GetProcessHeap(), 0, proto_str );
2884 #endif
2885 TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
2886 return retval;
2890 /***********************************************************************
2891 * gethostname (WS2_32.57)
2893 int WINAPI WS_gethostname(char *name, int namelen)
2895 TRACE("name %p, len %d\n", name, namelen);
2897 if (gethostname(name, namelen) == 0)
2899 TRACE("<- '%s'\n", name);
2900 return 0;
2902 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2903 TRACE("<- ERROR !\n");
2904 return SOCKET_ERROR;
2908 /* ------------------------------------- Windows sockets extensions -- *
2910 * ------------------------------------------------------------------- */
2912 /***********************************************************************
2913 * WSAEnumNetworkEvents (WS2_32.36)
2915 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2917 int ret;
2919 TRACE("%08x, hEvent %p, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2921 SERVER_START_REQ( get_socket_event )
2923 req->handle = SOCKET2HANDLE(s);
2924 req->service = TRUE;
2925 req->c_event = hEvent;
2926 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
2927 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
2929 SERVER_END_REQ;
2930 if (!ret) return 0;
2931 SetLastError(WSAEINVAL);
2932 return SOCKET_ERROR;
2935 /***********************************************************************
2936 * WSAEventSelect (WS2_32.39)
2938 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, long lEvent)
2940 int ret;
2942 TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
2944 SERVER_START_REQ( set_socket_event )
2946 req->handle = SOCKET2HANDLE(s);
2947 req->mask = lEvent;
2948 req->event = hEvent;
2949 req->window = 0;
2950 req->msg = 0;
2951 ret = wine_server_call( req );
2953 SERVER_END_REQ;
2954 if (!ret) return 0;
2955 SetLastError(WSAEINVAL);
2956 return SOCKET_ERROR;
2959 /**********************************************************************
2960 * WSAGetOverlappedResult (WS2_32.40)
2962 BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
2963 LPDWORD lpcbTransfer, BOOL fWait,
2964 LPDWORD lpdwFlags )
2966 DWORD r;
2968 TRACE( "socket %04x ovl %p trans %p, wait %d flags %p\n",
2969 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
2971 if ( lpOverlapped == NULL )
2973 ERR( "Invalid pointer\n" );
2974 WSASetLastError(WSA_INVALID_PARAMETER);
2975 return FALSE;
2978 if ( fWait )
2980 if (lpOverlapped->hEvent)
2981 while ( WaitForSingleObjectEx(lpOverlapped->hEvent,
2982 INFINITE, TRUE) == STATUS_USER_APC );
2983 else /* busy loop */
2984 while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING )
2985 Sleep( 10 );
2988 else if ( lpOverlapped->Internal == STATUS_PENDING )
2990 /* Wait in order to give APCs a chance to run. */
2991 /* This is cheating, so we must set the event again in case of success -
2992 it may be a non-manual reset event. */
2993 while ( (r = WaitForSingleObjectEx(lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
2994 if ( r == WAIT_OBJECT_0 && lpOverlapped->hEvent )
2995 NtSetEvent( lpOverlapped->hEvent, NULL );
2998 if ( lpcbTransfer )
2999 *lpcbTransfer = lpOverlapped->InternalHigh;
3001 if ( lpdwFlags )
3002 *lpdwFlags = lpOverlapped->u.s.Offset;
3004 switch ( lpOverlapped->Internal )
3006 case STATUS_SUCCESS:
3007 return TRUE;
3008 case STATUS_PENDING:
3009 WSASetLastError( WSA_IO_INCOMPLETE );
3010 if (fWait) ERR("PENDING status after waiting!\n");
3011 return FALSE;
3012 default:
3013 WSASetLastError( NtStatusToWSAError( lpOverlapped->Internal ));
3014 return FALSE;
3019 /***********************************************************************
3020 * WSAAsyncSelect (WS2_32.101)
3022 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, long lEvent)
3024 int ret;
3026 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3028 SERVER_START_REQ( set_socket_event )
3030 req->handle = SOCKET2HANDLE(s);
3031 req->mask = lEvent;
3032 req->event = 0;
3033 req->window = hWnd;
3034 req->msg = uMsg;
3035 ret = wine_server_call( req );
3037 SERVER_END_REQ;
3038 if (!ret) return 0;
3039 SetLastError(WSAEINVAL);
3040 return SOCKET_ERROR;
3043 /***********************************************************************
3044 * WSACreateEvent (WS2_32.31)
3047 WSAEVENT WINAPI WSACreateEvent(void)
3049 /* Create a manual-reset event, with initial state: unsignaled */
3050 TRACE("\n");
3052 return CreateEventW(NULL, TRUE, FALSE, NULL);
3055 /***********************************************************************
3056 * WSACloseEvent (WS2_32.29)
3059 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3061 TRACE ("event=%p\n", event);
3063 return CloseHandle(event);
3066 /***********************************************************************
3067 * WSASocketA (WS2_32.78)
3070 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3071 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3072 GROUP g, DWORD dwFlags)
3074 INT len;
3075 WSAPROTOCOL_INFOW info;
3077 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3078 af, type, protocol, lpProtocolInfo, g, dwFlags);
3080 if (!lpProtocolInfo) return WSASocketW(af, type, protocol, NULL, g, dwFlags);
3082 memcpy(&info, lpProtocolInfo, FIELD_OFFSET(WSAPROTOCOL_INFOW, szProtocol));
3083 len = MultiByteToWideChar(CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3084 info.szProtocol, WSAPROTOCOL_LEN * sizeof(WCHAR) + 1);
3086 if (!len)
3088 WSASetLastError( WSAEINVAL);
3089 return SOCKET_ERROR;
3092 return WSASocketW(af, type, protocol, &info, g, dwFlags);
3095 /***********************************************************************
3096 * WSASocketW (WS2_32.79)
3099 SOCKET WINAPI WSASocketW(int af, int type, int protocol,
3100 LPWSAPROTOCOL_INFOW lpProtocolInfo,
3101 GROUP g, DWORD dwFlags)
3103 SOCKET ret;
3106 FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
3107 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3110 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3111 af, type, protocol, lpProtocolInfo, g, dwFlags );
3113 /* hack for WSADuplicateSocket */
3114 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3115 ret = lpProtocolInfo->dwCatalogEntryId;
3116 TRACE("\tgot duplicate %04x\n", ret);
3117 return ret;
3120 /* check the socket family */
3121 switch(af)
3123 #ifdef HAVE_IPX
3124 case WS_AF_IPX: af = AF_IPX;
3125 #endif
3126 case AF_INET:
3127 case AF_UNSPEC:
3128 break;
3129 default:
3130 SetLastError(WSAEAFNOSUPPORT);
3131 return INVALID_SOCKET;
3134 /* check the socket type */
3135 switch(type)
3137 case WS_SOCK_STREAM:
3138 type=SOCK_STREAM;
3139 break;
3140 case WS_SOCK_DGRAM:
3141 type=SOCK_DGRAM;
3142 break;
3143 case WS_SOCK_RAW:
3144 type=SOCK_RAW;
3145 break;
3146 default:
3147 SetLastError(WSAESOCKTNOSUPPORT);
3148 return INVALID_SOCKET;
3151 /* check the protocol type */
3152 if ( protocol < 0 ) /* don't support negative values */
3154 SetLastError(WSAEPROTONOSUPPORT);
3155 return INVALID_SOCKET;
3158 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3159 switch(protocol)
3161 case IPPROTO_TCP:
3162 if (type == SOCK_STREAM) { af = AF_INET; break; }
3163 case IPPROTO_UDP:
3164 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3165 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3168 SERVER_START_REQ( create_socket )
3170 req->family = af;
3171 req->type = type;
3172 req->protocol = protocol;
3173 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3174 req->flags = dwFlags;
3175 req->inherit = TRUE;
3176 set_error( wine_server_call( req ) );
3177 ret = HANDLE2SOCKET( reply->handle );
3179 SERVER_END_REQ;
3180 if (ret)
3182 TRACE("\tcreated %04x\n", ret );
3183 return ret;
3186 if (GetLastError() == WSAEACCES) /* raw socket denied */
3188 if (type == SOCK_RAW)
3189 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3190 else
3191 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3192 SetLastError(WSAESOCKTNOSUPPORT);
3195 WARN("\t\tfailed!\n");
3196 return INVALID_SOCKET;
3199 /***********************************************************************
3200 * WSAJoinLeaf (WS2_32.58)
3203 SOCKET WINAPI WSAJoinLeaf(
3204 SOCKET s,
3205 const struct WS_sockaddr *addr,
3206 int addrlen,
3207 LPWSABUF lpCallerData,
3208 LPWSABUF lpCalleeData,
3209 LPQOS lpSQOS,
3210 LPQOS lpGQOS,
3211 DWORD dwFlags)
3213 FIXME("stub.\n");
3214 return INVALID_SOCKET;
3217 /***********************************************************************
3218 * __WSAFDIsSet (WS2_32.151)
3220 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3222 int i = set->fd_count;
3224 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3226 while (i--)
3227 if (set->fd_array[i] == s) return 1;
3228 return 0;
3231 /***********************************************************************
3232 * WSAIsBlocking (WINSOCK.114)
3233 * WSAIsBlocking (WS2_32.114)
3235 BOOL WINAPI WSAIsBlocking(void)
3237 /* By default WinSock should set all its sockets to non-blocking mode
3238 * and poll in PeekMessage loop when processing "blocking" ones. This
3239 * function is supposed to tell if the program is in this loop. Our
3240 * blocking calls are truly blocking so we always return FALSE.
3242 * Note: It is allowed to call this function without prior WSAStartup().
3245 TRACE("\n");
3246 return FALSE;
3249 /***********************************************************************
3250 * WSACancelBlockingCall (WINSOCK.113)
3251 * WSACancelBlockingCall (WS2_32.113)
3253 INT WINAPI WSACancelBlockingCall(void)
3255 TRACE("\n");
3256 return 0;
3259 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
3261 FIXME("How was this called?\n");
3262 return x();
3266 /***********************************************************************
3267 * WSASetBlockingHook (WS2_32.109)
3269 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3271 FARPROC prev = blocking_hook;
3272 blocking_hook = lpBlockFunc;
3273 TRACE("hook %p\n", lpBlockFunc);
3274 return prev;
3278 /***********************************************************************
3279 * WSAUnhookBlockingHook (WS2_32.110)
3281 INT WINAPI WSAUnhookBlockingHook(void)
3283 blocking_hook = WSA_DefaultBlockingHook;
3284 return 0;
3288 /* ----------------------------------- end of API stuff */
3290 /* ----------------------------------- helper functions -
3292 * TODO: Merge WS_dup_..() stuff into one function that
3293 * would operate with a generic structure containing internal
3294 * pointers (via a template of some kind).
3297 static int list_size(char** l, int item_size)
3299 int i,j = 0;
3300 if(l)
3301 { for(i=0;l[i];i++)
3302 j += (item_size) ? item_size : strlen(l[i]) + 1;
3303 j += (i + 1) * sizeof(char*); }
3304 return j;
3307 static int list_dup(char** l_src, char** l_to, int item_size)
3309 char *p;
3310 int i;
3312 for (i = 0; l_src[i]; i++) ;
3313 p = (char *)(l_to + i + 1);
3314 for (i = 0; l_src[i]; i++)
3316 int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3317 memcpy(p, l_src[i], count);
3318 l_to[i] = p;
3319 p += count;
3321 l_to[i] = NULL;
3322 return p - (char *)l_to;
3325 /* ----- hostent */
3327 /* duplicate hostent entry
3328 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3329 * Dito for protoent and servent.
3331 static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
3333 char *p;
3334 struct WS_hostent *p_to;
3336 int size = (sizeof(*p_he) +
3337 strlen(p_he->h_name) + 1 +
3338 list_size(p_he->h_aliases, 0) +
3339 list_size(p_he->h_addr_list, p_he->h_length));
3341 if (!(p_to = check_buffer_he(size))) return NULL;
3342 p_to->h_addrtype = p_he->h_addrtype;
3343 p_to->h_length = p_he->h_length;
3345 p = (char *)(p_to + 1);
3346 p_to->h_name = p;
3347 strcpy(p, p_he->h_name);
3348 p += strlen(p) + 1;
3350 p_to->h_aliases = (char **)p;
3351 p += list_dup(p_he->h_aliases, p_to->h_aliases, 0);
3353 p_to->h_addr_list = (char **)p;
3354 list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length);
3355 return p_to;
3358 /* ----- protoent */
3360 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe)
3362 char *p;
3363 struct WS_protoent *p_to;
3365 int size = (sizeof(*p_pe) +
3366 strlen(p_pe->p_name) + 1 +
3367 list_size(p_pe->p_aliases, 0));
3369 if (!(p_to = check_buffer_pe(size))) return NULL;
3370 p_to->p_proto = p_pe->p_proto;
3372 p = (char *)(p_to + 1);
3373 p_to->p_name = p;
3374 strcpy(p, p_pe->p_name);
3375 p += strlen(p) + 1;
3377 p_to->p_aliases = (char **)p;
3378 list_dup(p_pe->p_aliases, p_to->p_aliases, 0);
3379 return p_to;
3382 /* ----- servent */
3384 static struct WS_servent *WS_dup_se(const struct servent* p_se)
3386 char *p;
3387 struct WS_servent *p_to;
3389 int size = (sizeof(*p_se) +
3390 strlen(p_se->s_proto) + 1 +
3391 strlen(p_se->s_name) + 1 +
3392 list_size(p_se->s_aliases, 0));
3394 if (!(p_to = check_buffer_se(size))) return NULL;
3395 p_to->s_port = p_se->s_port;
3397 p = (char *)(p_to + 1);
3398 p_to->s_name = p;
3399 strcpy(p, p_se->s_name);
3400 p += strlen(p) + 1;
3402 p_to->s_proto = p;
3403 strcpy(p, p_se->s_proto);
3404 p += strlen(p) + 1;
3406 p_to->s_aliases = (char **)p;
3407 list_dup(p_se->s_aliases, p_to->s_aliases, 0);
3408 return p_to;
3411 /* ----------------------------------- error handling */
3413 UINT wsaErrno(void)
3415 int loc_errno = errno;
3416 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3418 switch(loc_errno)
3420 case EINTR: return WSAEINTR;
3421 case EBADF: return WSAEBADF;
3422 case EPERM:
3423 case EACCES: return WSAEACCES;
3424 case EFAULT: return WSAEFAULT;
3425 case EINVAL: return WSAEINVAL;
3426 case EMFILE: return WSAEMFILE;
3427 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3428 case EINPROGRESS: return WSAEINPROGRESS;
3429 case EALREADY: return WSAEALREADY;
3430 case ENOTSOCK: return WSAENOTSOCK;
3431 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3432 case EMSGSIZE: return WSAEMSGSIZE;
3433 case EPROTOTYPE: return WSAEPROTOTYPE;
3434 case ENOPROTOOPT: return WSAENOPROTOOPT;
3435 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3436 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3437 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3438 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3439 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3440 case EADDRINUSE: return WSAEADDRINUSE;
3441 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3442 case ENETDOWN: return WSAENETDOWN;
3443 case ENETUNREACH: return WSAENETUNREACH;
3444 case ENETRESET: return WSAENETRESET;
3445 case ECONNABORTED: return WSAECONNABORTED;
3446 case EPIPE:
3447 case ECONNRESET: return WSAECONNRESET;
3448 case ENOBUFS: return WSAENOBUFS;
3449 case EISCONN: return WSAEISCONN;
3450 case ENOTCONN: return WSAENOTCONN;
3451 case ESHUTDOWN: return WSAESHUTDOWN;
3452 case ETOOMANYREFS: return WSAETOOMANYREFS;
3453 case ETIMEDOUT: return WSAETIMEDOUT;
3454 case ECONNREFUSED: return WSAECONNREFUSED;
3455 case ELOOP: return WSAELOOP;
3456 case ENAMETOOLONG: return WSAENAMETOOLONG;
3457 case EHOSTDOWN: return WSAEHOSTDOWN;
3458 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3459 case ENOTEMPTY: return WSAENOTEMPTY;
3460 #ifdef EPROCLIM
3461 case EPROCLIM: return WSAEPROCLIM;
3462 #endif
3463 #ifdef EUSERS
3464 case EUSERS: return WSAEUSERS;
3465 #endif
3466 #ifdef EDQUOT
3467 case EDQUOT: return WSAEDQUOT;
3468 #endif
3469 #ifdef ESTALE
3470 case ESTALE: return WSAESTALE;
3471 #endif
3472 #ifdef EREMOTE
3473 case EREMOTE: return WSAEREMOTE;
3474 #endif
3476 /* just in case we ever get here and there are no problems */
3477 case 0: return 0;
3478 default:
3479 WARN("Unknown errno %d!\n", loc_errno);
3480 return WSAEOPNOTSUPP;
3484 UINT wsaHerrno(int loc_errno)
3487 WARN("h_errno %d.\n", loc_errno);
3489 switch(loc_errno)
3491 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3492 case TRY_AGAIN: return WSATRY_AGAIN;
3493 case NO_RECOVERY: return WSANO_RECOVERY;
3494 case NO_DATA: return WSANO_DATA;
3495 case ENOBUFS: return WSAENOBUFS;
3497 case 0: return 0;
3498 default:
3499 WARN("Unknown h_errno %d!\n", loc_errno);
3500 return WSAEOPNOTSUPP;
3505 /***********************************************************************
3506 * WSARecv (WS2_32.67)
3508 int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3509 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3510 LPWSAOVERLAPPED lpOverlapped,
3511 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3513 return WSARecvFrom(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3514 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3517 /***********************************************************************
3518 * WSARecvFrom (WS2_32.69)
3520 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3521 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3522 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3523 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3526 unsigned int i;
3527 int n, fd, err = WSAENOTSOCK, flags, ret;
3528 struct iovec* iovec;
3529 struct ws2_async *wsa;
3530 IO_STATUS_BLOCK* iosb;
3532 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3533 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3534 (lpFromlen ? *lpFromlen : -1L),
3535 lpOverlapped, lpCompletionRoutine);
3537 fd = get_sock_fd( s, GENERIC_READ, &flags );
3538 TRACE( "fd=%d, flags=%x\n", fd, flags );
3540 if (fd == -1) return SOCKET_ERROR;
3542 if (flags & FD_FLAG_RECV_SHUTDOWN)
3544 WSASetLastError( WSAESHUTDOWN );
3545 goto err_close;
3548 iovec = HeapAlloc( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3549 if ( !iovec )
3551 err = WSAEFAULT;
3552 goto err_close;
3555 for (i = 0; i < dwBufferCount; i++)
3557 iovec[i].iov_base = lpBuffers[i].buf;
3558 iovec[i].iov_len = lpBuffers[i].len;
3561 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3563 wsa = WS2_make_async( s, fd, ws2m_read, iovec, dwBufferCount,
3564 lpFlags, lpFrom, lpFromlen,
3565 lpOverlapped, lpCompletionRoutine, &iosb );
3567 if ( !wsa )
3569 err = WSAEFAULT;
3570 goto err_free;
3573 if ( ( ret = ws2_queue_async( wsa, iosb )) )
3575 err = NtStatusToWSAError( ret );
3577 if ( !lpOverlapped )
3578 HeapFree( GetProcessHeap(), 0, iosb );
3579 HeapFree( GetProcessHeap(), 0, wsa );
3580 goto err_free;
3583 /* Try immediate completion */
3584 if ( lpOverlapped )
3586 if ( WSAGetOverlappedResult( s, lpOverlapped,
3587 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3588 return 0;
3590 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
3591 goto error;
3594 WSASetLastError( WSA_IO_PENDING );
3595 return SOCKET_ERROR;
3598 if ( _is_blocking(s) )
3600 /* block here */
3601 /* FIXME: OOB and exceptfds? */
3602 int timeout = GET_RCVTIMEO(fd);
3603 if( !do_block(fd, POLLIN, timeout)) {
3604 err = WSAETIMEDOUT;
3605 /* a timeout is not fatal */
3606 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3607 goto err_free;
3611 n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3612 if ( n == -1 )
3614 err = wsaErrno();
3615 goto err_free;
3618 TRACE(" -> %i bytes\n", n);
3619 *lpNumberOfBytesRecvd = n;
3621 HeapFree(GetProcessHeap(), 0, iovec);
3622 release_sock_fd( s, fd );
3623 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3625 return 0;
3627 err_free:
3628 HeapFree(GetProcessHeap(), 0, iovec);
3630 err_close:
3631 release_sock_fd( s, fd );
3633 error:
3634 WARN(" -> ERROR %d\n", err);
3635 WSASetLastError( err );
3636 return SOCKET_ERROR;
3639 /***********************************************************************
3640 * WSCInstallProvider (WS2_32.88)
3642 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
3643 LPCWSTR lpszProviderDllPath,
3644 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
3645 DWORD dwNumberOfEntries,
3646 LPINT lpErrno )
3648 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
3649 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
3650 dwNumberOfEntries, lpErrno);
3651 *lpErrno = 0;
3652 return 0;
3656 /***********************************************************************
3657 * WSCDeinstallProvider (WS2_32.83)
3659 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
3661 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
3662 *lpErrno = 0;
3663 return 0;
3667 /***********************************************************************
3668 * WSAAccept (WS2_32.26)
3670 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
3671 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
3674 int ret = 0, size = 0;
3675 WSABUF CallerId, CallerData, CalleeId, CalleeData;
3676 /* QOS SQOS, GQOS; */
3677 GROUP g;
3678 SOCKET cs;
3679 SOCKADDR src_addr, dst_addr;
3681 TRACE("Socket %04x, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
3682 s, addr, addrlen, lpfnCondition, dwCallbackData);
3685 size = sizeof(src_addr);
3686 cs = WS_accept(s, &src_addr, &size);
3688 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
3690 CallerId.buf = (char *)&src_addr;
3691 CallerId.len = sizeof(src_addr);
3693 CallerData.buf = NULL;
3694 CallerData.len = (ULONG)NULL;
3696 WS_getsockname(cs, &dst_addr, &size);
3698 CalleeId.buf = (char *)&dst_addr;
3699 CalleeId.len = sizeof(dst_addr);
3702 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
3703 &CalleeId, &CalleeData, &g, dwCallbackData);
3705 switch (ret)
3707 case CF_ACCEPT:
3708 if (addr && addrlen)
3709 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
3710 return cs;
3711 case CF_DEFER:
3712 SERVER_START_REQ( set_socket_deferred )
3714 req->handle = SOCKET2HANDLE(s);
3715 req->deferred = SOCKET2HANDLE(cs);
3716 if ( !wine_server_call_err ( req ) )
3718 SetLastError( WSATRY_AGAIN );
3719 WS_closesocket( cs );
3722 SERVER_END_REQ;
3723 return SOCKET_ERROR;
3724 case CF_REJECT:
3725 WS_closesocket(cs);
3726 SetLastError(WSAECONNREFUSED);
3727 return SOCKET_ERROR;
3728 default:
3729 FIXME("Unknown return type from Condition function\n");
3730 SetLastError(WSAENOTSOCK);
3731 return SOCKET_ERROR;
3735 /***********************************************************************
3736 * WSADuplicateSocketA (WS2_32.32)
3738 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
3740 HANDLE hProcess;
3742 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3743 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3744 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
3745 /* I don't know what the real Windoze does next, this is a hack */
3746 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
3747 * the target use the global duplicate, or we could copy a reference to us to the structure
3748 * and let the target duplicate it from us, but let's do it as simple as possible */
3749 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3750 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3751 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3752 0, FALSE, DUPLICATE_SAME_ACCESS);
3753 CloseHandle(hProcess);
3754 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3755 return 0;
3758 /***********************************************************************
3759 * WSADuplicateSocketW (WS2_32.33)
3761 int WINAPI WSADuplicateSocketW( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo )
3763 HANDLE hProcess;
3765 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3767 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3768 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3769 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3770 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3771 0, FALSE, DUPLICATE_SAME_ACCESS);
3772 CloseHandle(hProcess);
3773 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3774 return 0;
3777 /***********************************************************************
3778 * WSAInstallServiceClassA (WS2_32.48)
3780 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
3782 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
3783 WSASetLastError(WSAEACCES);
3784 return SOCKET_ERROR;
3787 /***********************************************************************
3788 * WSAInstallServiceClassW (WS2_32.49)
3790 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
3792 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
3793 WSASetLastError(WSAEACCES);
3794 return SOCKET_ERROR;
3797 /***********************************************************************
3798 * WSARemoveServiceClass (WS2_32.70)
3800 int WINAPI WSARemoveServiceClass(LPGUID info)
3802 FIXME("Request to remove service %p\n",info);
3803 WSASetLastError(WSATYPE_NOT_FOUND);
3804 return SOCKET_ERROR;
3807 /***********************************************************************
3808 * WSAStringToAddressA (WS2_32.80)
3810 INT WINAPI WSAStringToAddressA(LPSTR AddressString,
3811 INT AddressFamily,
3812 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3813 LPSOCKADDR lpAddress,
3814 LPINT lpAddressLength)
3816 INT res=0;
3817 LONG inetaddr;
3818 LPSTR workBuffer=NULL,ptrPort;
3820 TRACE( "(%s, %x, %p, %p, %p)\n", AddressString, AddressFamily, lpProtocolInfo,
3821 lpAddress, lpAddressLength );
3823 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
3825 if (AddressString)
3827 workBuffer = HeapAlloc( GetProcessHeap(), 0, strlen(AddressString)+1 );
3828 if (workBuffer)
3830 strcpy(workBuffer,AddressString);
3831 switch (AddressFamily)
3833 case AF_INET:
3834 /* caller wants to know the size of the socket buffer */
3835 if (*lpAddressLength < sizeof(SOCKADDR_IN))
3837 *lpAddressLength = sizeof(SOCKADDR_IN);
3838 res = WSAEFAULT;
3840 else
3842 /* caller wants to translate an AdressString into a SOCKADDR */
3843 if (lpAddress)
3845 memset(lpAddress,0,sizeof(SOCKADDR_IN));
3846 ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET;
3847 ptrPort = strchr(workBuffer,':');
3848 if (ptrPort)
3850 ((LPSOCKADDR_IN)lpAddress)->sin_port = (u_short)atoi(ptrPort+1);
3851 *ptrPort = '\0';
3853 else
3854 ((LPSOCKADDR_IN)lpAddress)->sin_port = 0;
3855 inetaddr = inet_addr(workBuffer);
3856 if (inetaddr != INADDR_NONE)
3858 ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr;
3859 res = 0;
3861 else
3862 res = WSAEINVAL;
3865 if (lpProtocolInfo)
3866 FIXME("(%s, %x, %p, %p, %p) - ProtocolInfo not implemented!\n",
3867 AddressString, AddressFamily,
3868 lpProtocolInfo, lpAddress, lpAddressLength);
3870 break;
3871 default:
3872 FIXME("(%s, %x, %p, %p, %p) - AddressFamiliy not implemented!\n",
3873 AddressString, AddressFamily,
3874 lpProtocolInfo, lpAddress, lpAddressLength);
3876 HeapFree( GetProcessHeap(), 0, workBuffer );
3878 else
3879 res = WSA_NOT_ENOUGH_MEMORY;
3881 else
3882 res = WSAEINVAL;
3884 if (!res) return 0;
3885 WSASetLastError(res);
3886 return SOCKET_ERROR;
3889 /***********************************************************************
3890 * WSAStringToAddressW (WS2_32.81)
3892 * Does anybody know if this functions allows to use hebrew/arabic/chinese... digits?
3893 * If this should be the case, it would be required to map these digits
3894 * to Unicode digits (0-9) using FoldString first.
3896 INT WINAPI WSAStringToAddressW(LPWSTR AddressString,
3897 INT AddressFamily,
3898 LPWSAPROTOCOL_INFOW lpProtocolInfo,
3899 LPSOCKADDR lpAddress,
3900 LPINT lpAddressLength)
3902 INT sBuffer,res=0;
3903 LPSTR workBuffer=NULL;
3904 WSAPROTOCOL_INFOA infoA;
3905 LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL;
3907 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_w(AddressString), AddressFamily, lpProtocolInfo,
3908 lpAddress, lpAddressLength );
3910 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
3912 /* if ProtocolInfo is available - convert to ANSI variant */
3913 if (lpProtocolInfo)
3915 lpProtoInfoA = &infoA;
3916 memcpy( lpProtoInfoA, lpProtocolInfo, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
3918 if (!WideCharToMultiByte( CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3919 lpProtoInfoA->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL ))
3921 WSASetLastError( WSAEINVAL);
3922 return SOCKET_ERROR;
3926 if (AddressString)
3928 /* Translate AddressString to ANSI code page - assumes that only
3929 standard digits 0-9 are used with this API call */
3930 sBuffer = WideCharToMultiByte( CP_ACP, 0, AddressString, -1, NULL, 0, NULL, NULL );
3931 workBuffer = HeapAlloc( GetProcessHeap(), 0, sBuffer );
3933 if (workBuffer)
3935 WideCharToMultiByte( CP_ACP, 0, AddressString, -1, workBuffer, sBuffer, NULL, NULL );
3936 res = WSAStringToAddressA(workBuffer,AddressFamily,lpProtoInfoA,
3937 lpAddress,lpAddressLength);
3938 HeapFree( GetProcessHeap(), 0, workBuffer );
3939 return res;
3941 else
3942 res = WSA_NOT_ENOUGH_MEMORY;
3944 else
3945 res = WSAEINVAL;
3947 WSASetLastError(res);
3948 return SOCKET_ERROR;
3951 /***********************************************************************
3952 * WSAAddressToStringA (WS2_32.27)
3954 * See WSAAddressToStringW
3956 INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len,
3957 LPWSAPROTOCOL_INFOA info, LPSTR string,
3958 LPDWORD lenstr )
3960 INT size;
3961 CHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
3962 CHAR *p;
3964 TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
3966 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
3967 if (!string || !lenstr) return SOCKET_ERROR;
3969 /* sin_family is garanteed to be the first u_short */
3970 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
3972 sprintf( buffer, "%u.%u.%u.%u:%u",
3973 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
3974 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
3975 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
3976 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
3977 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
3979 p = strchr( buffer, ':' );
3980 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
3982 size = strlen( buffer );
3984 if (*lenstr < size)
3986 *lenstr = size;
3987 return SOCKET_ERROR;
3990 strcpy( string, buffer );
3991 return 0;
3994 /***********************************************************************
3995 * WSAAddressToStringW (WS2_32.28)
3997 * Convert a sockaddr address into a readable address string.
3999 * PARAMS
4000 * sockaddr [I] Pointer to a sockaddr structure.
4001 * len [I] Size of the sockaddr structure.
4002 * info [I] Pointer to a WSAPROTOCOL_INFOW structure (optional).
4003 * string [I/O] Pointer to a buffer to receive the address string.
4004 * lenstr [I/O] Size of the receive buffer in WCHARs.
4006 * RETURNS
4007 * Success: 0
4008 * Failure: SOCKET_ERROR
4010 * NOTES
4011 * The 'info' parameter is ignored.
4013 * BUGS
4014 * Only supports AF_INET addresses.
4016 INT WINAPI WSAAddressToStringW( LPSOCKADDR sockaddr, DWORD len,
4017 LPWSAPROTOCOL_INFOW info, LPWSTR string,
4018 LPDWORD lenstr )
4020 INT size;
4021 WCHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
4022 static const WCHAR format[] = { '%','u','.','%','u','.','%','u','.','%','u',':','%','u',0 };
4023 WCHAR *p;
4025 TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
4027 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
4028 if (!string || !lenstr) return SOCKET_ERROR;
4030 /* sin_family is garanteed to be the first u_short */
4031 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
4033 sprintfW( buffer, format,
4034 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
4035 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
4036 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
4037 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
4038 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
4040 p = strchrW( buffer, ':' );
4041 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
4043 size = lstrlenW( buffer );
4045 if (*lenstr < size)
4047 *lenstr = size;
4048 return SOCKET_ERROR;
4051 lstrcpyW( string, buffer );
4052 return 0;
4055 /***********************************************************************
4056 * WSAEnumNameSpaceProvidersA (WS2_32.34)
4058 INT WINAPI WSAEnumNameSpaceProvidersA( LPDWORD len, LPWSANAMESPACE_INFOA buffer )
4060 FIXME( "(%p %p) Stub!\n", len, buffer );
4061 return 0;
4064 /***********************************************************************
4065 * WSAEnumNameSpaceProvidersW (WS2_32.35)
4067 INT WINAPI WSAEnumNameSpaceProvidersW( LPDWORD len, LPWSANAMESPACE_INFOW buffer )
4069 FIXME( "(%p %p) Stub!\n", len, buffer );
4070 return 0;
4073 /***********************************************************************
4074 * WSAGetQOSByName (WS2_32.41)
4076 BOOL WINAPI WSAGetQOSByName( SOCKET s, LPWSABUF lpQOSName, LPQOS lpQOS )
4078 FIXME( "(0x%04x %p %p) Stub!\n", s, lpQOSName, lpQOS );
4079 return FALSE;
4082 /***********************************************************************
4083 * WSAGetServiceClassInfoA (WS2_32.42)
4085 INT WINAPI WSAGetServiceClassInfoA( LPGUID provider, LPGUID service, LPDWORD len,
4086 LPWSASERVICECLASSINFOA info )
4088 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4089 len, info );
4090 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4091 return SOCKET_ERROR;
4094 /***********************************************************************
4095 * WSAGetServiceClassInfoW (WS2_32.43)
4097 INT WINAPI WSAGetServiceClassInfoW( LPGUID provider, LPGUID service, LPDWORD len,
4098 LPWSASERVICECLASSINFOW info )
4100 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4101 len, info );
4102 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4103 return SOCKET_ERROR;
4106 /***********************************************************************
4107 * WSAGetServiceClassNameByClassIdA (WS2_32.44)
4109 INT WINAPI WSAGetServiceClassNameByClassIdA( LPGUID class, LPSTR service, LPDWORD len )
4111 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4112 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4113 return SOCKET_ERROR;
4116 /***********************************************************************
4117 * WSAGetServiceClassNameByClassIdW (WS2_32.45)
4119 INT WINAPI WSAGetServiceClassNameByClassIdW( LPGUID class, LPWSTR service, LPDWORD len )
4121 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4122 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4123 return SOCKET_ERROR;
4126 /***********************************************************************
4127 * WSALookupServiceBeginA (WS2_32.59)
4129 INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
4130 DWORD dwControlFlags,
4131 LPHANDLE lphLookup)
4133 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4134 lphLookup);
4135 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4136 return SOCKET_ERROR;
4139 /***********************************************************************
4140 * WSALookupServiceBeginW (WS2_32.60)
4142 INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
4143 DWORD dwControlFlags,
4144 LPHANDLE lphLookup)
4146 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4147 lphLookup);
4148 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4149 return SOCKET_ERROR;
4152 /***********************************************************************
4153 * WSALookupServiceBeginW (WS2_32.61)
4155 INT WINAPI WSALookupServiceEnd( HANDLE lookup )
4157 FIXME("(%p) Stub!\n", lookup );
4158 return 0;
4161 /***********************************************************************
4162 * WSALookupServiceNextA (WS2_32.62)
4164 INT WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETA results )
4166 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4167 return 0;
4170 /***********************************************************************
4171 * WSALookupServiceNextW (WS2_32.63)
4173 INT WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETW results )
4175 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4176 return 0;
4179 /***********************************************************************
4180 * WSANtohl (WS2_32.64)
4182 INT WINAPI WSANtohl( SOCKET s, u_long netlong, u_long* lphostlong )
4184 TRACE( "(0x%04x 0x%08lx %p)\n", s, netlong, lphostlong );
4186 if (!lphostlong) return WSAEFAULT;
4188 *lphostlong = ntohl( netlong );
4189 return 0;
4192 /***********************************************************************
4193 * WSANtohs (WS2_32.65)
4195 INT WINAPI WSANtohs( SOCKET s, u_short netshort, u_short* lphostshort )
4197 TRACE( "(0x%04x 0x%08x %p)\n", s, netshort, lphostshort );
4199 if (!lphostshort) return WSAEFAULT;
4201 *lphostshort = ntohs( netshort );
4202 return 0;
4205 /***********************************************************************
4206 * WSAProviderConfigChange (WS2_32.66)
4208 INT WINAPI WSAProviderConfigChange( LPHANDLE handle, LPWSAOVERLAPPED overlapped,
4209 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
4211 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
4212 return SOCKET_ERROR;
4215 /***********************************************************************
4216 * WSARecvDisconnect (WS2_32.68)
4218 INT WINAPI WSARecvDisconnect( SOCKET s, LPWSABUF disconnectdata )
4220 TRACE( "(0x%04x %p)\n", s, disconnectdata );
4222 return WS_shutdown( s, 0 );
4225 /***********************************************************************
4226 * WSASetServiceA (WS2_32.76)
4228 INT WINAPI WSASetServiceA( LPWSAQUERYSETA query, WSAESETSERVICEOP operation, DWORD flags )
4230 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4231 return 0;
4234 /***********************************************************************
4235 * WSASetServiceW (WS2_32.77)
4237 INT WINAPI WSASetServiceW( LPWSAQUERYSETW query, WSAESETSERVICEOP operation, DWORD flags )
4239 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4240 return 0;
4243 /***********************************************************************
4244 * WSCEnableNSProvider (WS2_32.84)
4246 INT WINAPI WSCEnableNSProvider( LPGUID provider, BOOL enable )
4248 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
4249 return 0;
4252 /***********************************************************************
4253 * WSCGetProviderPath (WS2_32.86)
4255 INT WINAPI WSCGetProviderPath( LPGUID provider, LPWSTR path, LPINT len, LPINT errno )
4257 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errno );
4259 if (!errno || !provider || !len) return WSAEFAULT;
4261 *errno = WSAEINVAL;
4262 return SOCKET_ERROR;
4265 /***********************************************************************
4266 * WSCInstallNameSpace (WS2_32.87)
4268 INT WINAPI WSCInstallNameSpace( LPWSTR identifier, LPWSTR path, DWORD namespace,
4269 DWORD version, LPGUID provider )
4271 FIXME( "(%s %s 0x%08lx 0x%08lx %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
4272 namespace, version, debugstr_guid(provider) );
4273 return 0;
4276 /***********************************************************************
4277 * WSCUnInstallNameSpace (WS2_32.89)
4279 INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
4281 FIXME("(%p) Stub!\n", lpProviderId);
4282 return NO_ERROR;
4285 /***********************************************************************
4286 * WSCWriteProviderOrder (WS2_32.91)
4288 INT WINAPI WSCWriteProviderOrder( LPDWORD entry, DWORD number )
4290 FIXME("(%p 0x%08lx) Stub!\n", entry, number);
4291 return 0;