- got rid of include/async.h
[wine.git] / dlls / winsock / socket.c
blob41dda63676ccbce76ae20fc4cc7bd2bddbd51020
1 /*
2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
5 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * NOTE: If you make any changes to fix a particular app, make sure
22 * they don't break something else like Netscape or telnet and ftp
23 * clients and servers (www.winsite.com got a lot of those).
26 #include "config.h"
27 #include "wine/port.h"
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #ifdef HAVE_SYS_IPC_H
34 # include <sys/ipc.h>
35 #endif
36 #ifdef HAVE_SYS_IOCTL_H
37 # include <sys/ioctl.h>
38 #endif
39 #ifdef HAVE_SYS_FILIO_H
40 # include <sys/filio.h>
41 #endif
42 #ifdef HAVE_SYS_SOCKIO_H
43 # include <sys/sockio.h>
44 #endif
46 #if defined(__EMX__)
47 # include <sys/so_ioctl.h>
48 #endif
50 #ifdef HAVE_SYS_PARAM_H
51 # include <sys/param.h>
52 #endif
54 #ifdef HAVE_SYS_MSG_H
55 # include <sys/msg.h>
56 #endif
57 #ifdef HAVE_SYS_WAIT_H
58 # include <sys/wait.h>
59 #endif
60 #ifdef HAVE_SYS_UIO_H
61 # include <sys/uio.h>
62 #endif
63 #ifdef HAVE_SYS_SOCKET_H
64 #include <sys/socket.h>
65 #endif
66 #ifdef HAVE_NETINET_IN_H
67 # include <netinet/in.h>
68 #endif
69 #ifdef HAVE_NETINET_TCP_H
70 # include <netinet/tcp.h>
71 #endif
72 #ifdef HAVE_ARPA_INET_H
73 # include <arpa/inet.h>
74 #endif
75 #include <ctype.h>
76 #include <fcntl.h>
77 #include <errno.h>
78 #ifdef HAVE_SYS_ERRNO_H
79 #include <sys/errno.h>
80 #endif
81 #ifdef HAVE_NETDB_H
82 #include <netdb.h>
83 #endif
84 #ifdef HAVE_UNISTD_H
85 # include <unistd.h>
86 #endif
87 #include <stdlib.h>
88 #ifdef HAVE_ARPA_NAMESER_H
89 # include <arpa/nameser.h>
90 #endif
91 #ifdef HAVE_RESOLV_H
92 # include <resolv.h>
93 #endif
94 #ifdef HAVE_NET_IF_H
95 # include <net/if.h>
96 #endif
97 #ifdef HAVE_IPX_GNU
98 # include <netipx/ipx.h>
99 # define HAVE_IPX
100 #endif
101 #ifdef HAVE_IPX_LINUX
102 # include <asm/types.h>
103 # include <linux/ipx.h>
104 # define HAVE_IPX
105 #endif
107 #ifdef HAVE_SYS_POLL_H
108 # include <sys/poll.h>
109 #endif
110 #ifdef HAVE_SYS_TIME_H
111 # include <sys/time.h>
112 #endif
114 #define NONAMELESSUNION
115 #define NONAMELESSSTRUCT
116 #include "windef.h"
117 #include "winbase.h"
118 #include "wingdi.h"
119 #include "winuser.h"
120 #include "winerror.h"
121 #include "winnls.h"
122 #include "winsock2.h"
123 #include "mswsock.h"
124 #include "ws2tcpip.h"
125 #include "wsipx.h"
126 #include "winnt.h"
127 #include "iphlpapi.h"
128 #include "thread.h"
129 #include "wine/server.h"
130 #include "wine/debug.h"
131 #include "ntstatus.h"
132 #include "wine/unicode.h"
134 #ifdef HAVE_IPX
135 # include "wsnwlink.h"
136 #endif
139 #ifdef __FreeBSD__
140 # define sipx_network sipx_addr.x_net
141 # define sipx_node sipx_addr.x_host.c_host
142 #endif /* __FreeBSD__ */
144 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
146 /* critical section to protect some non-rentrant net function */
147 extern CRITICAL_SECTION csWSgetXXXbyYYY;
149 inline static const char *debugstr_sockaddr( const struct WS_sockaddr *a )
151 if (!a) return "(nil)";
152 return wine_dbg_sprintf("{ family %d, address %s, port %d }",
153 ((struct sockaddr_in *)a)->sin_family,
154 inet_ntoa(((struct sockaddr_in *)a)->sin_addr),
155 ntohs(((struct sockaddr_in *)a)->sin_port));
158 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
159 #define SOCKET2HANDLE(s) ((HANDLE)(s))
160 #define HANDLE2SOCKET(h) ((SOCKET)(h))
162 /****************************************************************
163 * Async IO declarations
164 ****************************************************************/
166 typedef struct ws2_async
168 HANDLE hSocket;
169 enum ws2_mode {ws2m_read, ws2m_write, ws2m_sd_read, ws2m_sd_write} mode;
170 LPWSAOVERLAPPED user_overlapped;
171 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
172 struct iovec *iovec;
173 int n_iovecs;
174 struct WS_sockaddr *addr;
175 union
177 int val; /* for send operations */
178 int *ptr; /* for recv operations */
179 } addrlen;
180 DWORD flags;
181 int fd;
182 HANDLE event;
183 } ws2_async;
185 /****************************************************************/
187 /* ----------------------------------- internal data */
189 /* ws_... struct conversion flags */
191 typedef struct /* WSAAsyncSelect() control struct */
193 HANDLE service, event, sock;
194 HWND hWnd;
195 UINT uMsg;
196 LONG lEvent;
197 } ws_select_info;
199 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
200 #define WS_MAX_UDP_DATAGRAM 1024
201 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
203 /* hostent's, servent's and protent's are stored in one buffer per thread,
204 * as documented on MSDN for the functions that return any of the buffers */
205 struct per_thread_data
207 int opentype;
208 struct WS_hostent *he_buffer;
209 struct WS_servent *se_buffer;
210 struct WS_protoent *pe_buffer;
211 int he_len;
212 int se_len;
213 int pe_len;
216 static DWORD tls_index = TLS_OUT_OF_INDEXES; /* TLS index for per-thread data */
217 static INT num_startup; /* reference counter */
218 static FARPROC blocking_hook = WSA_DefaultBlockingHook;
220 /* function prototypes */
221 static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
222 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe);
223 static struct WS_servent *WS_dup_se(const struct servent* p_se);
225 int WSAIOCTL_GetInterfaceCount(void);
226 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
228 UINT wsaErrno(void);
229 UINT wsaHerrno(int errnr);
231 #define MAP_OPTION(opt) { WS_##opt, opt }
233 static const int ws_sock_map[][2] =
235 MAP_OPTION( SO_DEBUG ),
236 MAP_OPTION( SO_REUSEADDR ),
237 MAP_OPTION( SO_KEEPALIVE ),
238 MAP_OPTION( SO_DONTROUTE ),
239 MAP_OPTION( SO_BROADCAST ),
240 MAP_OPTION( SO_LINGER ),
241 MAP_OPTION( SO_OOBINLINE ),
242 MAP_OPTION( SO_SNDBUF ),
243 MAP_OPTION( SO_RCVBUF ),
244 MAP_OPTION( SO_ERROR ),
245 MAP_OPTION( SO_TYPE ),
246 #ifdef SO_RCVTIMEO
247 MAP_OPTION( SO_RCVTIMEO ),
248 #endif
249 #ifdef SO_SNDTIMEO
250 MAP_OPTION( SO_SNDTIMEO ),
251 #endif
252 { 0, 0 }
255 static const int ws_tcp_map[][2] =
257 #ifdef TCP_NODELAY
258 MAP_OPTION( TCP_NODELAY ),
259 #endif
260 { 0, 0 }
263 static const int ws_ip_map[][2] =
265 MAP_OPTION( IP_MULTICAST_IF ),
266 MAP_OPTION( IP_MULTICAST_TTL ),
267 MAP_OPTION( IP_MULTICAST_LOOP ),
268 MAP_OPTION( IP_ADD_MEMBERSHIP ),
269 MAP_OPTION( IP_DROP_MEMBERSHIP ),
270 MAP_OPTION( IP_OPTIONS ),
271 #ifdef IP_HDRINCL
272 MAP_OPTION( IP_HDRINCL ),
273 #endif
274 MAP_OPTION( IP_TOS ),
275 MAP_OPTION( IP_TTL ),
276 { 0, 0 }
279 inline static DWORD NtStatusToWSAError( const DWORD status )
281 /* We only need to cover the status codes set by server async request handling */
282 DWORD wserr;
283 switch ( status )
285 case STATUS_SUCCESS: wserr = 0; break;
286 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
287 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
288 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
289 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
290 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
291 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
292 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
293 default:
294 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
295 /* It is not a NT status code but a winsock error */
296 wserr = status;
297 else
299 wserr = RtlNtStatusToDosError( status );
300 FIXME( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
303 return wserr;
306 /* set last error code from NT status without mapping WSA errors */
307 inline static unsigned int set_error( unsigned int err )
309 if (err)
311 err = NtStatusToWSAError( err );
312 SetLastError( err );
314 return err;
317 inline static int get_sock_fd( SOCKET s, DWORD access, int *flags )
319 int fd;
320 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, flags ) ))
321 return -1;
322 return fd;
325 inline static void release_sock_fd( SOCKET s, int fd )
327 wine_server_release_fd( SOCKET2HANDLE(s), fd );
330 static void _enable_event( HANDLE s, unsigned int event,
331 unsigned int sstate, unsigned int cstate )
333 SERVER_START_REQ( enable_socket_event )
335 req->handle = s;
336 req->mask = event;
337 req->sstate = sstate;
338 req->cstate = cstate;
339 wine_server_call( req );
341 SERVER_END_REQ;
344 static int _is_blocking(SOCKET s)
346 int ret;
347 SERVER_START_REQ( get_socket_event )
349 req->handle = SOCKET2HANDLE(s);
350 req->service = FALSE;
351 req->c_event = 0;
352 wine_server_call( req );
353 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
355 SERVER_END_REQ;
356 return ret;
359 static unsigned int _get_sock_mask(SOCKET s)
361 unsigned int ret;
362 SERVER_START_REQ( get_socket_event )
364 req->handle = SOCKET2HANDLE(s);
365 req->service = FALSE;
366 req->c_event = 0;
367 wine_server_call( req );
368 ret = reply->mask;
370 SERVER_END_REQ;
371 return ret;
374 static void _sync_sock_state(SOCKET s)
376 /* do a dummy wineserver request in order to let
377 the wineserver run through its select loop once */
378 (void)_is_blocking(s);
381 static int _get_sock_error(SOCKET s, unsigned int bit)
383 int events[FD_MAX_EVENTS];
385 SERVER_START_REQ( get_socket_event )
387 req->handle = SOCKET2HANDLE(s);
388 req->service = FALSE;
389 req->c_event = 0;
390 wine_server_set_reply( req, events, sizeof(events) );
391 wine_server_call( req );
393 SERVER_END_REQ;
394 return events[bit];
397 static struct per_thread_data *get_per_thread_data(void)
399 struct per_thread_data * ptb = TlsGetValue( tls_index );
400 /* lazy initialization */
401 if (!ptb)
403 ptb = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptb) );
404 TlsSetValue( tls_index, ptb );
406 return ptb;
409 static void free_per_thread_data(void)
411 struct per_thread_data * ptb = TlsGetValue( tls_index );
413 if (!ptb) return;
415 /* delete scratch buffers */
416 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
417 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
418 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
419 ptb->he_buffer = NULL;
420 ptb->se_buffer = NULL;
421 ptb->pe_buffer = NULL;
423 HeapFree( GetProcessHeap(), 0, ptb );
426 /***********************************************************************
427 * DllMain (WS2_32.init)
429 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
431 TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
432 switch (fdwReason) {
433 case DLL_PROCESS_ATTACH:
434 tls_index = TlsAlloc();
435 break;
436 case DLL_PROCESS_DETACH:
437 free_per_thread_data();
438 TlsFree( tls_index );
439 num_startup = 0;
440 break;
441 case DLL_THREAD_DETACH:
442 free_per_thread_data();
443 break;
445 return TRUE;
448 /***********************************************************************
449 * convert_sockopt()
451 * Converts socket flags from Windows format.
452 * Return 1 if converted, 0 if not (error).
454 static int convert_sockopt(INT *level, INT *optname)
456 int i;
457 switch (*level)
459 case WS_SOL_SOCKET:
460 *level = SOL_SOCKET;
461 for(i=0; ws_sock_map[i][0]; i++)
463 if( ws_sock_map[i][0] == *optname )
465 *optname = ws_sock_map[i][1];
466 return 1;
469 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
470 break;
471 case WS_IPPROTO_TCP:
472 *level = IPPROTO_TCP;
473 for(i=0; ws_tcp_map[i][0]; i++)
475 if ( ws_tcp_map[i][0] == *optname )
477 *optname = ws_tcp_map[i][1];
478 return 1;
481 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
482 break;
483 case WS_IPPROTO_IP:
484 *level = IPPROTO_IP;
485 for(i=0; ws_ip_map[i][0]; i++)
487 if (ws_ip_map[i][0] == *optname )
489 *optname = ws_ip_map[i][1];
490 return 1;
493 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
494 break;
495 default: FIXME("Unimplemented or unknown socket level\n");
497 return 0;
500 static inline BOOL is_timeout_option( int optname )
502 #ifdef SO_RCVTIMEO
503 if (optname == SO_RCVTIMEO) return TRUE;
504 #endif
505 #ifdef SO_SNDTIMEO
506 if (optname == SO_SNDTIMEO) return TRUE;
507 #endif
508 return FALSE;
511 /* ----------------------------------- Per-thread info (or per-process?) */
513 static char *strdup_lower(const char *str)
515 int i;
516 char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
518 if (ret)
520 for (i = 0; str[i]; i++) ret[i] = tolower(str[i]);
521 ret[i] = 0;
523 else SetLastError(WSAENOBUFS);
524 return ret;
527 static fd_set* fd_set_import( fd_set* fds, const WS_fd_set* wsfds, int access, int* highfd, int lfd[] )
529 /* translate Winsock fd set into local fd set */
530 if( wsfds )
532 unsigned int i;
534 FD_ZERO(fds);
535 for( i = 0; i < wsfds->fd_count; i++ )
537 int s = wsfds->fd_array[i];
538 int fd = get_sock_fd( s, access, NULL );
539 if (fd != -1)
541 lfd[ i ] = fd;
542 if( fd > *highfd ) *highfd = fd;
543 FD_SET(fd, fds);
545 else lfd[ i ] = -1;
547 return fds;
549 return NULL;
552 inline static int sock_error_p(int s)
554 unsigned int optval, optlen;
556 optlen = sizeof(optval);
557 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
558 if (optval) WARN("\t[%i] error: %d\n", s, optval);
559 return optval != 0;
562 static int fd_set_export( const fd_set* fds, fd_set* exceptfds, WS_fd_set* wsfds, int lfd[] )
564 int num_err = 0;
566 /* translate local fd set into Winsock fd set, adding
567 * errors to exceptfds (only if app requested it) */
569 if( wsfds )
571 int i, j, count = wsfds->fd_count;
573 for( i = 0, j = 0; i < count; i++ )
575 int fd = lfd[i];
576 SOCKET s = wsfds->fd_array[i];
577 if (fd == -1) continue;
578 if( FD_ISSET(fd, fds) )
580 if ( exceptfds && sock_error_p(fd) )
582 FD_SET(fd, exceptfds);
583 num_err++;
585 else wsfds->fd_array[j++] = s;
587 release_sock_fd( s, fd );
589 wsfds->fd_count = j;
591 return num_err;
594 static void fd_set_unimport( WS_fd_set* wsfds, int lfd[] )
596 if ( wsfds )
598 unsigned int i;
600 for ( i = 0; i < wsfds->fd_count; i++ )
601 if ( lfd[i] >= 0 ) release_sock_fd( wsfds->fd_array[i], lfd[i] );
602 wsfds->fd_count = 0;
606 /* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option
607 * from an fd and return the value converted to milli seconds
608 * or -1 if there is an infinite time out */
609 static inline int get_rcvsnd_timeo( int fd, int optname)
611 struct timeval tv;
612 int len = sizeof(tv);
613 int ret = getsockopt(fd, SOL_SOCKET, optname, &tv, &len);
614 if( ret >= 0)
615 ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
616 if( ret <= 0 ) /* tv == {0,0} means infinite time out */
617 return -1;
618 return ret;
621 /* macro wrappers for portability */
622 #ifdef SO_RCVTIMEO
623 #define GET_RCVTIMEO(fd) get_rcvsnd_timeo( (fd), SO_RCVTIMEO)
624 #else
625 #define GET_RCVTIMEO(fd) (-1)
626 #endif
628 #ifdef SO_SNDTIMEO
629 #define GET_SNDTIMEO(fd) get_rcvsnd_timeo( (fd), SO_SNDTIMEO)
630 #else
631 #define GET_SNDTIMEO(fd) (-1)
632 #endif
634 /* utility: given an fd, will block until one of the events occurs */
635 static inline int do_block( int fd, int events, int timeout )
637 struct pollfd pfd;
638 int ret;
640 pfd.fd = fd;
641 pfd.events = events;
643 while ((ret = poll(&pfd, 1, timeout)) < 0)
645 if (errno != EINTR)
646 return -1;
648 if( ret == 0 )
649 return 0;
650 return pfd.revents;
654 /* ----------------------------------- API -----
656 * Init / cleanup / error checking.
659 /***********************************************************************
660 * WSAStartup (WS2_32.115)
662 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
664 TRACE("verReq=%x\n", wVersionRequested);
666 if (LOBYTE(wVersionRequested) < 1)
667 return WSAVERNOTSUPPORTED;
669 if (!lpWSAData) return WSAEINVAL;
671 num_startup++;
673 /* that's the whole of the negotiation for now */
674 lpWSAData->wVersion = wVersionRequested;
675 /* return winsock information */
676 lpWSAData->wHighVersion = 0x0202;
677 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
678 strcpy(lpWSAData->szSystemStatus, "Running" );
679 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
680 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
681 /* don't do anything with lpWSAData->lpVendorInfo */
682 /* (some apps don't allocate the space for this field) */
684 TRACE("succeeded\n");
685 return 0;
689 /***********************************************************************
690 * WSACleanup (WS2_32.116)
692 INT WINAPI WSACleanup(void)
694 if (num_startup)
695 return 0;
696 SetLastError(WSANOTINITIALISED);
697 return SOCKET_ERROR;
701 /***********************************************************************
702 * WSAGetLastError (WINSOCK.111)
703 * WSAGetLastError (WS2_32.111)
705 INT WINAPI WSAGetLastError(void)
707 return GetLastError();
710 /***********************************************************************
711 * WSASetLastError (WS2_32.112)
713 void WINAPI WSASetLastError(INT iError) {
714 SetLastError(iError);
717 static struct WS_hostent *check_buffer_he(int size)
719 struct per_thread_data * ptb = get_per_thread_data();
720 if (ptb->he_buffer)
722 if (ptb->he_len >= size ) return ptb->he_buffer;
723 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
725 ptb->he_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->he_len = size) );
726 if (!ptb->he_buffer) SetLastError(WSAENOBUFS);
727 return ptb->he_buffer;
730 static struct WS_servent *check_buffer_se(int size)
732 struct per_thread_data * ptb = get_per_thread_data();
733 if (ptb->se_buffer)
735 if (ptb->se_len >= size ) return ptb->se_buffer;
736 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
738 ptb->se_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->se_len = size) );
739 if (!ptb->se_buffer) SetLastError(WSAENOBUFS);
740 return ptb->se_buffer;
743 static struct WS_protoent *check_buffer_pe(int size)
745 struct per_thread_data * ptb = get_per_thread_data();
746 if (ptb->pe_buffer)
748 if (ptb->pe_len >= size ) return ptb->pe_buffer;
749 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
751 ptb->pe_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->pe_len = size) );
752 if (!ptb->pe_buffer) SetLastError(WSAENOBUFS);
753 return ptb->pe_buffer;
756 /* ----------------------------------- i/o APIs */
758 #ifdef HAVE_IPX
759 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
760 #else
761 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
762 #endif
765 /**********************************************************************/
767 /* Returns the converted address if successful, NULL if it was too small to
768 * start with. Note that the returned pointer may be the original pointer
769 * if no conversion is necessary.
771 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
773 switch (wsaddr->sa_family)
775 #ifdef HAVE_IPX
776 case WS_AF_IPX:
778 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
779 struct sockaddr_ipx* uipx;
781 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
782 return NULL;
784 *uaddrlen=sizeof(struct sockaddr_ipx);
785 uipx=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
786 uipx->sipx_family=AF_IPX;
787 uipx->sipx_port=wsipx->sa_socket;
788 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
789 * in one go
791 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
792 #ifdef IPX_FRAME_NONE
793 uipx->sipx_type=IPX_FRAME_NONE;
794 #endif
795 return (const struct sockaddr*)uipx;
797 #endif
799 default:
800 if (wsaddrlen<sizeof(struct WS_sockaddr))
801 return NULL;
803 /* No conversion needed, just return the original address */
804 *uaddrlen=wsaddrlen;
805 return (const struct sockaddr*)wsaddr;
809 /* Allocates a Unix sockaddr structure to receive the data */
810 inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
812 if (wsaddr==NULL)
814 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
816 /* This is not strictly the right thing to do. Hope it works however */
817 *uaddrlen=0;
819 return NULL;
822 if (*wsaddrlen==0)
823 *uaddrlen=0;
824 else
825 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
827 return HeapAlloc(GetProcessHeap(), 0, *uaddrlen);
830 /* Returns 0 if successful, -1 if the buffer is too small */
831 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
833 int res;
835 switch(uaddr->sa_family)
837 #ifdef HAVE_IPX
838 case AF_IPX:
840 struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
841 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
843 res=-1;
844 switch (*wsaddrlen) /* how much can we copy? */
846 default:
847 res=0; /* enough */
848 *wsaddrlen=uaddrlen;
849 wsipx->sa_socket=uipx->sipx_port;
850 /* fall through */
851 case 13:
852 case 12:
853 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
854 /* fall through */
855 case 11:
856 case 10:
857 case 9:
858 case 8:
859 case 7:
860 case 6:
861 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
862 /* fall through */
863 case 5:
864 case 4:
865 case 3:
866 case 2:
867 wsipx->sa_family=WS_AF_IPX;
868 /* fall through */
869 case 1:
870 case 0:
871 /* way too small */
872 break;
875 break;
876 #endif
878 default:
879 /* No conversion needed */
880 memcpy(wsaddr,uaddr,*wsaddrlen);
881 if (*wsaddrlen<uaddrlen) {
882 res=-1;
883 } else {
884 *wsaddrlen=uaddrlen;
885 res=0;
888 return res;
891 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
892 * ws_sockaddr_alloc
894 inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
896 if (uaddr!=(const struct sockaddr*)wsaddr)
897 HeapFree(GetProcessHeap(), 0, (void *)uaddr);
900 /**************************************************************************
901 * Functions for handling overlapped I/O
902 **************************************************************************/
904 static void CALLBACK ws2_async_terminate(ws2_async* as, IO_STATUS_BLOCK* iosb)
906 TRACE( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, iosb );
908 wine_server_release_fd( as->hSocket, as->fd );
909 if ( as->event != INVALID_HANDLE_VALUE )
910 NtSetEvent( as->event, NULL );
912 if (as->completion_func)
913 as->completion_func( NtStatusToWSAError (iosb->u.Status),
914 iosb->Information, as->user_overlapped, as->flags );
915 if ( !as->user_overlapped )
917 #if 0
918 /* FIXME: I don't think this is really used */
919 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
920 WSACloseEvent( as->overlapped->hEvent );
921 #endif
922 HeapFree( GetProcessHeap(), 0, iosb );
925 HeapFree( GetProcessHeap(), 0, as->iovec );
926 HeapFree( GetProcessHeap(), 0, as );
929 /***********************************************************************
930 * WS2_make_async (INTERNAL)
933 static void WINAPI WS2_async_recv(void*, IO_STATUS_BLOCK*, ULONG);
934 static void WINAPI WS2_async_send(void*, IO_STATUS_BLOCK*, ULONG);
935 static void WINAPI WS2_async_shutdown( void*, IO_STATUS_BLOCK*, ULONG);
937 inline static struct ws2_async*
938 WS2_make_async(SOCKET s, int fd, enum ws2_mode mode, struct iovec *iovec, DWORD dwBufferCount,
939 LPDWORD lpFlags, struct WS_sockaddr *addr,
940 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
941 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
942 IO_STATUS_BLOCK **piosb)
944 struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof( ws2_async ) );
946 TRACE( "wsa %p\n", wsa );
948 if (!wsa)
949 return NULL;
951 wsa->hSocket = (HANDLE) s;
952 wsa->mode = mode;
953 switch (mode)
955 case ws2m_read:
956 case ws2m_sd_read:
957 wsa->flags = *lpFlags;
958 wsa->addrlen.ptr = addrlen;
959 break;
960 case ws2m_write:
961 case ws2m_sd_write:
962 wsa->flags = 0;
963 wsa->addrlen.val = *addrlen;
964 break;
965 default:
966 ERR("Invalid async mode: %d\n", mode);
968 wsa->user_overlapped = lpOverlapped;
969 wsa->completion_func = lpCompletionRoutine;
970 wsa->iovec = iovec;
971 wsa->n_iovecs = dwBufferCount;
972 wsa->addr = addr;
973 wsa->fd = fd;
974 wsa->event = INVALID_HANDLE_VALUE;
976 if ( lpOverlapped )
978 *piosb = (IO_STATUS_BLOCK*)lpOverlapped;
979 if (!lpCompletionRoutine)
981 wsa->event = lpOverlapped->hEvent;
982 NtResetEvent(wsa->event, NULL);
985 else if (!(*piosb = HeapAlloc( GetProcessHeap(), 0, sizeof(IO_STATUS_BLOCK))))
986 goto error;
988 (*piosb)->Information = 0;
989 (*piosb)->u.Status = STATUS_PENDING;
990 TRACE( "wsa %p, h %p, ev %p, fd %d, iosb %p, uov %p, cfunc %p\n",
991 wsa, wsa->hSocket, wsa->event, wsa->fd,
992 *piosb, wsa->user_overlapped, wsa->completion_func );
994 return wsa;
996 error:
997 TRACE("Error\n");
998 HeapFree( GetProcessHeap(), 0, wsa );
999 return NULL;
1002 static ULONG ws2_queue_async(struct ws2_async* wsa, IO_STATUS_BLOCK* iosb)
1004 PIO_APC_ROUTINE apc;
1005 int type;
1006 NTSTATUS status;
1008 switch (wsa->mode)
1010 case ws2m_read: apc = WS2_async_recv; type = ASYNC_TYPE_READ; break;
1011 case ws2m_write: apc = WS2_async_send; type = ASYNC_TYPE_WRITE; break;
1012 case ws2m_sd_read: apc = WS2_async_shutdown; type = ASYNC_TYPE_READ; break;
1013 case ws2m_sd_write: apc = WS2_async_shutdown; type = ASYNC_TYPE_WRITE; break;
1014 default: FIXME("Unknown internal mode (%d)\n", wsa->mode); return STATUS_INVALID_PARAMETER;
1017 SERVER_START_REQ( register_async )
1019 req->handle = wsa->hSocket;
1020 req->io_apc = apc;
1021 req->io_sb = iosb;
1022 req->io_user = wsa;
1023 req->type = type;
1024 req->count = iosb->Information;
1025 status = wine_server_call( req );
1027 SERVER_END_REQ;
1029 if ( status ) iosb->u.Status = status;
1030 if ( iosb->u.Status != STATUS_PENDING )
1032 (apc)( wsa, iosb, iosb->u.Status );
1033 return iosb->u.Status;
1035 NtCurrentTeb()->num_async_io++;
1036 return STATUS_SUCCESS;
1039 /***********************************************************************
1040 * WS2_recv (INTERNAL)
1042 * Workhorse for both synchronous and asynchronous recv() operations.
1044 static int WS2_recv( int fd, struct iovec* iov, int count,
1045 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1046 LPDWORD lpFlags )
1048 struct msghdr hdr;
1049 int n;
1050 TRACE( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
1051 fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
1053 hdr.msg_name = NULL;
1055 if ( lpFrom )
1057 hdr.msg_namelen = *lpFromlen;
1058 hdr.msg_name = ws_sockaddr_alloc( lpFrom, lpFromlen, &hdr.msg_namelen );
1059 if ( !hdr.msg_name )
1061 WSASetLastError( WSAEFAULT );
1062 n = -1;
1063 goto out;
1066 else
1067 hdr.msg_namelen = 0;
1069 hdr.msg_iov = iov;
1070 hdr.msg_iovlen = count;
1071 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1072 hdr.msg_accrights = NULL;
1073 hdr.msg_accrightslen = 0;
1074 #else
1075 hdr.msg_control = NULL;
1076 hdr.msg_controllen = 0;
1077 hdr.msg_flags = 0;
1078 #endif
1080 if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 )
1082 TRACE( "recvmsg error %d\n", errno);
1083 goto out;
1086 if ( lpFrom &&
1087 ws_sockaddr_u2ws( hdr.msg_name, hdr.msg_namelen,
1088 lpFrom, lpFromlen ) != 0 )
1090 /* The from buffer was too small, but we read the data
1091 * anyway. Is that really bad?
1093 WSASetLastError( WSAEFAULT );
1094 WARN( "Address buffer too small\n" );
1097 out:
1099 ws_sockaddr_free( hdr.msg_name, lpFrom );
1100 TRACE("-> %d\n", n);
1101 return n;
1104 /***********************************************************************
1105 * WS2_async_recv (INTERNAL)
1107 * Handler for overlapped recv() operations.
1109 static void WINAPI WS2_async_recv( void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
1111 ws2_async* wsa = (ws2_async*) ovp;
1112 int result, err;
1114 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1116 switch (status)
1118 case STATUS_ALERTED:
1119 result = WS2_recv( wsa->fd, wsa->iovec, wsa->n_iovecs,
1120 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1121 if (result >= 0)
1123 iosb->u.Status = STATUS_SUCCESS;
1124 iosb->Information = result;
1125 TRACE( "received %d bytes\n", result );
1126 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1128 else
1130 err = wsaErrno();
1131 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1133 iosb->u.Status = STATUS_PENDING;
1134 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1135 TRACE( "still pending\n" );
1137 else
1139 iosb->u.Status = err; /* FIXME: is this correct ???? */
1140 TRACE( "Error: %x\n", err );
1143 if (iosb->u.Status == STATUS_PENDING)
1144 ws2_queue_async(wsa, iosb);
1145 else
1146 ws2_async_terminate(wsa, iosb);
1147 break;
1148 default:
1149 FIXME( "status: %ld\n", status );
1150 iosb->u.Status = status;
1151 ws2_async_terminate(wsa, iosb);
1152 return;
1156 /***********************************************************************
1157 * WS2_send (INTERNAL)
1159 * Workhorse for both synchronous and asynchronous send() operations.
1161 static int WS2_send( int fd, struct iovec* iov, int count,
1162 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1164 struct msghdr hdr;
1165 int n = -1;
1166 TRACE( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
1167 fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
1169 hdr.msg_name = NULL;
1171 if ( to )
1173 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u( to, tolen, &hdr.msg_namelen );
1174 if ( !hdr.msg_name )
1176 WSASetLastError( WSAEFAULT );
1177 goto out;
1180 #ifdef HAVE_IPX
1181 if(to->sa_family == WS_AF_IPX)
1183 #ifdef SOL_IPX
1184 struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
1185 int val=0;
1186 int len=sizeof(int);
1188 /* The packet type is stored at the ipx socket level; At least the linux kernel seems
1189 * to do something with it in case hdr.msg_name is NULL. Nonetheless can we use it to store
1190 * the packet type and then we can retrieve it using getsockopt. After that we can set the
1191 * ipx type in the sockaddr_opx structure with the stored value.
1193 if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1)
1195 TRACE("ptype: %d (fd:%d)\n", val, fd);
1196 uipx->sipx_type = val;
1198 #endif
1200 #endif
1203 else
1204 hdr.msg_namelen = 0;
1206 hdr.msg_iov = iov;
1207 hdr.msg_iovlen = count;
1208 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1209 hdr.msg_accrights = NULL;
1210 hdr.msg_accrightslen = 0;
1211 #else
1212 hdr.msg_control = NULL;
1213 hdr.msg_controllen = 0;
1214 hdr.msg_flags = 0;
1215 #endif
1217 n = sendmsg(fd, &hdr, dwFlags);
1219 out:
1220 ws_sockaddr_free( hdr.msg_name, to );
1221 return n;
1224 /***********************************************************************
1225 * WS2_async_send (INTERNAL)
1227 * Handler for overlapped send() operations.
1229 static void WINAPI WS2_async_send(void* as, IO_STATUS_BLOCK* iosb, ULONG status)
1231 ws2_async* wsa = (ws2_async*) as;
1232 int result;
1234 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1236 switch (status)
1238 case STATUS_ALERTED:
1239 if (iosb->u.Status != STATUS_PENDING) FIXME("wrong %08lx\n", iosb->u.Status);
1240 /* check to see if the data is ready (non-blocking) */
1241 result = WS2_send( wsa->fd, wsa->iovec, wsa->n_iovecs,
1242 wsa->addr, wsa->addrlen.val, wsa->flags );
1244 if (result >= 0)
1246 iosb->u.Status = STATUS_SUCCESS;
1247 iosb->Information = result;
1248 TRACE( "sent %d bytes\n", result );
1249 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1251 else
1253 int err = wsaErrno();
1254 if ( err == WSAEINTR )
1256 iosb->u.Status = STATUS_PENDING;
1257 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1258 TRACE( "still pending\n" );
1260 else
1262 /* We set the status to a winsock error code and check for that
1263 later in NtStatusToWSAError () */
1264 iosb->u.Status = err;
1265 TRACE( "Error: %x\n", err );
1268 if (iosb->u.Status == STATUS_PENDING)
1269 ws2_queue_async(wsa, iosb);
1270 else
1271 ws2_async_terminate(wsa, iosb);
1272 break;
1273 default:
1274 FIXME( "status: %ld\n", status );
1275 iosb->u.Status = status;
1276 ws2_async_terminate(wsa, iosb);
1277 return;
1282 /***********************************************************************
1283 * WS2_async_shutdown (INTERNAL)
1285 * Handler for shutdown() operations on overlapped sockets.
1287 static void WINAPI WS2_async_shutdown( void* as, PIO_STATUS_BLOCK iosb, ULONG status )
1289 ws2_async* wsa = (ws2_async*) as;
1290 int err = 1;
1292 TRACE( "async %p %d\n", wsa, wsa->mode );
1293 switch (status)
1295 case STATUS_ALERTED:
1296 switch ( wsa->mode )
1298 case ws2m_sd_read: err = shutdown( wsa->fd, 0 ); break;
1299 case ws2m_sd_write: err = shutdown( wsa->fd, 1 ); break;
1300 default: ERR("invalid mode: %d\n", wsa->mode );
1302 iosb->u.Status = err ? wsaErrno() : STATUS_SUCCESS;
1303 if (iosb->u.Status == STATUS_PENDING)
1304 ws2_queue_async(wsa, iosb);
1305 else
1306 ws2_async_terminate(wsa, iosb);
1307 break;
1308 default:
1309 iosb->u.Status = status;
1310 ws2_async_terminate(wsa, iosb);
1311 break;
1316 /***********************************************************************
1317 * WS2_register_async_shutdown (INTERNAL)
1319 * Helper function for WS_shutdown() on overlapped sockets.
1321 static int WS2_register_async_shutdown( SOCKET s, int fd, enum ws2_mode mode )
1323 struct ws2_async *wsa;
1324 int ret, err = WSAEFAULT;
1325 DWORD dwflags = 0;
1326 int len = 0;
1327 LPWSAOVERLAPPED ovl = HeapAlloc(GetProcessHeap(), 0, sizeof( WSAOVERLAPPED ));
1328 IO_STATUS_BLOCK *iosb;
1330 TRACE("s %d fd %d mode %d\n", s, fd, mode);
1331 if (!ovl)
1332 goto out;
1334 ovl->hEvent = WSACreateEvent();
1335 if ( ovl->hEvent == WSA_INVALID_EVENT )
1336 goto out_free;
1338 wsa = WS2_make_async( s, fd, mode, NULL, 0,
1339 &dwflags, NULL, &len, ovl, NULL, &iosb );
1340 if ( !wsa )
1341 goto out_close;
1343 /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
1344 wsa->user_overlapped = NULL;
1345 if ( (ret = ws2_queue_async( wsa, iosb )) )
1347 err = NtStatusToWSAError( ret );
1348 goto out;
1350 /* Try immediate completion */
1351 while ( WaitForSingleObjectEx( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1352 return 0;
1354 out_close:
1355 WSACloseEvent( ovl->hEvent );
1356 out_free:
1357 HeapFree( GetProcessHeap(), 0, iosb );
1358 HeapFree( GetProcessHeap(), 0, ovl );
1359 out:
1360 return err;
1363 /***********************************************************************
1364 * accept (WS2_32.1)
1366 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1367 int *addrlen32)
1369 SOCKET as;
1371 TRACE("socket %04x\n", s );
1372 if (_is_blocking(s))
1374 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1375 if (fd == -1) return INVALID_SOCKET;
1376 /* block here */
1377 do_block(fd, POLLIN, -1);
1378 _sync_sock_state(s); /* let wineserver notice connection */
1379 release_sock_fd( s, fd );
1380 /* retrieve any error codes from it */
1381 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1382 /* FIXME: care about the error? */
1384 SERVER_START_REQ( accept_socket )
1386 req->lhandle = SOCKET2HANDLE(s);
1387 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1388 req->inherit = TRUE;
1389 set_error( wine_server_call( req ) );
1390 as = HANDLE2SOCKET( reply->handle );
1392 SERVER_END_REQ;
1393 if (as)
1395 if (addr) WS_getpeername(as, addr, addrlen32);
1396 return as;
1398 return INVALID_SOCKET;
1401 /***********************************************************************
1402 * bind (WS2_32.2)
1404 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1406 int fd = get_sock_fd( s, 0, NULL );
1407 int res = SOCKET_ERROR;
1409 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1411 if (fd != -1)
1413 if (!name || !SUPPORTED_PF(name->sa_family))
1415 SetLastError(WSAEAFNOSUPPORT);
1417 else
1419 const struct sockaddr* uaddr;
1420 int uaddrlen;
1422 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1423 if (uaddr == NULL)
1425 SetLastError(WSAEFAULT);
1427 else
1429 if (bind(fd, uaddr, uaddrlen) < 0)
1431 int loc_errno = errno;
1432 WARN("\tfailure - errno = %i\n", errno);
1433 errno = loc_errno;
1434 switch (errno)
1436 case EBADF:
1437 SetLastError(WSAENOTSOCK);
1438 break;
1439 case EADDRNOTAVAIL:
1440 SetLastError(WSAEINVAL);
1441 break;
1442 default:
1443 SetLastError(wsaErrno());
1444 break;
1447 else
1449 res=0; /* success */
1451 ws_sockaddr_free(uaddr,name);
1454 release_sock_fd( s, fd );
1456 return res;
1459 /***********************************************************************
1460 * closesocket (WS2_32.3)
1462 int WINAPI WS_closesocket(SOCKET s)
1464 TRACE("socket %04x\n", s);
1465 if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1466 return SOCKET_ERROR;
1469 /***********************************************************************
1470 * connect (WS2_32.4)
1472 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1474 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1476 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1478 if (fd != -1)
1480 const struct sockaddr* uaddr;
1481 int uaddrlen;
1483 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1484 if (uaddr == NULL)
1486 SetLastError(WSAEFAULT);
1488 else
1490 int rc;
1492 rc=connect(fd, uaddr, uaddrlen);
1493 ws_sockaddr_free(uaddr,name);
1494 if (rc == 0)
1495 goto connect_success;
1498 if (errno == EINPROGRESS)
1500 /* tell wineserver that a connection is in progress */
1501 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1502 FD_CONNECT|FD_READ|FD_WRITE,
1503 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1504 if (_is_blocking(s))
1506 int result;
1507 /* block here */
1508 do_block(fd, POLLIN | POLLOUT, -1);
1509 _sync_sock_state(s); /* let wineserver notice connection */
1510 /* retrieve any error codes from it */
1511 result = _get_sock_error(s, FD_CONNECT_BIT);
1512 if (result)
1513 SetLastError(result);
1514 else
1516 goto connect_success;
1519 else
1521 SetLastError(WSAEWOULDBLOCK);
1524 else
1526 SetLastError(wsaErrno());
1528 release_sock_fd( s, fd );
1530 return SOCKET_ERROR;
1532 connect_success:
1533 release_sock_fd( s, fd );
1534 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1535 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1536 FD_CONNECT|FD_WINE_LISTENING);
1537 return 0;
1540 /***********************************************************************
1541 * WSAConnect (WS2_32.30)
1543 int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
1544 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1545 LPQOS lpSQOS, LPQOS lpGQOS )
1547 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1548 FIXME("unsupported parameters!\n");
1549 return WS_connect( s, name, namelen );
1553 /***********************************************************************
1554 * getpeername (WS2_32.5)
1556 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1558 int fd;
1559 int res;
1561 TRACE("socket: %04x, ptr %p, len %08x\n", s, name, *namelen);
1563 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1564 if( (name == NULL) || (namelen == NULL) )
1566 SetLastError( WSAEFAULT );
1567 return SOCKET_ERROR;
1570 fd = get_sock_fd( s, 0, NULL );
1571 res = SOCKET_ERROR;
1573 if (fd != -1)
1575 struct sockaddr* uaddr;
1576 int uaddrlen;
1578 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1579 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1581 SetLastError(wsaErrno());
1583 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1585 /* The buffer was too small */
1586 SetLastError(WSAEFAULT);
1588 else
1590 res=0;
1592 ws_sockaddr_free(uaddr,name);
1593 release_sock_fd( s, fd );
1595 return res;
1598 /***********************************************************************
1599 * getsockname (WS2_32.6)
1601 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1603 int fd;
1604 int res;
1606 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1608 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1609 if( (name == NULL) || (namelen == NULL) )
1611 SetLastError( WSAEFAULT );
1612 return SOCKET_ERROR;
1615 fd = get_sock_fd( s, 0, NULL );
1616 res = SOCKET_ERROR;
1618 if (fd != -1)
1620 struct sockaddr* uaddr;
1621 int uaddrlen;
1623 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1624 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1626 SetLastError(wsaErrno());
1628 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1630 /* The buffer was too small */
1631 SetLastError(WSAEFAULT);
1633 else
1635 res=0;
1637 ws_sockaddr_free(uaddr,name);
1638 release_sock_fd( s, fd );
1640 return res;
1643 /***********************************************************************
1644 * getsockopt (WS2_32.7)
1646 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1647 INT optname, char *optval, INT *optlen)
1649 int fd;
1650 INT ret = 0;
1652 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1653 (int) optname, (int) optval, (int) *optlen);
1654 /* SO_OPENTYPE does not require a valid socket handle. */
1655 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1657 if (!optlen || *optlen < sizeof(int) || !optval)
1659 SetLastError(WSAEFAULT);
1660 return SOCKET_ERROR;
1662 *(int *)optval = get_per_thread_data()->opentype;
1663 *optlen = sizeof(int);
1664 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1665 return 0;
1668 #ifdef HAVE_IPX
1669 if(level == NSPROTO_IPX)
1671 struct WS_sockaddr_ipx addr;
1672 IPX_ADDRESS_DATA *data;
1673 int namelen;
1674 switch(optname)
1676 case IPX_PTYPE:
1677 fd = get_sock_fd( s, 0, NULL );
1678 #ifdef SOL_IPX
1679 if(getsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
1681 return SOCKET_ERROR;
1683 #else
1685 struct ipx val;
1686 socklen_t len=sizeof(struct ipx);
1688 if(getsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, &len) == -1 )
1689 return SOCKET_ERROR;
1690 *optval = (int)val.ipx_pt;
1692 #endif
1693 TRACE("ptype: %d (fd: %d)\n", *(int*)optval, fd);
1694 release_sock_fd( s, fd );
1696 return 0;
1697 case IPX_ADDRESS:
1699 * On a Win2000 system with one network card there are usually three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
1700 * Using this call you can then retrieve info about this all. In case of Linux it is a bit different. Usually you have
1701 * only "one" device active and further it is not possible to query things like the linkspeed.
1703 FIXME("IPX_ADDRESS\n");
1704 namelen = sizeof(struct WS_sockaddr);
1705 memset(&addr, 0, sizeof(struct WS_sockaddr));
1706 WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
1708 data = (IPX_ADDRESS_DATA*)optval;
1709 memcpy(data->nodenum,&addr.sa_nodenum,sizeof(data->nodenum));
1710 memcpy(data->netnum,&addr.sa_netnum,sizeof(data->netnum));
1711 data->adapternum = 0;
1712 data->wan = FALSE; /* We are not on a wan for now .. */
1713 data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
1714 data->maxpkt = 1467; /* This value is the default one, at least on Win2k/WinXP */
1715 data->linkspeed = 100000; /* Set the line speed in 100bit/s to 10 Mbit; note 1MB = 1000kB in this case */
1716 return 0;
1717 case IPX_MAX_ADAPTER_NUM:
1718 FIXME("IPX_MAX_ADAPTER_NUM\n");
1719 *(int*)optval = 1; /* As noted under IPX_ADDRESS we have just one card. */
1721 return 0;
1722 default:
1723 FIXME("IPX optname:%x\n", optname);
1724 return SOCKET_ERROR;
1727 #endif
1729 if( (fd = get_sock_fd( s, 0, NULL )) == -1)
1730 return SOCKET_ERROR;
1732 if (!convert_sockopt(&level, &optname)) {
1733 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1734 ret = SOCKET_ERROR;
1735 } else {
1736 struct timeval tv;
1737 struct linger lingval;
1738 INT len, *plen = optlen;
1739 char *pval = optval;
1740 if(level == SOL_SOCKET && is_timeout_option(optname)) {
1741 len = sizeof(tv);
1742 plen = &len;
1743 pval = (char *) &tv;
1744 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1745 len = sizeof(lingval);
1746 plen = &len;
1747 pval = (char *) &lingval;
1749 if (getsockopt(fd, (int) level, optname, pval, plen) != 0 ) {
1750 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1751 ret = SOCKET_ERROR;
1752 } else if(level == SOL_SOCKET && is_timeout_option(optname)) {
1753 if( *optlen >= sizeof(INT) ) {
1754 *optlen = sizeof(INT);
1755 *(INT*)optval = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1756 } else {
1757 SetLastError(WSAEFAULT);
1758 ret = SOCKET_ERROR;
1760 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1761 if( *optlen >= sizeof( LINGER) ) {
1762 (( LINGER *) optval)->l_onoff = lingval.l_onoff;
1763 (( LINGER *) optval)->l_linger = lingval.l_linger;
1764 } else {
1765 SetLastError(WSAEFAULT);
1766 ret = SOCKET_ERROR;
1770 release_sock_fd( s, fd );
1771 return ret;
1775 /***********************************************************************
1776 * htonl (WINSOCK.8)
1777 * htonl (WS2_32.8)
1779 u_long WINAPI WS_htonl(u_long hostlong)
1781 return htonl(hostlong);
1785 /***********************************************************************
1786 * htons (WINSOCK.9)
1787 * htons (WS2_32.9)
1789 u_short WINAPI WS_htons(u_short hostshort)
1791 return htons(hostshort);
1794 /***********************************************************************
1795 * WSAHtonl (WS2_32.46)
1796 * From MSDN decription of error codes, this function should also
1797 * check if WinSock has been initialized and the socket is a valid
1798 * socket. But why? This function only translates a host byte order
1799 * u_long into a network byte order u_long...
1801 int WINAPI WSAHtonl(SOCKET s, u_long hostlong, u_long *lpnetlong)
1803 if (lpnetlong)
1805 *lpnetlong = htonl(hostlong);
1806 return 0;
1808 WSASetLastError(WSAEFAULT);
1809 return SOCKET_ERROR;
1812 /***********************************************************************
1813 * WSAHtons (WS2_32.47)
1814 * From MSDN decription of error codes, this function should also
1815 * check if WinSock has been initialized and the socket is a valid
1816 * socket. But why? This function only translates a host byte order
1817 * u_short into a network byte order u_short...
1819 int WINAPI WSAHtons(SOCKET s, u_short hostshort, u_short *lpnetshort)
1822 if (lpnetshort)
1824 *lpnetshort = htons(hostshort);
1825 return 0;
1827 WSASetLastError(WSAEFAULT);
1828 return SOCKET_ERROR;
1832 /***********************************************************************
1833 * inet_addr (WINSOCK.10)
1834 * inet_addr (WS2_32.11)
1836 u_long WINAPI WS_inet_addr(const char *cp)
1838 return inet_addr(cp);
1842 /***********************************************************************
1843 * ntohl (WINSOCK.14)
1844 * ntohl (WS2_32.14)
1846 u_long WINAPI WS_ntohl(u_long netlong)
1848 return ntohl(netlong);
1852 /***********************************************************************
1853 * ntohs (WINSOCK.15)
1854 * ntohs (WS2_32.15)
1856 u_short WINAPI WS_ntohs(u_short netshort)
1858 return ntohs(netshort);
1862 /***********************************************************************
1863 * inet_ntoa (WS2_32.12)
1865 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1867 /* use "buffer for dummies" here because some applications have a
1868 * propensity to decode addresses in ws_hostent structure without
1869 * saving them first...
1871 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1873 char* s = inet_ntoa(*((struct in_addr*)&in));
1874 if( s )
1876 strcpy(dbuffer, s);
1877 return dbuffer;
1879 SetLastError(wsaErrno());
1880 return NULL;
1883 /**********************************************************************
1884 * WSAIoctl (WS2_32.50)
1887 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1889 INT WINAPI WSAIoctl(SOCKET s,
1890 DWORD dwIoControlCode,
1891 LPVOID lpvInBuffer,
1892 DWORD cbInBuffer,
1893 LPVOID lpbOutBuffer,
1894 DWORD cbOutBuffer,
1895 LPDWORD lpcbBytesReturned,
1896 LPWSAOVERLAPPED lpOverlapped,
1897 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1899 int fd = get_sock_fd( s, 0, NULL );
1901 if (fd == -1) return SOCKET_ERROR;
1903 TRACE("%d, 0x%08lx, %p, %ld, %p, %ld, %p, %p, %p\n",
1904 s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpbOutBuffer,
1905 cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
1907 switch( dwIoControlCode )
1909 case SIO_GET_INTERFACE_LIST:
1911 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1912 DWORD size, numInt, apiReturn;
1914 TRACE("-> SIO_GET_INTERFACE_LIST request\n");
1916 if (!lpbOutBuffer)
1918 release_sock_fd( s, fd );
1919 WSASetLastError(WSAEFAULT);
1920 return SOCKET_ERROR;
1922 if (!lpcbBytesReturned)
1924 release_sock_fd( s, fd );
1925 WSASetLastError(WSAEFAULT);
1926 return SOCKET_ERROR;
1929 apiReturn = GetAdaptersInfo(NULL, &size);
1930 if (apiReturn == ERROR_NO_DATA)
1932 numInt = 0;
1934 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
1936 PIP_ADAPTER_INFO table = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(),0,size);
1938 if (table)
1940 if (GetAdaptersInfo(table, &size) == NO_ERROR)
1942 PIP_ADAPTER_INFO ptr;
1944 if (size*sizeof(INTERFACE_INFO)/sizeof(IP_ADAPTER_INFO) > cbOutBuffer)
1946 WARN("Buffer too small = %lu, cbOutBuffer = %lu\n", size, cbOutBuffer);
1947 HeapFree(GetProcessHeap(),0,table);
1948 release_sock_fd( s, fd );
1949 WSASetLastError(WSAEFAULT);
1950 return SOCKET_ERROR;
1952 for (ptr = table, numInt = 0; ptr;
1953 ptr = ptr->Next, intArray++, numInt++)
1955 unsigned int addr, mask, bcast;
1956 struct ifreq ifInfo;
1958 /* Socket Status Flags */
1959 strncpy(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
1960 ifInfo.ifr_name[IFNAMSIZ-1] = '\0';
1961 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1963 ERR("Error obtaining status flags for socket!\n");
1964 HeapFree(GetProcessHeap(),0,table);
1965 release_sock_fd( s, fd );
1966 WSASetLastError(WSAEINVAL);
1967 return SOCKET_ERROR;
1969 else
1971 /* set flags; the values of IFF_* are not the same
1972 under Linux and Windows, therefore must generate
1973 new flags */
1974 intArray->iiFlags = 0;
1975 if (ifInfo.ifr_flags & IFF_BROADCAST)
1976 intArray->iiFlags |= WS_IFF_BROADCAST;
1977 #ifdef IFF_POINTOPOINT
1978 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
1979 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
1980 #endif
1981 if (ifInfo.ifr_flags & IFF_LOOPBACK)
1982 intArray->iiFlags |= WS_IFF_LOOPBACK;
1983 if (ifInfo.ifr_flags & IFF_UP)
1984 intArray->iiFlags |= WS_IFF_UP;
1985 if (ifInfo.ifr_flags & IFF_MULTICAST)
1986 intArray->iiFlags |= WS_IFF_MULTICAST;
1989 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
1990 mask = inet_addr(ptr->IpAddressList.IpMask.String);
1991 bcast = addr | (addr & !mask);
1992 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1993 intArray->iiAddress.AddressIn.sin_port = 0;
1994 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
1995 addr;
1996 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1997 intArray->iiNetmask.AddressIn.sin_port = 0;
1998 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
1999 mask;
2000 intArray->iiBroadcastAddress.AddressIn.sin_family =
2001 AF_INET;
2002 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
2003 intArray->iiBroadcastAddress.AddressIn.sin_addr.
2004 WS_s_addr = bcast;
2007 else
2009 ERR("Unable to get interface table!\n");
2010 release_sock_fd( s, fd );
2011 HeapFree(GetProcessHeap(),0,table);
2012 WSASetLastError(WSAEINVAL);
2013 return SOCKET_ERROR;
2015 HeapFree(GetProcessHeap(),0,table);
2017 else
2019 release_sock_fd( s, fd );
2020 WSASetLastError(WSAEINVAL);
2021 return SOCKET_ERROR;
2024 else
2026 ERR("Unable to get interface table!\n");
2027 release_sock_fd( s, fd );
2028 WSASetLastError(WSAEINVAL);
2029 return SOCKET_ERROR;
2031 /* Calculate the size of the array being returned */
2032 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2033 break;
2036 case SIO_ADDRESS_LIST_CHANGE:
2037 FIXME("-> SIO_ADDRESS_LIST_CHANGE request: stub\n");
2038 /* FIXME: error and return code depend on whether socket was created
2039 * with WSA_FLAG_OVERLAPPED, but there is no easy way to get this */
2040 break;
2042 default:
2043 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2044 release_sock_fd( s, fd );
2045 WSASetLastError(WSAEOPNOTSUPP);
2046 return SOCKET_ERROR;
2049 /* Function executed with no errors */
2050 release_sock_fd( s, fd );
2051 return 0;
2055 /***********************************************************************
2056 * ioctlsocket (WS2_32.10)
2058 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2060 int fd;
2061 long newcmd = cmd;
2063 TRACE("socket %04x, cmd %08lx, ptr %p\n", s, cmd, argp);
2065 switch( cmd )
2067 case WS_FIONREAD:
2068 newcmd=FIONREAD;
2069 break;
2071 case WS_FIONBIO:
2072 if( _get_sock_mask(s) )
2074 /* AsyncSelect()'ed sockets are always nonblocking */
2075 if (*argp) return 0;
2076 SetLastError(WSAEINVAL);
2077 return SOCKET_ERROR;
2079 fd = get_sock_fd( s, 0, NULL );
2080 if (fd != -1)
2082 int ret;
2083 if (*argp)
2085 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2086 ret = fcntl( fd, F_SETFL, O_NONBLOCK );
2088 else
2090 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2091 ret = fcntl( fd, F_SETFL, 0 );
2093 release_sock_fd( s, fd );
2094 if (!ret) return 0;
2095 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2097 return SOCKET_ERROR;
2099 case WS_SIOCATMARK:
2100 newcmd=SIOCATMARK;
2101 break;
2103 case WS__IOW('f',125,u_long):
2104 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2105 SetLastError(WSAEINVAL);
2106 return SOCKET_ERROR;
2108 case SIOCGIFBRDADDR:
2109 case SIOCGIFNETMASK:
2110 case SIOCGIFADDR:
2111 /* These don't need any special handling. They are used by
2112 WsControl, and are here to suppress an unnecessary warning. */
2113 break;
2115 default:
2116 /* Netscape tries hard to use bogus ioctl 0x667e */
2117 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2118 break;
2121 fd = get_sock_fd( s, 0, NULL );
2122 if (fd != -1)
2124 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2126 release_sock_fd( s, fd );
2127 return 0;
2129 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2130 release_sock_fd( s, fd );
2132 return SOCKET_ERROR;
2135 /***********************************************************************
2136 * listen (WS2_32.13)
2138 int WINAPI WS_listen(SOCKET s, int backlog)
2140 int fd = get_sock_fd( s, GENERIC_READ, NULL );
2142 TRACE("socket %04x, backlog %d\n", s, backlog);
2143 if (fd != -1)
2145 if (listen(fd, backlog) == 0)
2147 release_sock_fd( s, fd );
2148 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2149 FD_WINE_LISTENING,
2150 FD_CONNECT|FD_WINE_CONNECTED);
2151 return 0;
2153 SetLastError(wsaErrno());
2154 release_sock_fd( s, fd );
2156 return SOCKET_ERROR;
2159 /***********************************************************************
2160 * recv (WS2_32.16)
2162 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2164 DWORD n, dwFlags = flags;
2165 WSABUF wsabuf;
2167 wsabuf.len = len;
2168 wsabuf.buf = buf;
2170 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2171 return SOCKET_ERROR;
2172 else
2173 return n;
2176 /***********************************************************************
2177 * recvfrom (WS2_32.17)
2179 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2180 struct WS_sockaddr *from, int *fromlen)
2182 DWORD n, dwFlags = flags;
2183 WSABUF wsabuf;
2185 wsabuf.len = len;
2186 wsabuf.buf = buf;
2188 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2189 return SOCKET_ERROR;
2190 else
2191 return n;
2194 /***********************************************************************
2195 * select (WS2_32.18)
2197 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2198 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2199 const struct WS_timeval* ws_timeout)
2201 int highfd = 0;
2202 fd_set readfds, writefds, exceptfds;
2203 fd_set *p_read, *p_write, *p_except;
2204 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2205 struct timeval timeout, *timeoutaddr = NULL;
2207 TRACE("read %p, write %p, excp %p timeout %p\n",
2208 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2210 p_read = fd_set_import(&readfds, ws_readfds, GENERIC_READ, &highfd, readfd);
2211 p_write = fd_set_import(&writefds, ws_writefds, GENERIC_WRITE, &highfd, writefd);
2212 p_except = fd_set_import(&exceptfds, ws_exceptfds, 0, &highfd, exceptfd);
2213 if (ws_timeout)
2215 timeoutaddr = &timeout;
2216 timeout.tv_sec=ws_timeout->tv_sec;
2217 timeout.tv_usec=ws_timeout->tv_usec;
2220 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2222 fd_set_export(&readfds, p_except, ws_readfds, readfd);
2223 fd_set_export(&writefds, p_except, ws_writefds, writefd);
2225 if (p_except && ws_exceptfds)
2227 unsigned int i, j;
2229 for (i = j = 0; i < ws_exceptfds->fd_count; i++)
2231 int fd = exceptfd[i];
2232 SOCKET s = ws_exceptfds->fd_array[i];
2233 if (fd == -1) continue;
2234 if (FD_ISSET(fd, &exceptfds)) ws_exceptfds->fd_array[j++] = s;
2235 release_sock_fd( s, fd );
2237 ws_exceptfds->fd_count = j;
2239 return highfd;
2241 fd_set_unimport(ws_readfds, readfd);
2242 fd_set_unimport(ws_writefds, writefd);
2243 fd_set_unimport(ws_exceptfds, exceptfd);
2245 if( highfd == 0 ) return 0;
2246 SetLastError(wsaErrno());
2247 return SOCKET_ERROR;
2251 /***********************************************************************
2252 * send (WS2_32.19)
2254 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2256 DWORD n;
2257 WSABUF wsabuf;
2259 wsabuf.len = len;
2260 wsabuf.buf = (char*) buf;
2262 if ( WSASendTo( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2263 return SOCKET_ERROR;
2264 else
2265 return n;
2268 /***********************************************************************
2269 * WSASend (WS2_32.72)
2271 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2272 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2273 LPWSAOVERLAPPED lpOverlapped,
2274 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2276 return WSASendTo( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2277 NULL, 0, lpOverlapped, lpCompletionRoutine );
2280 /***********************************************************************
2281 * WSASendDisconnect (WS2_32.73)
2283 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2285 return WS_shutdown( s, SD_SEND );
2289 /***********************************************************************
2290 * WSASendTo (WS2_32.74)
2292 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2293 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2294 const struct WS_sockaddr *to, int tolen,
2295 LPWSAOVERLAPPED lpOverlapped,
2296 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2298 unsigned int i;
2299 int n, fd, err = WSAENOTSOCK, flags, ret;
2300 struct iovec* iovec;
2301 struct ws2_async *wsa;
2302 IO_STATUS_BLOCK* iosb;
2304 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2305 s, lpBuffers, dwBufferCount, dwFlags,
2306 to, tolen, lpOverlapped, lpCompletionRoutine);
2308 fd = get_sock_fd( s, GENERIC_WRITE, &flags );
2309 TRACE( "fd=%d, flags=%x\n", fd, flags );
2311 if ( fd == -1 ) return SOCKET_ERROR;
2313 if (flags & FD_FLAG_SEND_SHUTDOWN)
2315 WSASetLastError( WSAESHUTDOWN );
2316 goto err_close;
2319 if ( !lpNumberOfBytesSent )
2321 err = WSAEFAULT;
2322 goto err_close;
2325 iovec = HeapAlloc(GetProcessHeap(), 0, dwBufferCount * sizeof(struct iovec) );
2327 if ( !iovec )
2329 err = WSAEFAULT;
2330 goto err_close;
2333 for ( i = 0; i < dwBufferCount; i++ )
2335 iovec[i].iov_base = lpBuffers[i].buf;
2336 iovec[i].iov_len = lpBuffers[i].len;
2339 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2341 wsa = WS2_make_async( s, fd, ws2m_write, iovec, dwBufferCount,
2342 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2343 lpOverlapped, lpCompletionRoutine, &iosb );
2344 if ( !wsa )
2346 err = WSAEFAULT;
2347 goto err_free;
2350 if ( ( ret = ws2_queue_async( wsa, iosb ) ) )
2352 err = NtStatusToWSAError( ret );
2354 if ( !lpOverlapped )
2355 HeapFree( GetProcessHeap(), 0, iosb );
2356 HeapFree( GetProcessHeap(), 0, wsa );
2357 goto err_free;
2360 /* Try immediate completion */
2361 if ( lpOverlapped )
2363 if ( WSAGetOverlappedResult( s, lpOverlapped,
2364 lpNumberOfBytesSent, FALSE, &dwFlags) )
2365 return 0;
2367 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
2368 goto error;
2371 WSASetLastError( WSA_IO_PENDING );
2372 return SOCKET_ERROR;
2375 if (_is_blocking(s))
2377 /* FIXME: exceptfds? */
2378 int timeout = GET_SNDTIMEO(fd);
2379 if( !do_block(fd, POLLOUT, timeout)) {
2380 err = WSAETIMEDOUT;
2381 goto err_free; /* msdn says a timeout in send is fatal */
2385 n = WS2_send( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2386 if ( n == -1 )
2388 err = wsaErrno();
2389 if ( err == WSAEWOULDBLOCK )
2390 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2391 goto err_free;
2394 TRACE(" -> %i bytes\n", n);
2395 *lpNumberOfBytesSent = n;
2397 HeapFree( GetProcessHeap(), 0, iovec );
2398 release_sock_fd( s, fd );
2399 return 0;
2401 err_free:
2402 HeapFree( GetProcessHeap(), 0, iovec );
2404 err_close:
2405 release_sock_fd( s, fd );
2407 error:
2408 WARN(" -> ERROR %d\n", err);
2409 WSASetLastError(err);
2410 return SOCKET_ERROR;
2413 /***********************************************************************
2414 * sendto (WS2_32.20)
2416 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2417 const struct WS_sockaddr *to, int tolen)
2419 DWORD n;
2420 WSABUF wsabuf;
2422 wsabuf.len = len;
2423 wsabuf.buf = (char*) buf;
2425 if ( WSASendTo(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2426 return SOCKET_ERROR;
2427 else
2428 return n;
2431 /***********************************************************************
2432 * setsockopt (WS2_32.21)
2434 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2435 const char *optval, int optlen)
2437 int fd;
2438 int woptval;
2439 struct linger linger;
2440 struct timeval tval;
2442 TRACE("socket: %04x, level %d, name %d, ptr %p, len %d\n",
2443 s, level, optname, optval, optlen);
2445 /* SO_OPENTYPE does not require a valid socket handle. */
2446 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2448 if (optlen < sizeof(int) || !optval)
2450 SetLastError(WSAEFAULT);
2451 return SOCKET_ERROR;
2453 get_per_thread_data()->opentype = *(int *)optval;
2454 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2455 return 0;
2458 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2459 * socket. This will either not happen under windows or it is ignored in
2460 * windows (but it works in linux and therefore prevents the game from
2461 * finding games outside the current network) */
2462 if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE )
2464 FIXME("Does windows ignore SO_DONTROUTE?\n");
2465 return 0;
2468 #ifdef HAVE_IPX
2469 if(level == NSPROTO_IPX)
2471 switch(optname)
2473 case IPX_PTYPE:
2474 fd = get_sock_fd( s, 0, NULL );
2475 TRACE("trying to set IPX_PTYPE: %d (fd: %d)\n", *(int*)optval, fd);
2477 /* We try to set the ipx type on ipx socket level. */
2478 #ifdef SOL_IPX
2479 if(setsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
2481 ERR("IPX: could not set ipx option type; expect weird behaviour\n");
2482 return SOCKET_ERROR;
2484 #else
2486 struct ipx val;
2487 /* Should we retrieve val using a getsockopt call and then
2488 * set the modified one? */
2489 val.ipx_pt = *optval;
2490 setsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, sizeof(struct ipx));
2492 #endif
2493 release_sock_fd( s, fd );
2494 return 0;
2495 case IPX_FILTERPTYPE:
2496 /* Sets the receive filter packet type, at the moment we don't support it */
2497 FIXME("IPX_FILTERPTYPE: %x\n", *optval);
2499 /* Returning 0 is better for now than returning a SOCKET_ERROR */
2500 return 0;
2501 default:
2502 FIXME("opt_name:%x\n", optname);
2503 return SOCKET_ERROR;
2505 return 0;
2507 #endif
2509 /* Is a privileged and useless operation, so we don't. */
2510 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET))
2512 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2513 return 0;
2516 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2517 /* This is unique to WinSock and takes special conversion */
2518 linger.l_onoff = *((int*)optval) ? 0: 1;
2519 linger.l_linger = 0;
2520 optname=SO_LINGER;
2521 optval = (char*)&linger;
2522 optlen = sizeof(struct linger);
2523 level = SOL_SOCKET;
2525 else
2527 if (!convert_sockopt(&level, &optname)) {
2528 ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2529 SetLastError(WSAENOPROTOOPT);
2530 return SOCKET_ERROR;
2532 if (optname == SO_LINGER && optval) {
2533 linger.l_onoff = ((LINGER*)optval)->l_onoff;
2534 linger.l_linger = ((LINGER*)optval)->l_linger;
2535 /* FIXME: what is documented behavior if SO_LINGER optval
2536 is null?? */
2537 optval = (char*)&linger;
2538 optlen = sizeof(struct linger);
2540 else if (optval && optlen < sizeof(int))
2542 woptval= *((INT16 *) optval);
2543 optval= (char*) &woptval;
2544 optlen=sizeof(int);
2546 if (level == SOL_SOCKET && is_timeout_option(optname))
2548 if (optlen == sizeof(UINT32)) {
2549 /* WinSock passes miliseconds instead of struct timeval */
2550 tval.tv_usec = (*(PUINT32)optval % 1000) * 1000;
2551 tval.tv_sec = *(PUINT32)optval / 1000;
2552 /* min of 500 milisec */
2553 if (tval.tv_sec == 0 && tval.tv_usec < 500000)
2554 tval.tv_usec = 500000;
2555 optlen = sizeof(struct timeval);
2556 optval = (char*)&tval;
2557 } else if (optlen == sizeof(struct timeval)) {
2558 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2559 } else {
2560 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2561 return 0;
2564 if (level == SOL_SOCKET && optname == SO_RCVBUF && *(int*)optval < 2048)
2566 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2567 return 0;
2572 fd = get_sock_fd( s, 0, NULL );
2573 if (fd == -1) return SOCKET_ERROR;
2575 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2577 release_sock_fd( s, fd );
2578 return 0;
2580 TRACE("Setting socket error, %d\n", wsaErrno());
2581 SetLastError(wsaErrno());
2582 release_sock_fd( s, fd );
2583 return SOCKET_ERROR;
2586 /***********************************************************************
2587 * shutdown (WS2_32.22)
2589 int WINAPI WS_shutdown(SOCKET s, int how)
2591 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2592 unsigned int clear_flags = 0;
2594 fd = get_sock_fd( s, 0, &flags );
2595 TRACE("socket %04x, how %i %x\n", s, how, flags );
2597 if (fd == -1)
2598 return SOCKET_ERROR;
2600 switch( how )
2602 case 0: /* drop receives */
2603 clear_flags |= FD_READ;
2604 break;
2605 case 1: /* drop sends */
2606 clear_flags |= FD_WRITE;
2607 break;
2608 case 2: /* drop all */
2609 clear_flags |= FD_READ|FD_WRITE;
2610 default:
2611 clear_flags |= FD_WINE_LISTENING;
2614 if ( flags & FD_FLAG_OVERLAPPED ) {
2616 switch ( how )
2618 case SD_RECEIVE:
2619 fd0 = fd;
2620 break;
2621 case SD_SEND:
2622 fd1 = fd;
2623 break;
2624 case SD_BOTH:
2625 default:
2626 fd0 = fd;
2627 fd1 = get_sock_fd( s, 0, NULL );
2628 break;
2631 if ( fd0 != -1 )
2633 err = WS2_register_async_shutdown( s, fd0, ws2m_sd_read );
2634 if ( err )
2636 release_sock_fd( s, fd0 );
2637 goto error;
2640 if ( fd1 != -1 )
2642 err = WS2_register_async_shutdown( s, fd1, ws2m_sd_write );
2643 if ( err )
2645 release_sock_fd( s, fd1 );
2646 goto error;
2650 else /* non-overlapped mode */
2652 if ( shutdown( fd, how ) )
2654 err = wsaErrno();
2655 release_sock_fd( s, fd );
2656 goto error;
2658 release_sock_fd( s, fd );
2661 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2662 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2663 return 0;
2665 error:
2666 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2667 WSASetLastError( err );
2668 return SOCKET_ERROR;
2671 /***********************************************************************
2672 * socket (WS2_32.23)
2674 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2676 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2678 return WSASocketA( af, type, protocol, NULL, 0,
2679 get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
2683 /***********************************************************************
2684 * gethostbyaddr (WS2_32.51)
2686 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
2688 struct WS_hostent *retval = NULL;
2689 struct hostent* host;
2691 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2692 char *extrabuf;
2693 int ebufsize=1024;
2694 struct hostent hostentry;
2695 int locerr=ENOBUFS;
2696 host = NULL;
2697 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2698 while(extrabuf) {
2699 int res = gethostbyaddr_r(addr, len, type,
2700 &hostentry, extrabuf, ebufsize, &host, &locerr);
2701 if( res != ERANGE) break;
2702 ebufsize *=2;
2703 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2705 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2706 #else
2707 EnterCriticalSection( &csWSgetXXXbyYYY );
2708 host = gethostbyaddr(addr, len, type);
2709 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2710 #endif
2711 if( host != NULL ) retval = WS_dup_he(host);
2712 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2713 HeapFree(GetProcessHeap(),0,extrabuf);
2714 #else
2715 LeaveCriticalSection( &csWSgetXXXbyYYY );
2716 #endif
2717 TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
2718 return retval;
2721 /***********************************************************************
2722 * gethostbyname (WS2_32.52)
2724 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2726 struct WS_hostent *retval = NULL;
2727 struct hostent* host;
2728 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2729 char *extrabuf;
2730 int ebufsize=1024;
2731 struct hostent hostentry;
2732 int locerr = ENOBUFS;
2733 #endif
2734 char buf[100];
2735 if( !name) {
2736 name = buf;
2737 if( gethostname( buf, 100) == -1) {
2738 SetLastError( WSAENOBUFS); /* appropriate ? */
2739 return retval;
2742 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2743 host = NULL;
2744 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2745 while(extrabuf) {
2746 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2747 if( res != ERANGE) break;
2748 ebufsize *=2;
2749 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2751 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2752 #else
2753 EnterCriticalSection( &csWSgetXXXbyYYY );
2754 host = gethostbyname(name);
2755 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2756 #endif
2757 if (host) retval = WS_dup_he(host);
2758 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2759 HeapFree(GetProcessHeap(),0,extrabuf);
2760 #else
2761 LeaveCriticalSection( &csWSgetXXXbyYYY );
2762 #endif
2763 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2764 return retval;
2768 /***********************************************************************
2769 * getprotobyname (WS2_32.53)
2771 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
2773 struct WS_protoent* retval = NULL;
2774 #ifdef HAVE_GETPROTOBYNAME
2775 struct protoent* proto;
2776 EnterCriticalSection( &csWSgetXXXbyYYY );
2777 if( (proto = getprotobyname(name)) != NULL )
2779 retval = WS_dup_pe(proto);
2781 else {
2782 MESSAGE("protocol %s not found; You might want to add "
2783 "this to /etc/protocols\n", debugstr_a(name) );
2784 SetLastError(WSANO_DATA);
2786 LeaveCriticalSection( &csWSgetXXXbyYYY );
2787 #endif
2788 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2789 return retval;
2793 /***********************************************************************
2794 * getprotobynumber (WS2_32.54)
2796 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
2798 struct WS_protoent* retval = NULL;
2799 #ifdef HAVE_GETPROTOBYNUMBER
2800 struct protoent* proto;
2801 EnterCriticalSection( &csWSgetXXXbyYYY );
2802 if( (proto = getprotobynumber(number)) != NULL )
2804 retval = WS_dup_pe(proto);
2806 else {
2807 MESSAGE("protocol number %d not found; You might want to add "
2808 "this to /etc/protocols\n", number );
2809 SetLastError(WSANO_DATA);
2811 LeaveCriticalSection( &csWSgetXXXbyYYY );
2812 #endif
2813 TRACE("%i ret %p\n", number, retval);
2814 return retval;
2818 /***********************************************************************
2819 * getservbyname (WS2_32.55)
2821 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
2823 struct WS_servent* retval = NULL;
2824 struct servent* serv;
2825 char *name_str;
2826 char *proto_str = NULL;
2828 if (!(name_str = strdup_lower(name))) return NULL;
2830 if (proto && *proto)
2832 if (!(proto_str = strdup_lower(proto)))
2834 HeapFree( GetProcessHeap(), 0, name_str );
2835 return NULL;
2839 EnterCriticalSection( &csWSgetXXXbyYYY );
2840 serv = getservbyname(name_str, proto_str);
2841 if( serv != NULL )
2843 retval = WS_dup_se(serv);
2845 else SetLastError(WSANO_DATA);
2846 LeaveCriticalSection( &csWSgetXXXbyYYY );
2847 HeapFree( GetProcessHeap(), 0, proto_str );
2848 HeapFree( GetProcessHeap(), 0, name_str );
2849 TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
2850 return retval;
2854 /***********************************************************************
2855 * getservbyport (WS2_32.56)
2857 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
2859 struct WS_servent* retval = NULL;
2860 #ifdef HAVE_GETSERVBYPORT
2861 struct servent* serv;
2862 char *proto_str = NULL;
2864 if (proto && *proto)
2866 if (!(proto_str = strdup_lower(proto))) return NULL;
2868 EnterCriticalSection( &csWSgetXXXbyYYY );
2869 if( (serv = getservbyport(port, proto_str)) != NULL ) {
2870 retval = WS_dup_se(serv);
2872 else SetLastError(WSANO_DATA);
2873 LeaveCriticalSection( &csWSgetXXXbyYYY );
2874 HeapFree( GetProcessHeap(), 0, proto_str );
2875 #endif
2876 TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
2877 return retval;
2881 /***********************************************************************
2882 * gethostname (WS2_32.57)
2884 int WINAPI WS_gethostname(char *name, int namelen)
2886 TRACE("name %p, len %d\n", name, namelen);
2888 if (gethostname(name, namelen) == 0)
2890 TRACE("<- '%s'\n", name);
2891 return 0;
2893 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2894 TRACE("<- ERROR !\n");
2895 return SOCKET_ERROR;
2899 /* ------------------------------------- Windows sockets extensions -- *
2901 * ------------------------------------------------------------------- */
2903 /***********************************************************************
2904 * WSAEnumNetworkEvents (WS2_32.36)
2906 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2908 int ret;
2910 TRACE("%08x, hEvent %p, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2912 SERVER_START_REQ( get_socket_event )
2914 req->handle = SOCKET2HANDLE(s);
2915 req->service = TRUE;
2916 req->c_event = hEvent;
2917 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
2918 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
2920 SERVER_END_REQ;
2921 if (!ret) return 0;
2922 SetLastError(WSAEINVAL);
2923 return SOCKET_ERROR;
2926 /***********************************************************************
2927 * WSAEventSelect (WS2_32.39)
2929 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, long lEvent)
2931 int ret;
2933 TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
2935 SERVER_START_REQ( set_socket_event )
2937 req->handle = SOCKET2HANDLE(s);
2938 req->mask = lEvent;
2939 req->event = hEvent;
2940 req->window = 0;
2941 req->msg = 0;
2942 ret = wine_server_call( req );
2944 SERVER_END_REQ;
2945 if (!ret) return 0;
2946 SetLastError(WSAEINVAL);
2947 return SOCKET_ERROR;
2950 /**********************************************************************
2951 * WSAGetOverlappedResult (WS2_32.40)
2953 BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
2954 LPDWORD lpcbTransfer, BOOL fWait,
2955 LPDWORD lpdwFlags )
2957 DWORD r;
2959 TRACE( "socket %04x ovl %p trans %p, wait %d flags %p\n",
2960 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
2962 if ( lpOverlapped == NULL )
2964 ERR( "Invalid pointer\n" );
2965 WSASetLastError(WSA_INVALID_PARAMETER);
2966 return FALSE;
2969 if ( fWait )
2971 if (lpOverlapped->hEvent)
2972 while ( WaitForSingleObjectEx(lpOverlapped->hEvent,
2973 INFINITE, TRUE) == STATUS_USER_APC );
2974 else /* busy loop */
2975 while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING )
2976 Sleep( 10 );
2979 else if ( lpOverlapped->Internal == STATUS_PENDING )
2981 /* Wait in order to give APCs a chance to run. */
2982 /* This is cheating, so we must set the event again in case of success -
2983 it may be a non-manual reset event. */
2984 while ( (r = WaitForSingleObjectEx(lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
2985 if ( r == WAIT_OBJECT_0 && lpOverlapped->hEvent )
2986 NtSetEvent( lpOverlapped->hEvent, NULL );
2989 if ( lpcbTransfer )
2990 *lpcbTransfer = lpOverlapped->InternalHigh;
2992 if ( lpdwFlags )
2993 *lpdwFlags = lpOverlapped->Offset;
2995 switch ( lpOverlapped->Internal )
2997 case STATUS_SUCCESS:
2998 return TRUE;
2999 case STATUS_PENDING:
3000 WSASetLastError( WSA_IO_INCOMPLETE );
3001 if (fWait) ERR("PENDING status after waiting!\n");
3002 return FALSE;
3003 default:
3004 WSASetLastError( NtStatusToWSAError( lpOverlapped->Internal ));
3005 return FALSE;
3010 /***********************************************************************
3011 * WSAAsyncSelect (WS2_32.101)
3013 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, long lEvent)
3015 int ret;
3017 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3019 SERVER_START_REQ( set_socket_event )
3021 req->handle = SOCKET2HANDLE(s);
3022 req->mask = lEvent;
3023 req->event = 0;
3024 req->window = hWnd;
3025 req->msg = uMsg;
3026 ret = wine_server_call( req );
3028 SERVER_END_REQ;
3029 if (!ret) return 0;
3030 SetLastError(WSAEINVAL);
3031 return SOCKET_ERROR;
3034 /***********************************************************************
3035 * WSACreateEvent (WS2_32.31)
3038 WSAEVENT WINAPI WSACreateEvent(void)
3040 /* Create a manual-reset event, with initial state: unsignaled */
3041 TRACE("\n");
3043 return CreateEventW(NULL, TRUE, FALSE, NULL);
3046 /***********************************************************************
3047 * WSACloseEvent (WS2_32.29)
3050 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3052 TRACE ("event=%p\n", event);
3054 return CloseHandle(event);
3057 /***********************************************************************
3058 * WSASocketA (WS2_32.78)
3061 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3062 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3063 GROUP g, DWORD dwFlags)
3065 INT len;
3066 WSAPROTOCOL_INFOW info;
3068 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3069 af, type, protocol, lpProtocolInfo, g, dwFlags);
3071 if (!lpProtocolInfo) return WSASocketW(af, type, protocol, NULL, g, dwFlags);
3073 memcpy(&info, lpProtocolInfo, FIELD_OFFSET(WSAPROTOCOL_INFOW, szProtocol));
3074 len = MultiByteToWideChar(CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3075 info.szProtocol, WSAPROTOCOL_LEN * sizeof(WCHAR) + 1);
3077 if (!len)
3079 WSASetLastError( WSAEINVAL);
3080 return SOCKET_ERROR;
3083 return WSASocketW(af, type, protocol, &info, g, dwFlags);
3086 /***********************************************************************
3087 * WSASocketW (WS2_32.79)
3090 SOCKET WINAPI WSASocketW(int af, int type, int protocol,
3091 LPWSAPROTOCOL_INFOW lpProtocolInfo,
3092 GROUP g, DWORD dwFlags)
3094 SOCKET ret;
3097 FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
3098 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3101 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3102 af, type, protocol, lpProtocolInfo, g, dwFlags );
3104 /* hack for WSADuplicateSocket */
3105 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3106 ret = lpProtocolInfo->dwCatalogEntryId;
3107 TRACE("\tgot duplicate %04x\n", ret);
3108 return ret;
3111 /* check the socket family */
3112 switch(af)
3114 #ifdef HAVE_IPX
3115 case WS_AF_IPX: af = AF_IPX;
3116 #endif
3117 case AF_INET:
3118 case AF_UNSPEC:
3119 break;
3120 default:
3121 SetLastError(WSAEAFNOSUPPORT);
3122 return INVALID_SOCKET;
3125 /* check the socket type */
3126 switch(type)
3128 case WS_SOCK_STREAM:
3129 type=SOCK_STREAM;
3130 break;
3131 case WS_SOCK_DGRAM:
3132 type=SOCK_DGRAM;
3133 break;
3134 case WS_SOCK_RAW:
3135 type=SOCK_RAW;
3136 break;
3137 default:
3138 SetLastError(WSAESOCKTNOSUPPORT);
3139 return INVALID_SOCKET;
3142 /* check the protocol type */
3143 if ( protocol < 0 ) /* don't support negative values */
3145 SetLastError(WSAEPROTONOSUPPORT);
3146 return INVALID_SOCKET;
3149 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3150 switch(protocol)
3152 case IPPROTO_TCP:
3153 if (type == SOCK_STREAM) { af = AF_INET; break; }
3154 case IPPROTO_UDP:
3155 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3156 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3159 SERVER_START_REQ( create_socket )
3161 req->family = af;
3162 req->type = type;
3163 req->protocol = protocol;
3164 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3165 req->flags = dwFlags;
3166 req->inherit = TRUE;
3167 set_error( wine_server_call( req ) );
3168 ret = HANDLE2SOCKET( reply->handle );
3170 SERVER_END_REQ;
3171 if (ret)
3173 TRACE("\tcreated %04x\n", ret );
3174 return ret;
3177 if (GetLastError() == WSAEACCES) /* raw socket denied */
3179 if (type == SOCK_RAW)
3180 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3181 else
3182 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3183 SetLastError(WSAESOCKTNOSUPPORT);
3186 WARN("\t\tfailed!\n");
3187 return INVALID_SOCKET;
3190 /***********************************************************************
3191 * WSAJoinLeaf (WS2_32.58)
3194 SOCKET WINAPI WSAJoinLeaf(
3195 SOCKET s,
3196 const struct WS_sockaddr *addr,
3197 int addrlen,
3198 LPWSABUF lpCallerData,
3199 LPWSABUF lpCalleeData,
3200 LPQOS lpSQOS,
3201 LPQOS lpGQOS,
3202 DWORD dwFlags)
3204 FIXME("stub.\n");
3205 return INVALID_SOCKET;
3208 /***********************************************************************
3209 * __WSAFDIsSet (WS2_32.151)
3211 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3213 int i = set->fd_count;
3215 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3217 while (i--)
3218 if (set->fd_array[i] == s) return 1;
3219 return 0;
3222 /***********************************************************************
3223 * WSAIsBlocking (WINSOCK.114)
3224 * WSAIsBlocking (WS2_32.114)
3226 BOOL WINAPI WSAIsBlocking(void)
3228 /* By default WinSock should set all its sockets to non-blocking mode
3229 * and poll in PeekMessage loop when processing "blocking" ones. This
3230 * function is supposed to tell if the program is in this loop. Our
3231 * blocking calls are truly blocking so we always return FALSE.
3233 * Note: It is allowed to call this function without prior WSAStartup().
3236 TRACE("\n");
3237 return FALSE;
3240 /***********************************************************************
3241 * WSACancelBlockingCall (WINSOCK.113)
3242 * WSACancelBlockingCall (WS2_32.113)
3244 INT WINAPI WSACancelBlockingCall(void)
3246 TRACE("\n");
3247 return 0;
3250 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
3252 FIXME("How was this called?\n");
3253 return x();
3257 /***********************************************************************
3258 * WSASetBlockingHook (WS2_32.109)
3260 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3262 FARPROC prev = blocking_hook;
3263 blocking_hook = lpBlockFunc;
3264 TRACE("hook %p\n", lpBlockFunc);
3265 return prev;
3269 /***********************************************************************
3270 * WSAUnhookBlockingHook (WS2_32.110)
3272 INT WINAPI WSAUnhookBlockingHook(void)
3274 blocking_hook = WSA_DefaultBlockingHook;
3275 return 0;
3279 /* ----------------------------------- end of API stuff */
3281 /* ----------------------------------- helper functions -
3283 * TODO: Merge WS_dup_..() stuff into one function that
3284 * would operate with a generic structure containing internal
3285 * pointers (via a template of some kind).
3288 static int list_size(char** l, int item_size)
3290 int i,j = 0;
3291 if(l)
3292 { for(i=0;l[i];i++)
3293 j += (item_size) ? item_size : strlen(l[i]) + 1;
3294 j += (i + 1) * sizeof(char*); }
3295 return j;
3298 static int list_dup(char** l_src, char** l_to, int item_size)
3300 char *p;
3301 int i;
3303 for (i = 0; l_src[i]; i++) ;
3304 p = (char *)(l_to + i + 1);
3305 for (i = 0; l_src[i]; i++)
3307 int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3308 memcpy(p, l_src[i], count);
3309 l_to[i] = p;
3310 p += count;
3312 l_to[i] = NULL;
3313 return p - (char *)l_to;
3316 /* ----- hostent */
3318 /* duplicate hostent entry
3319 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3320 * Dito for protoent and servent.
3322 static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
3324 char *p;
3325 struct WS_hostent *p_to;
3327 int size = (sizeof(*p_he) +
3328 strlen(p_he->h_name) + 1 +
3329 list_size(p_he->h_aliases, 0) +
3330 list_size(p_he->h_addr_list, p_he->h_length));
3332 if (!(p_to = check_buffer_he(size))) return NULL;
3333 p_to->h_addrtype = p_he->h_addrtype;
3334 p_to->h_length = p_he->h_length;
3336 p = (char *)(p_to + 1);
3337 p_to->h_name = p;
3338 strcpy(p, p_he->h_name);
3339 p += strlen(p) + 1;
3341 p_to->h_aliases = (char **)p;
3342 p += list_dup(p_he->h_aliases, p_to->h_aliases, 0);
3344 p_to->h_addr_list = (char **)p;
3345 list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length);
3346 return p_to;
3349 /* ----- protoent */
3351 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe)
3353 char *p;
3354 struct WS_protoent *p_to;
3356 int size = (sizeof(*p_pe) +
3357 strlen(p_pe->p_name) + 1 +
3358 list_size(p_pe->p_aliases, 0));
3360 if (!(p_to = check_buffer_pe(size))) return NULL;
3361 p_to->p_proto = p_pe->p_proto;
3363 p = (char *)(p_to + 1);
3364 p_to->p_name = p;
3365 strcpy(p, p_pe->p_name);
3366 p += strlen(p) + 1;
3368 p_to->p_aliases = (char **)p;
3369 list_dup(p_pe->p_aliases, p_to->p_aliases, 0);
3370 return p_to;
3373 /* ----- servent */
3375 static struct WS_servent *WS_dup_se(const struct servent* p_se)
3377 char *p;
3378 struct WS_servent *p_to;
3380 int size = (sizeof(*p_se) +
3381 strlen(p_se->s_proto) + 1 +
3382 strlen(p_se->s_name) + 1 +
3383 list_size(p_se->s_aliases, 0));
3385 if (!(p_to = check_buffer_se(size))) return NULL;
3386 p_to->s_port = p_se->s_port;
3388 p = (char *)(p_to + 1);
3389 p_to->s_name = p;
3390 strcpy(p, p_se->s_name);
3391 p += strlen(p) + 1;
3393 p_to->s_proto = p;
3394 strcpy(p, p_se->s_proto);
3395 p += strlen(p) + 1;
3397 p_to->s_aliases = (char **)p;
3398 list_dup(p_se->s_aliases, p_to->s_aliases, 0);
3399 return p_to;
3402 /* ----------------------------------- error handling */
3404 UINT wsaErrno(void)
3406 int loc_errno = errno;
3407 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3409 switch(loc_errno)
3411 case EINTR: return WSAEINTR;
3412 case EBADF: return WSAEBADF;
3413 case EPERM:
3414 case EACCES: return WSAEACCES;
3415 case EFAULT: return WSAEFAULT;
3416 case EINVAL: return WSAEINVAL;
3417 case EMFILE: return WSAEMFILE;
3418 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3419 case EINPROGRESS: return WSAEINPROGRESS;
3420 case EALREADY: return WSAEALREADY;
3421 case ENOTSOCK: return WSAENOTSOCK;
3422 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3423 case EMSGSIZE: return WSAEMSGSIZE;
3424 case EPROTOTYPE: return WSAEPROTOTYPE;
3425 case ENOPROTOOPT: return WSAENOPROTOOPT;
3426 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3427 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3428 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3429 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3430 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3431 case EADDRINUSE: return WSAEADDRINUSE;
3432 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3433 case ENETDOWN: return WSAENETDOWN;
3434 case ENETUNREACH: return WSAENETUNREACH;
3435 case ENETRESET: return WSAENETRESET;
3436 case ECONNABORTED: return WSAECONNABORTED;
3437 case EPIPE:
3438 case ECONNRESET: return WSAECONNRESET;
3439 case ENOBUFS: return WSAENOBUFS;
3440 case EISCONN: return WSAEISCONN;
3441 case ENOTCONN: return WSAENOTCONN;
3442 case ESHUTDOWN: return WSAESHUTDOWN;
3443 case ETOOMANYREFS: return WSAETOOMANYREFS;
3444 case ETIMEDOUT: return WSAETIMEDOUT;
3445 case ECONNREFUSED: return WSAECONNREFUSED;
3446 case ELOOP: return WSAELOOP;
3447 case ENAMETOOLONG: return WSAENAMETOOLONG;
3448 case EHOSTDOWN: return WSAEHOSTDOWN;
3449 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3450 case ENOTEMPTY: return WSAENOTEMPTY;
3451 #ifdef EPROCLIM
3452 case EPROCLIM: return WSAEPROCLIM;
3453 #endif
3454 #ifdef EUSERS
3455 case EUSERS: return WSAEUSERS;
3456 #endif
3457 #ifdef EDQUOT
3458 case EDQUOT: return WSAEDQUOT;
3459 #endif
3460 #ifdef ESTALE
3461 case ESTALE: return WSAESTALE;
3462 #endif
3463 #ifdef EREMOTE
3464 case EREMOTE: return WSAEREMOTE;
3465 #endif
3467 /* just in case we ever get here and there are no problems */
3468 case 0: return 0;
3469 default:
3470 WARN("Unknown errno %d!\n", loc_errno);
3471 return WSAEOPNOTSUPP;
3475 UINT wsaHerrno(int loc_errno)
3478 WARN("h_errno %d.\n", loc_errno);
3480 switch(loc_errno)
3482 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3483 case TRY_AGAIN: return WSATRY_AGAIN;
3484 case NO_RECOVERY: return WSANO_RECOVERY;
3485 case NO_DATA: return WSANO_DATA;
3486 case ENOBUFS: return WSAENOBUFS;
3488 case 0: return 0;
3489 default:
3490 WARN("Unknown h_errno %d!\n", loc_errno);
3491 return WSAEOPNOTSUPP;
3496 /***********************************************************************
3497 * WSARecv (WS2_32.67)
3499 int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3500 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3501 LPWSAOVERLAPPED lpOverlapped,
3502 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3504 return WSARecvFrom(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3505 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3508 /***********************************************************************
3509 * WSARecvFrom (WS2_32.69)
3511 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3512 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3513 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3514 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3517 unsigned int i;
3518 int n, fd, err = WSAENOTSOCK, flags, ret;
3519 struct iovec* iovec;
3520 struct ws2_async *wsa;
3521 IO_STATUS_BLOCK* iosb;
3523 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3524 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3525 (lpFromlen ? *lpFromlen : -1L),
3526 lpOverlapped, lpCompletionRoutine);
3528 fd = get_sock_fd( s, GENERIC_READ, &flags );
3529 TRACE( "fd=%d, flags=%x\n", fd, flags );
3531 if (fd == -1) return SOCKET_ERROR;
3533 if (flags & FD_FLAG_RECV_SHUTDOWN)
3535 WSASetLastError( WSAESHUTDOWN );
3536 goto err_close;
3539 iovec = HeapAlloc( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3540 if ( !iovec )
3542 err = WSAEFAULT;
3543 goto err_close;
3546 for (i = 0; i < dwBufferCount; i++)
3548 iovec[i].iov_base = lpBuffers[i].buf;
3549 iovec[i].iov_len = lpBuffers[i].len;
3552 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3554 wsa = WS2_make_async( s, fd, ws2m_read, iovec, dwBufferCount,
3555 lpFlags, lpFrom, lpFromlen,
3556 lpOverlapped, lpCompletionRoutine, &iosb );
3558 if ( !wsa )
3560 err = WSAEFAULT;
3561 goto err_free;
3564 if ( ( ret = ws2_queue_async( wsa, iosb )) )
3566 err = NtStatusToWSAError( ret );
3568 if ( !lpOverlapped )
3569 HeapFree( GetProcessHeap(), 0, iosb );
3570 HeapFree( GetProcessHeap(), 0, wsa );
3571 goto err_free;
3574 /* Try immediate completion */
3575 if ( lpOverlapped )
3577 if ( WSAGetOverlappedResult( s, lpOverlapped,
3578 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3579 return 0;
3581 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
3582 goto error;
3585 WSASetLastError( WSA_IO_PENDING );
3586 return SOCKET_ERROR;
3589 if ( _is_blocking(s) )
3591 /* block here */
3592 /* FIXME: OOB and exceptfds? */
3593 int timeout = GET_RCVTIMEO(fd);
3594 if( !do_block(fd, POLLIN, timeout)) {
3595 err = WSAETIMEDOUT;
3596 /* a timeout is not fatal */
3597 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3598 goto err_free;
3602 n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3603 if ( n == -1 )
3605 err = wsaErrno();
3606 goto err_free;
3609 TRACE(" -> %i bytes\n", n);
3610 *lpNumberOfBytesRecvd = n;
3612 HeapFree(GetProcessHeap(), 0, iovec);
3613 release_sock_fd( s, fd );
3614 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3616 return 0;
3618 err_free:
3619 HeapFree(GetProcessHeap(), 0, iovec);
3621 err_close:
3622 release_sock_fd( s, fd );
3624 error:
3625 WARN(" -> ERROR %d\n", err);
3626 WSASetLastError( err );
3627 return SOCKET_ERROR;
3630 /***********************************************************************
3631 * WSCInstallProvider (WS2_32.88)
3633 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
3634 LPCWSTR lpszProviderDllPath,
3635 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
3636 DWORD dwNumberOfEntries,
3637 LPINT lpErrno )
3639 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
3640 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
3641 dwNumberOfEntries, lpErrno);
3642 *lpErrno = 0;
3643 return 0;
3647 /***********************************************************************
3648 * WSCDeinstallProvider (WS2_32.83)
3650 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
3652 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
3653 *lpErrno = 0;
3654 return 0;
3658 /***********************************************************************
3659 * WSAAccept (WS2_32.26)
3661 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
3662 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
3665 int ret = 0, size = 0;
3666 WSABUF CallerId, CallerData, CalleeId, CalleeData;
3667 /* QOS SQOS, GQOS; */
3668 GROUP g;
3669 SOCKET cs;
3670 SOCKADDR src_addr, dst_addr;
3672 TRACE("Socket %04x, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
3673 s, addr, addrlen, lpfnCondition, dwCallbackData);
3676 size = sizeof(src_addr);
3677 cs = WS_accept(s, &src_addr, &size);
3679 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
3681 CallerId.buf = (char *)&src_addr;
3682 CallerId.len = sizeof(src_addr);
3684 CallerData.buf = NULL;
3685 CallerData.len = (ULONG)NULL;
3687 WS_getsockname(cs, &dst_addr, &size);
3689 CalleeId.buf = (char *)&dst_addr;
3690 CalleeId.len = sizeof(dst_addr);
3693 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
3694 &CalleeId, &CalleeData, &g, dwCallbackData);
3696 switch (ret)
3698 case CF_ACCEPT:
3699 if (addr && addrlen)
3700 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
3701 return cs;
3702 case CF_DEFER:
3703 SERVER_START_REQ( set_socket_deferred )
3705 req->handle = SOCKET2HANDLE(s);
3706 req->deferred = SOCKET2HANDLE(cs);
3707 if ( !wine_server_call_err ( req ) )
3709 SetLastError( WSATRY_AGAIN );
3710 WS_closesocket( cs );
3713 SERVER_END_REQ;
3714 return SOCKET_ERROR;
3715 case CF_REJECT:
3716 WS_closesocket(cs);
3717 SetLastError(WSAECONNREFUSED);
3718 return SOCKET_ERROR;
3719 default:
3720 FIXME("Unknown return type from Condition function\n");
3721 SetLastError(WSAENOTSOCK);
3722 return SOCKET_ERROR;
3726 /***********************************************************************
3727 * WSADuplicateSocketA (WS2_32.32)
3729 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
3731 HANDLE hProcess;
3733 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3734 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3735 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
3736 /* I don't know what the real Windoze does next, this is a hack */
3737 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
3738 * the target use the global duplicate, or we could copy a reference to us to the structure
3739 * and let the target duplicate it from us, but let's do it as simple as possible */
3740 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3741 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3742 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3743 0, FALSE, DUPLICATE_SAME_ACCESS);
3744 CloseHandle(hProcess);
3745 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3746 return 0;
3749 /***********************************************************************
3750 * WSADuplicateSocketW (WS2_32.33)
3752 int WINAPI WSADuplicateSocketW( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo )
3754 HANDLE hProcess;
3756 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3758 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3759 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3760 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3761 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3762 0, FALSE, DUPLICATE_SAME_ACCESS);
3763 CloseHandle(hProcess);
3764 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3765 return 0;
3768 /***********************************************************************
3769 * WSAInstallServiceClassA (WS2_32.48)
3771 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
3773 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
3774 WSASetLastError(WSAEACCES);
3775 return SOCKET_ERROR;
3778 /***********************************************************************
3779 * WSAInstallServiceClassW (WS2_32.49)
3781 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
3783 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
3784 WSASetLastError(WSAEACCES);
3785 return SOCKET_ERROR;
3788 /***********************************************************************
3789 * WSARemoveServiceClass (WS2_32.70)
3791 int WINAPI WSARemoveServiceClass(LPGUID info)
3793 FIXME("Request to remove service %p\n",info);
3794 WSASetLastError(WSATYPE_NOT_FOUND);
3795 return SOCKET_ERROR;
3798 /***********************************************************************
3799 * WSAStringToAddressA (WS2_32.80)
3801 INT WINAPI WSAStringToAddressA(LPSTR AddressString,
3802 INT AddressFamily,
3803 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3804 LPSOCKADDR lpAddress,
3805 LPINT lpAddressLength)
3807 INT res=0;
3808 LONG inetaddr;
3809 LPSTR workBuffer=NULL,ptrPort;
3811 TRACE( "(%s, %x, %p, %p, %p)\n", AddressString, AddressFamily, lpProtocolInfo,
3812 lpAddress, lpAddressLength );
3814 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
3816 if (AddressString)
3818 workBuffer = HeapAlloc( GetProcessHeap(), 0, strlen(AddressString)+1 );
3819 if (workBuffer)
3821 strcpy(workBuffer,AddressString);
3822 switch (AddressFamily)
3824 case AF_INET:
3825 /* caller wants to know the size of the socket buffer */
3826 if (*lpAddressLength < sizeof(SOCKADDR_IN))
3828 *lpAddressLength = sizeof(SOCKADDR_IN);
3829 res = WSAEFAULT;
3831 else
3833 /* caller wants to translate an AdressString into a SOCKADDR */
3834 if (lpAddress)
3836 memset(lpAddress,0,sizeof(SOCKADDR_IN));
3837 ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET;
3838 ptrPort = strchr(workBuffer,':');
3839 if (ptrPort)
3841 ((LPSOCKADDR_IN)lpAddress)->sin_port = (u_short)atoi(ptrPort+1);
3842 *ptrPort = '\0';
3844 else
3845 ((LPSOCKADDR_IN)lpAddress)->sin_port = 0;
3846 inetaddr = inet_addr(workBuffer);
3847 if (inetaddr != INADDR_NONE)
3849 ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr;
3850 res = 0;
3852 else
3853 res = WSAEINVAL;
3856 if (lpProtocolInfo)
3857 FIXME("(%s, %x, %p, %p, %p) - ProtocolInfo not implemented!\n",
3858 AddressString, AddressFamily,
3859 lpProtocolInfo, lpAddress, lpAddressLength);
3861 break;
3862 default:
3863 FIXME("(%s, %x, %p, %p, %p) - AddressFamiliy not implemented!\n",
3864 AddressString, AddressFamily,
3865 lpProtocolInfo, lpAddress, lpAddressLength);
3867 HeapFree( GetProcessHeap(), 0, workBuffer );
3869 else
3870 res = WSA_NOT_ENOUGH_MEMORY;
3872 else
3873 res = WSAEINVAL;
3875 if (!res) return 0;
3876 WSASetLastError(res);
3877 return SOCKET_ERROR;
3880 /***********************************************************************
3881 * WSAStringToAddressW (WS2_32.81)
3883 * Does anybody know if this functions allows to use hebrew/arabic/chinese... digits?
3884 * If this should be the case, it would be required to map these digits
3885 * to Unicode digits (0-9) using FoldString first.
3887 INT WINAPI WSAStringToAddressW(LPWSTR AddressString,
3888 INT AddressFamily,
3889 LPWSAPROTOCOL_INFOW lpProtocolInfo,
3890 LPSOCKADDR lpAddress,
3891 LPINT lpAddressLength)
3893 INT sBuffer,res=0;
3894 LPSTR workBuffer=NULL;
3895 WSAPROTOCOL_INFOA infoA;
3896 LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL;
3898 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_w(AddressString), AddressFamily, lpProtocolInfo,
3899 lpAddress, lpAddressLength );
3901 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
3903 /* if ProtocolInfo is available - convert to ANSI variant */
3904 if (lpProtocolInfo)
3906 lpProtoInfoA = &infoA;
3907 memcpy( lpProtoInfoA, lpProtocolInfo, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
3909 if (!WideCharToMultiByte( CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3910 lpProtoInfoA->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL ))
3912 WSASetLastError( WSAEINVAL);
3913 return SOCKET_ERROR;
3917 if (AddressString)
3919 /* Translate AddressString to ANSI code page - assumes that only
3920 standard digits 0-9 are used with this API call */
3921 sBuffer = WideCharToMultiByte( CP_ACP, 0, AddressString, -1, NULL, 0, NULL, NULL );
3922 workBuffer = HeapAlloc( GetProcessHeap(), 0, sBuffer );
3924 if (workBuffer)
3926 WideCharToMultiByte( CP_ACP, 0, AddressString, -1, workBuffer, sBuffer, NULL, NULL );
3927 res = WSAStringToAddressA(workBuffer,AddressFamily,lpProtoInfoA,
3928 lpAddress,lpAddressLength);
3929 HeapFree( GetProcessHeap(), 0, workBuffer );
3930 return res;
3932 else
3933 res = WSA_NOT_ENOUGH_MEMORY;
3935 else
3936 res = WSAEINVAL;
3938 WSASetLastError(res);
3939 return SOCKET_ERROR;
3942 /***********************************************************************
3943 * WSAAddressToStringA (WS2_32.27)
3945 * See WSAAddressToStringW
3947 INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len,
3948 LPWSAPROTOCOL_INFOA info, LPSTR string,
3949 LPDWORD lenstr )
3951 INT size;
3952 CHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
3953 CHAR *p;
3955 TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
3957 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
3958 if (!string || !lenstr) return SOCKET_ERROR;
3960 /* sin_family is garanteed to be the first u_short */
3961 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
3963 sprintf( buffer, "%u.%u.%u.%u:%u",
3964 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
3965 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
3966 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
3967 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
3968 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
3970 p = strchr( buffer, ':' );
3971 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
3973 size = strlen( buffer );
3975 if (*lenstr < size)
3977 *lenstr = size;
3978 return SOCKET_ERROR;
3981 strcpy( string, buffer );
3982 return 0;
3985 /***********************************************************************
3986 * WSAAddressToStringW (WS2_32.28)
3988 * Convert a sockaddr address into a readable address string.
3990 * PARAMS
3991 * sockaddr [I] Pointer to a sockaddr structure.
3992 * len [I] Size of the sockaddr structure.
3993 * info [I] Pointer to a WSAPROTOCOL_INFOW structure (optional).
3994 * string [I/O] Pointer to a buffer to receive the address string.
3995 * lenstr [I/O] Size of the receive buffer in WCHARs.
3997 * RETURNS
3998 * Success: 0
3999 * Failure: SOCKET_ERROR
4001 * NOTES
4002 * The 'info' parameter is ignored.
4004 * BUGS
4005 * Only supports AF_INET addresses.
4007 INT WINAPI WSAAddressToStringW( LPSOCKADDR sockaddr, DWORD len,
4008 LPWSAPROTOCOL_INFOW info, LPWSTR string,
4009 LPDWORD lenstr )
4011 INT size;
4012 WCHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
4013 static const WCHAR format[] = { '%','u','.','%','u','.','%','u','.','%','u',':','%','u',0 };
4014 WCHAR *p;
4016 TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
4018 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
4019 if (!string || !lenstr) return SOCKET_ERROR;
4021 /* sin_family is garanteed to be the first u_short */
4022 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
4024 sprintfW( buffer, format,
4025 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
4026 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
4027 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
4028 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
4029 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
4031 p = strchrW( buffer, ':' );
4032 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
4034 size = lstrlenW( buffer );
4036 if (*lenstr < size)
4038 *lenstr = size;
4039 return SOCKET_ERROR;
4042 lstrcpyW( string, buffer );
4043 return 0;
4046 /***********************************************************************
4047 * WSAEnumNameSpaceProvidersA (WS2_32.34)
4049 INT WINAPI WSAEnumNameSpaceProvidersA( LPDWORD len, LPWSANAMESPACE_INFOA buffer )
4051 FIXME( "(%p %p) Stub!\n", len, buffer );
4052 return 0;
4055 /***********************************************************************
4056 * WSAEnumNameSpaceProvidersW (WS2_32.35)
4058 INT WINAPI WSAEnumNameSpaceProvidersW( LPDWORD len, LPWSANAMESPACE_INFOW buffer )
4060 FIXME( "(%p %p) Stub!\n", len, buffer );
4061 return 0;
4064 /***********************************************************************
4065 * WSAGetQOSByName (WS2_32.41)
4067 BOOL WINAPI WSAGetQOSByName( SOCKET s, LPWSABUF lpQOSName, LPQOS lpQOS )
4069 FIXME( "(0x%04x %p %p) Stub!\n", s, lpQOSName, lpQOS );
4070 return FALSE;
4073 /***********************************************************************
4074 * WSAGetServiceClassInfoA (WS2_32.42)
4076 INT WINAPI WSAGetServiceClassInfoA( LPGUID provider, LPGUID service, LPDWORD len,
4077 LPWSASERVICECLASSINFOA info )
4079 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4080 len, info );
4081 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4082 return SOCKET_ERROR;
4085 /***********************************************************************
4086 * WSAGetServiceClassInfoW (WS2_32.43)
4088 INT WINAPI WSAGetServiceClassInfoW( LPGUID provider, LPGUID service, LPDWORD len,
4089 LPWSASERVICECLASSINFOW info )
4091 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4092 len, info );
4093 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4094 return SOCKET_ERROR;
4097 /***********************************************************************
4098 * WSAGetServiceClassNameByClassIdA (WS2_32.44)
4100 INT WINAPI WSAGetServiceClassNameByClassIdA( LPGUID class, LPSTR service, LPDWORD len )
4102 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4103 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4104 return SOCKET_ERROR;
4107 /***********************************************************************
4108 * WSAGetServiceClassNameByClassIdW (WS2_32.45)
4110 INT WINAPI WSAGetServiceClassNameByClassIdW( LPGUID class, LPWSTR service, LPDWORD len )
4112 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4113 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4114 return SOCKET_ERROR;
4117 /***********************************************************************
4118 * WSALookupServiceBeginA (WS2_32.59)
4120 INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
4121 DWORD dwControlFlags,
4122 LPHANDLE lphLookup)
4124 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4125 lphLookup);
4126 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4127 return SOCKET_ERROR;
4130 /***********************************************************************
4131 * WSALookupServiceBeginW (WS2_32.60)
4133 INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
4134 DWORD dwControlFlags,
4135 LPHANDLE lphLookup)
4137 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4138 lphLookup);
4139 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4140 return SOCKET_ERROR;
4143 /***********************************************************************
4144 * WSALookupServiceBeginW (WS2_32.61)
4146 INT WINAPI WSALookupServiceEnd( HANDLE lookup )
4148 FIXME("(%p) Stub!\n", lookup );
4149 return 0;
4152 /***********************************************************************
4153 * WSALookupServiceNextA (WS2_32.62)
4155 INT WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETA results )
4157 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4158 return 0;
4161 /***********************************************************************
4162 * WSALookupServiceNextW (WS2_32.63)
4164 INT WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETW results )
4166 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4167 return 0;
4170 /***********************************************************************
4171 * WSANtohl (WS2_32.64)
4173 INT WINAPI WSANtohl( SOCKET s, u_long netlong, u_long* lphostlong )
4175 TRACE( "(0x%04x 0x%08lx %p)\n", s, netlong, lphostlong );
4177 if (!lphostlong) return WSAEFAULT;
4179 *lphostlong = ntohl( netlong );
4180 return 0;
4183 /***********************************************************************
4184 * WSANtohs (WS2_32.65)
4186 INT WINAPI WSANtohs( SOCKET s, u_short netshort, u_short* lphostshort )
4188 TRACE( "(0x%04x 0x%08x %p)\n", s, netshort, lphostshort );
4190 if (!lphostshort) return WSAEFAULT;
4192 *lphostshort = ntohs( netshort );
4193 return 0;
4196 /***********************************************************************
4197 * WSAProviderConfigChange (WS2_32.66)
4199 INT WINAPI WSAProviderConfigChange( LPHANDLE handle, LPWSAOVERLAPPED overlapped,
4200 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
4202 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
4203 return SOCKET_ERROR;
4206 /***********************************************************************
4207 * WSARecvDisconnect (WS2_32.68)
4209 INT WINAPI WSARecvDisconnect( SOCKET s, LPWSABUF disconnectdata )
4211 TRACE( "(0x%04x %p)\n", s, disconnectdata );
4213 return WS_shutdown( s, 0 );
4216 /***********************************************************************
4217 * WSASetServiceA (WS2_32.76)
4219 INT WINAPI WSASetServiceA( LPWSAQUERYSETA query, WSAESETSERVICEOP operation, DWORD flags )
4221 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4222 return 0;
4225 /***********************************************************************
4226 * WSASetServiceW (WS2_32.77)
4228 INT WINAPI WSASetServiceW( LPWSAQUERYSETW query, WSAESETSERVICEOP operation, DWORD flags )
4230 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4231 return 0;
4234 /***********************************************************************
4235 * WSCEnableNSProvider (WS2_32.84)
4237 INT WINAPI WSCEnableNSProvider( LPGUID provider, BOOL enable )
4239 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
4240 return 0;
4243 /***********************************************************************
4244 * WSCGetProviderPath (WS2_32.86)
4246 INT WINAPI WSCGetProviderPath( LPGUID provider, LPWSTR path, LPINT len, LPINT errno )
4248 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errno );
4250 if (!errno || !provider || !len) return WSAEFAULT;
4252 *errno = WSAEINVAL;
4253 return SOCKET_ERROR;
4256 /***********************************************************************
4257 * WSCInstallNameSpace (WS2_32.87)
4259 INT WINAPI WSCInstallNameSpace( LPWSTR identifier, LPWSTR path, DWORD namespace,
4260 DWORD version, LPGUID provider )
4262 FIXME( "(%s %s 0x%08lx 0x%08lx %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
4263 namespace, version, debugstr_guid(provider) );
4264 return 0;
4267 /***********************************************************************
4268 * WSCUnInstallNameSpace (WS2_32.89)
4270 INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
4272 FIXME("(%p) Stub!\n", lpProviderId);
4273 return NO_ERROR;
4276 /***********************************************************************
4277 * WSCWriteProviderOrder (WS2_32.91)
4279 INT WINAPI WSCWriteProviderOrder( LPDWORD entry, DWORD number )
4281 FIXME("(%p 0x%08lx) Stub!\n", entry, number);
4282 return 0;