Added descriptions for a few more machine types.
[wine/multimedia.git] / dlls / winsock / socket.c
blob7ce9a36cb7fe509b8655f565d05d014fe5887a5f
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
98 #ifdef HAVE_NETIPX_IPX_H
99 # include <netipx/ipx.h>
100 # define HAVE_IPX
101 #elif defined(HAVE_LINUX_IPX_H)
102 # ifdef HAVE_ASM_TYPES_H
103 # include <asm/types.h>
104 # endif
105 # include <linux/ipx.h>
106 # define HAVE_IPX
107 #endif
109 #ifdef HAVE_POLL_H
110 #include <poll.h>
111 #endif
112 #ifdef HAVE_SYS_POLL_H
113 # include <sys/poll.h>
114 #endif
115 #ifdef HAVE_SYS_TIME_H
116 # include <sys/time.h>
117 #endif
119 #define NONAMELESSUNION
120 #define NONAMELESSSTRUCT
121 #include "windef.h"
122 #include "winbase.h"
123 #include "wingdi.h"
124 #include "winuser.h"
125 #include "winerror.h"
126 #include "winnls.h"
127 #include "winsock2.h"
128 #include "mswsock.h"
129 #include "ws2tcpip.h"
130 #include "ws2spi.h"
131 #include "wsipx.h"
132 #include "winnt.h"
133 #include "iphlpapi.h"
134 #include "thread.h"
135 #include "wine/server.h"
136 #include "wine/debug.h"
137 #include "ntstatus.h"
138 #include "wine/unicode.h"
140 #ifdef HAVE_IPX
141 # include "wsnwlink.h"
142 #endif
145 #ifdef __FreeBSD__
146 # define sipx_network sipx_addr.x_net
147 # define sipx_node sipx_addr.x_host.c_host
148 #endif /* __FreeBSD__ */
150 #ifndef INADDR_NONE
151 #define INADDR_NONE ~0UL
152 #endif
154 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
156 /* critical section to protect some non-rentrant net function */
157 extern CRITICAL_SECTION csWSgetXXXbyYYY;
159 inline static const char *debugstr_sockaddr( const struct WS_sockaddr *a )
161 if (!a) return "(nil)";
162 return wine_dbg_sprintf("{ family %d, address %s, port %d }",
163 ((const struct sockaddr_in *)a)->sin_family,
164 inet_ntoa(((const struct sockaddr_in *)a)->sin_addr),
165 ntohs(((const struct sockaddr_in *)a)->sin_port));
168 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
169 #define SOCKET2HANDLE(s) ((HANDLE)(s))
170 #define HANDLE2SOCKET(h) ((SOCKET)(h))
172 /****************************************************************
173 * Async IO declarations
174 ****************************************************************/
176 typedef struct ws2_async
178 HANDLE hSocket;
179 enum ws2_mode {ws2m_read, ws2m_write, ws2m_sd_read, ws2m_sd_write} mode;
180 LPWSAOVERLAPPED user_overlapped;
181 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
182 struct iovec *iovec;
183 int n_iovecs;
184 struct WS_sockaddr *addr;
185 union
187 int val; /* for send operations */
188 int *ptr; /* for recv operations */
189 } addrlen;
190 DWORD flags;
191 int fd;
192 HANDLE event;
193 } ws2_async;
195 /****************************************************************/
197 /* ----------------------------------- internal data */
199 /* ws_... struct conversion flags */
201 typedef struct /* WSAAsyncSelect() control struct */
203 HANDLE service, event, sock;
204 HWND hWnd;
205 UINT uMsg;
206 LONG lEvent;
207 } ws_select_info;
209 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
210 #define WS_MAX_UDP_DATAGRAM 1024
211 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
213 /* hostent's, servent's and protent's are stored in one buffer per thread,
214 * as documented on MSDN for the functions that return any of the buffers */
215 struct per_thread_data
217 int opentype;
218 struct WS_hostent *he_buffer;
219 struct WS_servent *se_buffer;
220 struct WS_protoent *pe_buffer;
221 int he_len;
222 int se_len;
223 int pe_len;
226 static INT num_startup; /* reference counter */
227 static FARPROC blocking_hook = WSA_DefaultBlockingHook;
229 /* function prototypes */
230 static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
231 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe);
232 static struct WS_servent *WS_dup_se(const struct servent* p_se);
234 int WSAIOCTL_GetInterfaceCount(void);
235 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
237 UINT wsaErrno(void);
238 UINT wsaHerrno(int errnr);
240 #define MAP_OPTION(opt) { WS_##opt, opt }
242 static const int ws_sock_map[][2] =
244 MAP_OPTION( SO_DEBUG ),
245 MAP_OPTION( SO_REUSEADDR ),
246 MAP_OPTION( SO_KEEPALIVE ),
247 MAP_OPTION( SO_DONTROUTE ),
248 MAP_OPTION( SO_BROADCAST ),
249 MAP_OPTION( SO_LINGER ),
250 MAP_OPTION( SO_OOBINLINE ),
251 MAP_OPTION( SO_SNDBUF ),
252 MAP_OPTION( SO_RCVBUF ),
253 MAP_OPTION( SO_ERROR ),
254 MAP_OPTION( SO_TYPE ),
255 #ifdef SO_RCVTIMEO
256 MAP_OPTION( SO_RCVTIMEO ),
257 #endif
258 #ifdef SO_SNDTIMEO
259 MAP_OPTION( SO_SNDTIMEO ),
260 #endif
261 { 0, 0 }
264 static const int ws_tcp_map[][2] =
266 #ifdef TCP_NODELAY
267 MAP_OPTION( TCP_NODELAY ),
268 #endif
269 { 0, 0 }
272 static const int ws_ip_map[][2] =
274 MAP_OPTION( IP_MULTICAST_IF ),
275 MAP_OPTION( IP_MULTICAST_TTL ),
276 MAP_OPTION( IP_MULTICAST_LOOP ),
277 MAP_OPTION( IP_ADD_MEMBERSHIP ),
278 MAP_OPTION( IP_DROP_MEMBERSHIP ),
279 MAP_OPTION( IP_OPTIONS ),
280 #ifdef IP_HDRINCL
281 MAP_OPTION( IP_HDRINCL ),
282 #endif
283 MAP_OPTION( IP_TOS ),
284 MAP_OPTION( IP_TTL ),
285 { 0, 0 }
288 inline static DWORD NtStatusToWSAError( const DWORD status )
290 /* We only need to cover the status codes set by server async request handling */
291 DWORD wserr;
292 switch ( status )
294 case STATUS_SUCCESS: wserr = 0; break;
295 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
296 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
297 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
298 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
299 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
300 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
301 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
302 default:
303 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
304 /* It is not a NT status code but a winsock error */
305 wserr = status;
306 else
308 wserr = RtlNtStatusToDosError( status );
309 FIXME( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
312 return wserr;
315 /* set last error code from NT status without mapping WSA errors */
316 inline static unsigned int set_error( unsigned int err )
318 if (err)
320 err = NtStatusToWSAError( err );
321 SetLastError( err );
323 return err;
326 inline static int get_sock_fd( SOCKET s, DWORD access, int *flags )
328 int fd;
329 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, flags ) ))
330 return -1;
331 return fd;
334 inline static void release_sock_fd( SOCKET s, int fd )
336 wine_server_release_fd( SOCKET2HANDLE(s), fd );
339 static void _enable_event( HANDLE s, unsigned int event,
340 unsigned int sstate, unsigned int cstate )
342 SERVER_START_REQ( enable_socket_event )
344 req->handle = s;
345 req->mask = event;
346 req->sstate = sstate;
347 req->cstate = cstate;
348 wine_server_call( req );
350 SERVER_END_REQ;
353 static int _is_blocking(SOCKET s)
355 int ret;
356 SERVER_START_REQ( get_socket_event )
358 req->handle = SOCKET2HANDLE(s);
359 req->service = FALSE;
360 req->c_event = 0;
361 wine_server_call( req );
362 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
364 SERVER_END_REQ;
365 return ret;
368 static unsigned int _get_sock_mask(SOCKET s)
370 unsigned int ret;
371 SERVER_START_REQ( get_socket_event )
373 req->handle = SOCKET2HANDLE(s);
374 req->service = FALSE;
375 req->c_event = 0;
376 wine_server_call( req );
377 ret = reply->mask;
379 SERVER_END_REQ;
380 return ret;
383 static void _sync_sock_state(SOCKET s)
385 /* do a dummy wineserver request in order to let
386 the wineserver run through its select loop once */
387 (void)_is_blocking(s);
390 static int _get_sock_error(SOCKET s, unsigned int bit)
392 int events[FD_MAX_EVENTS];
394 SERVER_START_REQ( get_socket_event )
396 req->handle = SOCKET2HANDLE(s);
397 req->service = FALSE;
398 req->c_event = 0;
399 wine_server_set_reply( req, events, sizeof(events) );
400 wine_server_call( req );
402 SERVER_END_REQ;
403 return events[bit];
406 static struct per_thread_data *get_per_thread_data(void)
408 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
409 /* lazy initialization */
410 if (!ptb)
412 ptb = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptb) );
413 NtCurrentTeb()->WinSockData = ptb;
415 return ptb;
418 static void free_per_thread_data(void)
420 struct per_thread_data * ptb = NtCurrentTeb()->WinSockData;
422 if (!ptb) return;
424 /* delete scratch buffers */
425 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
426 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
427 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
428 ptb->he_buffer = NULL;
429 ptb->se_buffer = NULL;
430 ptb->pe_buffer = NULL;
432 HeapFree( GetProcessHeap(), 0, ptb );
433 NtCurrentTeb()->WinSockData = NULL;
436 /***********************************************************************
437 * DllMain (WS2_32.init)
439 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
441 TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
442 switch (fdwReason) {
443 case DLL_PROCESS_ATTACH:
444 break;
445 case DLL_PROCESS_DETACH:
446 free_per_thread_data();
447 num_startup = 0;
448 break;
449 case DLL_THREAD_DETACH:
450 free_per_thread_data();
451 break;
453 return TRUE;
456 /***********************************************************************
457 * convert_sockopt()
459 * Converts socket flags from Windows format.
460 * Return 1 if converted, 0 if not (error).
462 static int convert_sockopt(INT *level, INT *optname)
464 int i;
465 switch (*level)
467 case WS_SOL_SOCKET:
468 *level = SOL_SOCKET;
469 for(i=0; ws_sock_map[i][0]; i++)
471 if( ws_sock_map[i][0] == *optname )
473 *optname = ws_sock_map[i][1];
474 return 1;
477 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
478 break;
479 case WS_IPPROTO_TCP:
480 *level = IPPROTO_TCP;
481 for(i=0; ws_tcp_map[i][0]; i++)
483 if ( ws_tcp_map[i][0] == *optname )
485 *optname = ws_tcp_map[i][1];
486 return 1;
489 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
490 break;
491 case WS_IPPROTO_IP:
492 *level = IPPROTO_IP;
493 for(i=0; ws_ip_map[i][0]; i++)
495 if (ws_ip_map[i][0] == *optname )
497 *optname = ws_ip_map[i][1];
498 return 1;
501 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
502 break;
503 default: FIXME("Unimplemented or unknown socket level\n");
505 return 0;
508 static inline BOOL is_timeout_option( int optname )
510 #ifdef SO_RCVTIMEO
511 if (optname == SO_RCVTIMEO) return TRUE;
512 #endif
513 #ifdef SO_SNDTIMEO
514 if (optname == SO_SNDTIMEO) return TRUE;
515 #endif
516 return FALSE;
519 /* ----------------------------------- Per-thread info (or per-process?) */
521 static char *strdup_lower(const char *str)
523 int i;
524 char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
526 if (ret)
528 for (i = 0; str[i]; i++) ret[i] = tolower(str[i]);
529 ret[i] = 0;
531 else SetLastError(WSAENOBUFS);
532 return ret;
535 static fd_set* fd_set_import( fd_set* fds, const WS_fd_set* wsfds, int access, int* highfd, int lfd[] )
537 /* translate Winsock fd set into local fd set */
538 if( wsfds )
540 unsigned int i;
542 FD_ZERO(fds);
543 for( i = 0; i < wsfds->fd_count; i++ )
545 int s = wsfds->fd_array[i];
546 int fd = get_sock_fd( s, access, NULL );
547 if (fd != -1)
549 lfd[ i ] = fd;
550 if( fd > *highfd ) *highfd = fd;
551 FD_SET(fd, fds);
553 else lfd[ i ] = -1;
555 return fds;
557 return NULL;
560 inline static int sock_error_p(int s)
562 unsigned int optval, optlen;
564 optlen = sizeof(optval);
565 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
566 if (optval) WARN("\t[%i] error: %d\n", s, optval);
567 return optval != 0;
570 static int fd_set_export( const fd_set* fds, fd_set* exceptfds, WS_fd_set* wsfds, int lfd[] )
572 int num_err = 0;
574 /* translate local fd set into Winsock fd set, adding
575 * errors to exceptfds (only if app requested it) */
577 if( wsfds )
579 int i, j, count = wsfds->fd_count;
581 for( i = 0, j = 0; i < count; i++ )
583 int fd = lfd[i];
584 SOCKET s = wsfds->fd_array[i];
585 if (fd == -1) continue;
586 if( FD_ISSET(fd, fds) )
588 if ( exceptfds && sock_error_p(fd) )
590 FD_SET(fd, exceptfds);
591 num_err++;
593 else wsfds->fd_array[j++] = s;
595 release_sock_fd( s, fd );
597 wsfds->fd_count = j;
599 return num_err;
602 static void fd_set_unimport( WS_fd_set* wsfds, int lfd[] )
604 if ( wsfds )
606 unsigned int i;
608 for ( i = 0; i < wsfds->fd_count; i++ )
609 if ( lfd[i] >= 0 ) release_sock_fd( wsfds->fd_array[i], lfd[i] );
610 wsfds->fd_count = 0;
614 /* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option
615 * from an fd and return the value converted to milli seconds
616 * or -1 if there is an infinite time out */
617 static inline int get_rcvsnd_timeo( int fd, int optname)
619 struct timeval tv;
620 unsigned int len = sizeof(tv);
621 int ret = getsockopt(fd, SOL_SOCKET, optname, &tv, &len);
622 if( ret >= 0)
623 ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
624 if( ret <= 0 ) /* tv == {0,0} means infinite time out */
625 return -1;
626 return ret;
629 /* macro wrappers for portability */
630 #ifdef SO_RCVTIMEO
631 #define GET_RCVTIMEO(fd) get_rcvsnd_timeo( (fd), SO_RCVTIMEO)
632 #else
633 #define GET_RCVTIMEO(fd) (-1)
634 #endif
636 #ifdef SO_SNDTIMEO
637 #define GET_SNDTIMEO(fd) get_rcvsnd_timeo( (fd), SO_SNDTIMEO)
638 #else
639 #define GET_SNDTIMEO(fd) (-1)
640 #endif
642 /* utility: given an fd, will block until one of the events occurs */
643 static inline int do_block( int fd, int events, int timeout )
645 struct pollfd pfd;
646 int ret;
648 pfd.fd = fd;
649 pfd.events = events;
651 while ((ret = poll(&pfd, 1, timeout)) < 0)
653 if (errno != EINTR)
654 return -1;
656 if( ret == 0 )
657 return 0;
658 return pfd.revents;
662 /* ----------------------------------- API -----
664 * Init / cleanup / error checking.
667 /***********************************************************************
668 * WSAStartup (WS2_32.115)
670 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
672 TRACE("verReq=%x\n", wVersionRequested);
674 if (LOBYTE(wVersionRequested) < 1)
675 return WSAVERNOTSUPPORTED;
677 if (!lpWSAData) return WSAEINVAL;
679 num_startup++;
681 /* that's the whole of the negotiation for now */
682 lpWSAData->wVersion = wVersionRequested;
683 /* return winsock information */
684 lpWSAData->wHighVersion = 0x0202;
685 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
686 strcpy(lpWSAData->szSystemStatus, "Running" );
687 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
688 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
689 /* don't do anything with lpWSAData->lpVendorInfo */
690 /* (some apps don't allocate the space for this field) */
692 TRACE("succeeded\n");
693 return 0;
697 /***********************************************************************
698 * WSACleanup (WS2_32.116)
700 INT WINAPI WSACleanup(void)
702 if (num_startup)
703 return 0;
704 SetLastError(WSANOTINITIALISED);
705 return SOCKET_ERROR;
709 /***********************************************************************
710 * WSAGetLastError (WINSOCK.111)
711 * WSAGetLastError (WS2_32.111)
713 INT WINAPI WSAGetLastError(void)
715 return GetLastError();
718 /***********************************************************************
719 * WSASetLastError (WS2_32.112)
721 void WINAPI WSASetLastError(INT iError) {
722 SetLastError(iError);
725 static struct WS_hostent *check_buffer_he(int size)
727 struct per_thread_data * ptb = get_per_thread_data();
728 if (ptb->he_buffer)
730 if (ptb->he_len >= size ) return ptb->he_buffer;
731 HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
733 ptb->he_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->he_len = size) );
734 if (!ptb->he_buffer) SetLastError(WSAENOBUFS);
735 return ptb->he_buffer;
738 static struct WS_servent *check_buffer_se(int size)
740 struct per_thread_data * ptb = get_per_thread_data();
741 if (ptb->se_buffer)
743 if (ptb->se_len >= size ) return ptb->se_buffer;
744 HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
746 ptb->se_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->se_len = size) );
747 if (!ptb->se_buffer) SetLastError(WSAENOBUFS);
748 return ptb->se_buffer;
751 static struct WS_protoent *check_buffer_pe(int size)
753 struct per_thread_data * ptb = get_per_thread_data();
754 if (ptb->pe_buffer)
756 if (ptb->pe_len >= size ) return ptb->pe_buffer;
757 HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
759 ptb->pe_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->pe_len = size) );
760 if (!ptb->pe_buffer) SetLastError(WSAENOBUFS);
761 return ptb->pe_buffer;
764 /* ----------------------------------- i/o APIs */
766 #ifdef HAVE_IPX
767 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
768 #else
769 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
770 #endif
773 /**********************************************************************/
775 /* Returns the converted address if successful, NULL if it was too small to
776 * start with. Note that the returned pointer may be the original pointer
777 * if no conversion is necessary.
779 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, unsigned int *uaddrlen)
781 switch (wsaddr->sa_family)
783 #ifdef HAVE_IPX
784 case WS_AF_IPX:
786 const struct WS_sockaddr_ipx* wsipx=(const struct WS_sockaddr_ipx*)wsaddr;
787 struct sockaddr_ipx* uipx;
789 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
790 return NULL;
792 *uaddrlen=sizeof(struct sockaddr_ipx);
793 uipx=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
794 uipx->sipx_family=AF_IPX;
795 uipx->sipx_port=wsipx->sa_socket;
796 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
797 * in one go
799 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
800 #ifdef IPX_FRAME_NONE
801 uipx->sipx_type=IPX_FRAME_NONE;
802 #endif
803 return (const struct sockaddr*)uipx;
805 #endif
807 default:
808 if (wsaddrlen<sizeof(struct WS_sockaddr))
809 return NULL;
811 /* No conversion needed, just return the original address */
812 *uaddrlen=wsaddrlen;
813 return (const struct sockaddr*)wsaddr;
817 /* Allocates a Unix sockaddr structure to receive the data */
818 static inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, unsigned int* uaddrlen)
820 if (wsaddr==NULL)
822 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
824 /* This is not strictly the right thing to do. Hope it works however */
825 *uaddrlen=0;
827 return NULL;
830 if (*wsaddrlen==0)
831 *uaddrlen=0;
832 else
833 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
835 return HeapAlloc(GetProcessHeap(), 0, *uaddrlen);
838 /* Returns 0 if successful, -1 if the buffer is too small */
839 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
841 int res;
843 switch(uaddr->sa_family)
845 #ifdef HAVE_IPX
846 case AF_IPX:
848 const struct sockaddr_ipx* uipx=(const struct sockaddr_ipx*)uaddr;
849 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
851 res=-1;
852 switch (*wsaddrlen) /* how much can we copy? */
854 default:
855 res=0; /* enough */
856 *wsaddrlen=uaddrlen;
857 wsipx->sa_socket=uipx->sipx_port;
858 /* fall through */
859 case 13:
860 case 12:
861 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
862 /* fall through */
863 case 11:
864 case 10:
865 case 9:
866 case 8:
867 case 7:
868 case 6:
869 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
870 /* fall through */
871 case 5:
872 case 4:
873 case 3:
874 case 2:
875 wsipx->sa_family=WS_AF_IPX;
876 /* fall through */
877 case 1:
878 case 0:
879 /* way too small */
880 break;
883 break;
884 #endif
886 default:
887 /* No conversion needed */
888 memcpy(wsaddr,uaddr,*wsaddrlen);
889 if (*wsaddrlen<uaddrlen) {
890 res=-1;
891 } else {
892 *wsaddrlen=uaddrlen;
893 res=0;
896 return res;
899 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
900 * ws_sockaddr_alloc
902 static inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
904 if (uaddr!=(const struct sockaddr*)wsaddr)
905 HeapFree(GetProcessHeap(), 0, (void *)uaddr);
908 /**************************************************************************
909 * Functions for handling overlapped I/O
910 **************************************************************************/
912 static void CALLBACK ws2_async_terminate(ws2_async* as, IO_STATUS_BLOCK* iosb)
914 TRACE( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, iosb );
916 wine_server_release_fd( as->hSocket, as->fd );
917 if ( as->event != INVALID_HANDLE_VALUE )
918 NtSetEvent( as->event, NULL );
920 if (as->completion_func)
921 as->completion_func( NtStatusToWSAError (iosb->u.Status),
922 iosb->Information, as->user_overlapped, as->flags );
923 if ( !as->user_overlapped )
925 #if 0
926 /* FIXME: I don't think this is really used */
927 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
928 WSACloseEvent( as->overlapped->hEvent );
929 #endif
930 HeapFree( GetProcessHeap(), 0, iosb );
933 HeapFree( GetProcessHeap(), 0, as->iovec );
934 HeapFree( GetProcessHeap(), 0, as );
937 /***********************************************************************
938 * WS2_make_async (INTERNAL)
941 static void WINAPI WS2_async_recv(void*, IO_STATUS_BLOCK*, ULONG);
942 static void WINAPI WS2_async_send(void*, IO_STATUS_BLOCK*, ULONG);
943 static void WINAPI WS2_async_shutdown( void*, IO_STATUS_BLOCK*, ULONG);
945 inline static struct ws2_async*
946 WS2_make_async(SOCKET s, int fd, enum ws2_mode mode, struct iovec *iovec, DWORD dwBufferCount,
947 LPDWORD lpFlags, struct WS_sockaddr *addr,
948 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
949 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
950 IO_STATUS_BLOCK **piosb)
952 struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof( ws2_async ) );
954 TRACE( "wsa %p\n", wsa );
956 if (!wsa)
957 return NULL;
959 wsa->hSocket = (HANDLE) s;
960 wsa->mode = mode;
961 switch (mode)
963 case ws2m_read:
964 case ws2m_sd_read:
965 wsa->flags = *lpFlags;
966 wsa->addrlen.ptr = addrlen;
967 break;
968 case ws2m_write:
969 case ws2m_sd_write:
970 wsa->flags = 0;
971 wsa->addrlen.val = *addrlen;
972 break;
973 default:
974 ERR("Invalid async mode: %d\n", mode);
976 wsa->user_overlapped = lpOverlapped;
977 wsa->completion_func = lpCompletionRoutine;
978 wsa->iovec = iovec;
979 wsa->n_iovecs = dwBufferCount;
980 wsa->addr = addr;
981 wsa->fd = fd;
982 wsa->event = INVALID_HANDLE_VALUE;
984 if ( lpOverlapped )
986 *piosb = (IO_STATUS_BLOCK*)lpOverlapped;
987 if (!lpCompletionRoutine)
989 wsa->event = lpOverlapped->hEvent;
990 NtResetEvent(wsa->event, NULL);
993 else if (!(*piosb = HeapAlloc( GetProcessHeap(), 0, sizeof(IO_STATUS_BLOCK))))
994 goto error;
996 (*piosb)->Information = 0;
997 (*piosb)->u.Status = STATUS_PENDING;
998 TRACE( "wsa %p, h %p, ev %p, fd %d, iosb %p, uov %p, cfunc %p\n",
999 wsa, wsa->hSocket, wsa->event, wsa->fd,
1000 *piosb, wsa->user_overlapped, wsa->completion_func );
1002 return wsa;
1004 error:
1005 TRACE("Error\n");
1006 HeapFree( GetProcessHeap(), 0, wsa );
1007 return NULL;
1010 static ULONG ws2_queue_async(struct ws2_async* wsa, IO_STATUS_BLOCK* iosb)
1012 PIO_APC_ROUTINE apc;
1013 int type;
1014 NTSTATUS status;
1016 switch (wsa->mode)
1018 case ws2m_read: apc = WS2_async_recv; type = ASYNC_TYPE_READ; break;
1019 case ws2m_write: apc = WS2_async_send; type = ASYNC_TYPE_WRITE; break;
1020 case ws2m_sd_read: apc = WS2_async_shutdown; type = ASYNC_TYPE_READ; break;
1021 case ws2m_sd_write: apc = WS2_async_shutdown; type = ASYNC_TYPE_WRITE; break;
1022 default: FIXME("Unknown internal mode (%d)\n", wsa->mode); return STATUS_INVALID_PARAMETER;
1025 SERVER_START_REQ( register_async )
1027 req->handle = wsa->hSocket;
1028 req->io_apc = apc;
1029 req->io_sb = iosb;
1030 req->io_user = wsa;
1031 req->type = type;
1032 req->count = iosb->Information;
1033 status = wine_server_call( req );
1035 SERVER_END_REQ;
1037 if ( status ) iosb->u.Status = status;
1038 if ( iosb->u.Status != STATUS_PENDING )
1040 /* Note: we get here a non zero status when we couldn't queue the async
1041 * in the server. Therefore, we simply terminate the async.
1043 status = iosb->u.Status;
1044 ws2_async_terminate(wsa, iosb);
1045 return status;
1047 NtCurrentTeb()->num_async_io++;
1048 return STATUS_SUCCESS;
1051 /***********************************************************************
1052 * WS2_recv (INTERNAL)
1054 * Workhorse for both synchronous and asynchronous recv() operations.
1056 static int WS2_recv( int fd, struct iovec* iov, int count,
1057 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1058 LPDWORD lpFlags )
1060 struct msghdr hdr;
1061 int n;
1062 TRACE( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
1063 fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
1065 hdr.msg_name = NULL;
1067 if ( lpFrom )
1069 hdr.msg_namelen = *lpFromlen;
1070 hdr.msg_name = ws_sockaddr_alloc( lpFrom, lpFromlen, &hdr.msg_namelen );
1071 if ( !hdr.msg_name )
1073 WSASetLastError( WSAEFAULT );
1074 n = -1;
1075 goto out;
1078 else
1079 hdr.msg_namelen = 0;
1081 hdr.msg_iov = iov;
1082 hdr.msg_iovlen = count;
1083 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1084 hdr.msg_accrights = NULL;
1085 hdr.msg_accrightslen = 0;
1086 #else
1087 hdr.msg_control = NULL;
1088 hdr.msg_controllen = 0;
1089 hdr.msg_flags = 0;
1090 #endif
1092 if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 )
1094 TRACE( "recvmsg error %d\n", errno);
1095 goto out;
1098 if ( lpFrom &&
1099 ws_sockaddr_u2ws( hdr.msg_name, hdr.msg_namelen,
1100 lpFrom, lpFromlen ) != 0 )
1102 /* The from buffer was too small, but we read the data
1103 * anyway. Is that really bad?
1105 WSASetLastError( WSAEFAULT );
1106 WARN( "Address buffer too small\n" );
1109 out:
1111 ws_sockaddr_free( hdr.msg_name, lpFrom );
1112 TRACE("-> %d\n", n);
1113 return n;
1116 /***********************************************************************
1117 * WS2_async_recv (INTERNAL)
1119 * Handler for overlapped recv() operations.
1121 static void WINAPI WS2_async_recv( void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
1123 ws2_async* wsa = (ws2_async*) ovp;
1124 int result, err;
1126 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1128 switch (status)
1130 case STATUS_ALERTED:
1131 result = WS2_recv( wsa->fd, wsa->iovec, wsa->n_iovecs,
1132 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1133 if (result >= 0)
1135 iosb->u.Status = STATUS_SUCCESS;
1136 iosb->Information = result;
1137 TRACE( "received %d bytes\n", result );
1138 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1140 else
1142 err = wsaErrno();
1143 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1145 iosb->u.Status = STATUS_PENDING;
1146 _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1147 TRACE( "still pending\n" );
1149 else
1151 iosb->u.Status = err; /* FIXME: is this correct ???? */
1152 TRACE( "Error: %x\n", err );
1155 if (iosb->u.Status == STATUS_PENDING)
1156 ws2_queue_async(wsa, iosb);
1157 else
1158 ws2_async_terminate(wsa, iosb);
1159 break;
1160 default:
1161 FIXME( "status: %ld\n", status );
1162 iosb->u.Status = status;
1163 ws2_async_terminate(wsa, iosb);
1164 return;
1168 /***********************************************************************
1169 * WS2_send (INTERNAL)
1171 * Workhorse for both synchronous and asynchronous send() operations.
1173 static int WS2_send( int fd, struct iovec* iov, int count,
1174 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1176 struct msghdr hdr;
1177 int n = -1;
1178 TRACE( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
1179 fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
1181 hdr.msg_name = NULL;
1183 if ( to )
1185 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u( to, tolen, &hdr.msg_namelen );
1186 if ( !hdr.msg_name )
1188 WSASetLastError( WSAEFAULT );
1189 goto out;
1192 #ifdef HAVE_IPX
1193 if(to->sa_family == WS_AF_IPX)
1195 #ifdef SOL_IPX
1196 struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
1197 int val=0;
1198 unsigned int len=sizeof(int);
1200 /* The packet type is stored at the ipx socket level; At least the linux kernel seems
1201 * to do something with it in case hdr.msg_name is NULL. Nonetheless can we use it to store
1202 * the packet type and then we can retrieve it using getsockopt. After that we can set the
1203 * ipx type in the sockaddr_opx structure with the stored value.
1205 if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1)
1207 TRACE("ptype: %d (fd:%d)\n", val, fd);
1208 uipx->sipx_type = val;
1210 #endif
1212 #endif
1215 else
1216 hdr.msg_namelen = 0;
1218 hdr.msg_iov = iov;
1219 hdr.msg_iovlen = count;
1220 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1221 hdr.msg_accrights = NULL;
1222 hdr.msg_accrightslen = 0;
1223 #else
1224 hdr.msg_control = NULL;
1225 hdr.msg_controllen = 0;
1226 hdr.msg_flags = 0;
1227 #endif
1229 n = sendmsg(fd, &hdr, dwFlags);
1231 out:
1232 ws_sockaddr_free( hdr.msg_name, to );
1233 return n;
1236 /***********************************************************************
1237 * WS2_async_send (INTERNAL)
1239 * Handler for overlapped send() operations.
1241 static void WINAPI WS2_async_send(void* as, IO_STATUS_BLOCK* iosb, ULONG status)
1243 ws2_async* wsa = (ws2_async*) as;
1244 int result;
1246 TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1248 switch (status)
1250 case STATUS_ALERTED:
1251 if (iosb->u.Status != STATUS_PENDING) FIXME("wrong %08lx\n", iosb->u.Status);
1252 /* check to see if the data is ready (non-blocking) */
1253 result = WS2_send( wsa->fd, wsa->iovec, wsa->n_iovecs,
1254 wsa->addr, wsa->addrlen.val, wsa->flags );
1256 if (result >= 0)
1258 iosb->u.Status = STATUS_SUCCESS;
1259 iosb->Information = result;
1260 TRACE( "sent %d bytes\n", result );
1261 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1263 else
1265 int err = wsaErrno();
1266 if ( err == WSAEINTR )
1268 iosb->u.Status = STATUS_PENDING;
1269 _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1270 TRACE( "still pending\n" );
1272 else
1274 /* We set the status to a winsock error code and check for that
1275 later in NtStatusToWSAError () */
1276 iosb->u.Status = err;
1277 TRACE( "Error: %x\n", err );
1280 if (iosb->u.Status == STATUS_PENDING)
1281 ws2_queue_async(wsa, iosb);
1282 else
1283 ws2_async_terminate(wsa, iosb);
1284 break;
1285 default:
1286 FIXME( "status: %ld\n", status );
1287 iosb->u.Status = status;
1288 ws2_async_terminate(wsa, iosb);
1289 return;
1294 /***********************************************************************
1295 * WS2_async_shutdown (INTERNAL)
1297 * Handler for shutdown() operations on overlapped sockets.
1299 static void WINAPI WS2_async_shutdown( void* as, PIO_STATUS_BLOCK iosb, ULONG status )
1301 ws2_async* wsa = (ws2_async*) as;
1302 int err = 1;
1304 TRACE( "async %p %d\n", wsa, wsa->mode );
1305 switch (status)
1307 case STATUS_ALERTED:
1308 switch ( wsa->mode )
1310 case ws2m_sd_read: err = shutdown( wsa->fd, 0 ); break;
1311 case ws2m_sd_write: err = shutdown( wsa->fd, 1 ); break;
1312 default: ERR("invalid mode: %d\n", wsa->mode );
1314 iosb->u.Status = err ? wsaErrno() : STATUS_SUCCESS;
1315 if (iosb->u.Status == STATUS_PENDING)
1316 ws2_queue_async(wsa, iosb);
1317 else
1318 ws2_async_terminate(wsa, iosb);
1319 break;
1320 default:
1321 iosb->u.Status = status;
1322 ws2_async_terminate(wsa, iosb);
1323 break;
1328 /***********************************************************************
1329 * WS2_register_async_shutdown (INTERNAL)
1331 * Helper function for WS_shutdown() on overlapped sockets.
1333 static int WS2_register_async_shutdown( SOCKET s, int fd, enum ws2_mode mode )
1335 struct ws2_async *wsa;
1336 int ret, err = WSAEFAULT;
1337 DWORD dwflags = 0;
1338 int len = 0;
1339 LPWSAOVERLAPPED ovl = HeapAlloc(GetProcessHeap(), 0, sizeof( WSAOVERLAPPED ));
1340 IO_STATUS_BLOCK *iosb = NULL;
1342 TRACE("s %d fd %d mode %d\n", s, fd, mode);
1343 if (!ovl)
1344 goto out;
1346 ovl->hEvent = WSACreateEvent();
1347 if ( ovl->hEvent == WSA_INVALID_EVENT )
1348 goto out_free;
1350 wsa = WS2_make_async( s, fd, mode, NULL, 0,
1351 &dwflags, NULL, &len, ovl, NULL, &iosb );
1352 if ( !wsa )
1353 goto out_close;
1355 /* Hack: this will cause ws2_async_terminate() to free the overlapped structure */
1356 wsa->user_overlapped = NULL;
1357 if ( (ret = ws2_queue_async( wsa, iosb )) )
1359 err = NtStatusToWSAError( ret );
1360 goto out;
1362 /* Try immediate completion */
1363 while ( WaitForSingleObjectEx( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1364 return 0;
1366 out_close:
1367 WSACloseEvent( ovl->hEvent );
1368 out_free:
1369 HeapFree( GetProcessHeap(), 0, ovl );
1370 out:
1371 return err;
1374 /***********************************************************************
1375 * accept (WS2_32.1)
1377 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1378 int *addrlen32)
1380 SOCKET as;
1382 TRACE("socket %04x\n", s );
1383 if (_is_blocking(s))
1385 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1386 if (fd == -1) return INVALID_SOCKET;
1387 /* block here */
1388 do_block(fd, POLLIN, -1);
1389 _sync_sock_state(s); /* let wineserver notice connection */
1390 release_sock_fd( s, fd );
1391 /* retrieve any error codes from it */
1392 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1393 /* FIXME: care about the error? */
1395 SERVER_START_REQ( accept_socket )
1397 req->lhandle = SOCKET2HANDLE(s);
1398 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1399 req->inherit = TRUE;
1400 set_error( wine_server_call( req ) );
1401 as = HANDLE2SOCKET( reply->handle );
1403 SERVER_END_REQ;
1404 if (as)
1406 if (addr) WS_getpeername(as, addr, addrlen32);
1407 return as;
1409 return INVALID_SOCKET;
1412 /***********************************************************************
1413 * bind (WS2_32.2)
1415 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1417 int fd = get_sock_fd( s, 0, NULL );
1418 int res = SOCKET_ERROR;
1420 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1422 if (fd != -1)
1424 if (!name || (name->sa_family && !SUPPORTED_PF(name->sa_family)))
1426 SetLastError(WSAEAFNOSUPPORT);
1428 else
1430 const struct sockaddr* uaddr;
1431 unsigned int uaddrlen;
1433 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1434 if (uaddr == NULL)
1436 SetLastError(WSAEFAULT);
1438 else
1440 if (bind(fd, uaddr, uaddrlen) < 0)
1442 int loc_errno = errno;
1443 WARN("\tfailure - errno = %i\n", errno);
1444 errno = loc_errno;
1445 switch (errno)
1447 case EBADF:
1448 SetLastError(WSAENOTSOCK);
1449 break;
1450 case EADDRNOTAVAIL:
1451 SetLastError(WSAEINVAL);
1452 break;
1453 default:
1454 SetLastError(wsaErrno());
1455 break;
1458 else
1460 res=0; /* success */
1462 ws_sockaddr_free(uaddr,name);
1465 release_sock_fd( s, fd );
1467 return res;
1470 /***********************************************************************
1471 * closesocket (WS2_32.3)
1473 int WINAPI WS_closesocket(SOCKET s)
1475 TRACE("socket %04x\n", s);
1476 if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1477 return SOCKET_ERROR;
1480 /***********************************************************************
1481 * connect (WS2_32.4)
1483 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1485 int fd = get_sock_fd( s, GENERIC_READ, NULL );
1487 TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1489 if (fd != -1)
1491 const struct sockaddr* uaddr;
1492 unsigned int uaddrlen;
1494 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1495 if (uaddr == NULL)
1497 SetLastError(WSAEFAULT);
1499 else
1501 int rc;
1503 rc=connect(fd, uaddr, uaddrlen);
1504 ws_sockaddr_free(uaddr,name);
1505 if (rc == 0)
1506 goto connect_success;
1509 if (errno == EINPROGRESS)
1511 /* tell wineserver that a connection is in progress */
1512 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1513 FD_CONNECT|FD_READ|FD_WRITE,
1514 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1515 if (_is_blocking(s))
1517 int result;
1518 /* block here */
1519 do_block(fd, POLLIN | POLLOUT, -1);
1520 _sync_sock_state(s); /* let wineserver notice connection */
1521 /* retrieve any error codes from it */
1522 result = _get_sock_error(s, FD_CONNECT_BIT);
1523 if (result)
1524 SetLastError(result);
1525 else
1527 goto connect_success;
1530 else
1532 SetLastError(WSAEWOULDBLOCK);
1535 else
1537 SetLastError(wsaErrno());
1539 release_sock_fd( s, fd );
1541 return SOCKET_ERROR;
1543 connect_success:
1544 release_sock_fd( s, fd );
1545 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1546 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1547 FD_CONNECT|FD_WINE_LISTENING);
1548 return 0;
1551 /***********************************************************************
1552 * WSAConnect (WS2_32.30)
1554 int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
1555 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1556 LPQOS lpSQOS, LPQOS lpGQOS )
1558 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1559 FIXME("unsupported parameters!\n");
1560 return WS_connect( s, name, namelen );
1564 /***********************************************************************
1565 * getpeername (WS2_32.5)
1567 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1569 int fd;
1570 int res;
1572 TRACE("socket: %04x, ptr %p, len %08x\n", s, name, *namelen);
1574 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1575 if( (name == NULL) || (namelen == NULL) )
1577 SetLastError( WSAEFAULT );
1578 return SOCKET_ERROR;
1581 fd = get_sock_fd( s, 0, NULL );
1582 res = SOCKET_ERROR;
1584 if (fd != -1)
1586 struct sockaddr* uaddr;
1587 unsigned int uaddrlen;
1589 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1590 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1592 SetLastError(wsaErrno());
1594 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1596 /* The buffer was too small */
1597 SetLastError(WSAEFAULT);
1599 else
1601 res=0;
1603 ws_sockaddr_free(uaddr,name);
1604 release_sock_fd( s, fd );
1606 return res;
1609 /***********************************************************************
1610 * getsockname (WS2_32.6)
1612 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1614 int fd;
1615 int res;
1617 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1619 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1620 if( (name == NULL) || (namelen == NULL) )
1622 SetLastError( WSAEFAULT );
1623 return SOCKET_ERROR;
1626 fd = get_sock_fd( s, 0, NULL );
1627 res = SOCKET_ERROR;
1629 if (fd != -1)
1631 struct sockaddr* uaddr;
1632 unsigned int uaddrlen;
1634 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1635 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1637 SetLastError(wsaErrno());
1639 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1641 /* The buffer was too small */
1642 SetLastError(WSAEFAULT);
1644 else
1646 res=0;
1648 ws_sockaddr_free(uaddr,name);
1649 release_sock_fd( s, fd );
1651 return res;
1654 /***********************************************************************
1655 * getsockopt (WS2_32.7)
1657 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1658 INT optname, char *optval, INT *optlen)
1660 int fd;
1661 INT ret = 0;
1663 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1664 (int) optname, (int) optval, (int) *optlen);
1665 /* SO_OPENTYPE does not require a valid socket handle. */
1666 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1668 if (!optlen || *optlen < sizeof(int) || !optval)
1670 SetLastError(WSAEFAULT);
1671 return SOCKET_ERROR;
1673 *(int *)optval = get_per_thread_data()->opentype;
1674 *optlen = sizeof(int);
1675 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1676 return 0;
1679 #ifdef HAVE_IPX
1680 if(level == NSPROTO_IPX)
1682 struct WS_sockaddr_ipx addr;
1683 IPX_ADDRESS_DATA *data;
1684 int namelen;
1685 switch(optname)
1687 case IPX_PTYPE:
1688 fd = get_sock_fd( s, 0, NULL );
1689 #ifdef SOL_IPX
1690 if(getsockopt(fd, SOL_IPX, IPX_TYPE, optval, (unsigned int*)optlen) == -1)
1692 return SOCKET_ERROR;
1694 #else
1696 struct ipx val;
1697 socklen_t len=sizeof(struct ipx);
1699 if(getsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, &len) == -1 )
1700 return SOCKET_ERROR;
1701 *optval = (int)val.ipx_pt;
1703 #endif
1704 TRACE("ptype: %d (fd: %d)\n", *(int*)optval, fd);
1705 release_sock_fd( s, fd );
1707 return 0;
1708 case IPX_ADDRESS:
1710 * On a Win2000 system with one network card there are usually three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
1711 * Using this call you can then retrieve info about this all. In case of Linux it is a bit different. Usually you have
1712 * only "one" device active and further it is not possible to query things like the linkspeed.
1714 FIXME("IPX_ADDRESS\n");
1715 namelen = sizeof(struct WS_sockaddr_ipx);
1716 memset(&addr, 0, sizeof(struct WS_sockaddr_ipx));
1717 WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
1719 data = (IPX_ADDRESS_DATA*)optval;
1720 memcpy(data->nodenum,&addr.sa_nodenum,sizeof(data->nodenum));
1721 memcpy(data->netnum,&addr.sa_netnum,sizeof(data->netnum));
1722 data->adapternum = 0;
1723 data->wan = FALSE; /* We are not on a wan for now .. */
1724 data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
1725 data->maxpkt = 1467; /* This value is the default one, at least on Win2k/WinXP */
1726 data->linkspeed = 100000; /* Set the line speed in 100bit/s to 10 Mbit; note 1MB = 1000kB in this case */
1727 return 0;
1728 case IPX_MAX_ADAPTER_NUM:
1729 FIXME("IPX_MAX_ADAPTER_NUM\n");
1730 *(int*)optval = 1; /* As noted under IPX_ADDRESS we have just one card. */
1732 return 0;
1733 default:
1734 FIXME("IPX optname:%x\n", optname);
1735 return SOCKET_ERROR;
1738 #endif
1740 if( (fd = get_sock_fd( s, 0, NULL )) == -1)
1741 return SOCKET_ERROR;
1743 if (!convert_sockopt(&level, &optname)) {
1744 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1745 ret = SOCKET_ERROR;
1746 } else {
1747 struct timeval tv;
1748 struct linger lingval;
1749 unsigned int len, *plen = (unsigned int*)optlen;
1750 char *pval = optval;
1751 if(level == SOL_SOCKET && is_timeout_option(optname)) {
1752 len = sizeof(tv);
1753 plen = &len;
1754 pval = (char *) &tv;
1755 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1756 len = sizeof(lingval);
1757 plen = &len;
1758 pval = (char *) &lingval;
1760 if (getsockopt(fd, (int) level, optname, pval, plen) != 0 ) {
1761 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1762 ret = SOCKET_ERROR;
1763 } else if(level == SOL_SOCKET && is_timeout_option(optname)) {
1764 if( *optlen >= sizeof(INT) ) {
1765 *optlen = sizeof(INT);
1766 *(INT*)optval = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1767 } else {
1768 SetLastError(WSAEFAULT);
1769 ret = SOCKET_ERROR;
1771 } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1772 if( *optlen >= sizeof( LINGER) ) {
1773 (( LINGER *) optval)->l_onoff = lingval.l_onoff;
1774 (( LINGER *) optval)->l_linger = lingval.l_linger;
1775 } else {
1776 SetLastError(WSAEFAULT);
1777 ret = SOCKET_ERROR;
1781 release_sock_fd( s, fd );
1782 return ret;
1786 /***********************************************************************
1787 * htonl (WINSOCK.8)
1788 * htonl (WS2_32.8)
1790 u_long WINAPI WS_htonl(u_long hostlong)
1792 return htonl(hostlong);
1796 /***********************************************************************
1797 * htons (WINSOCK.9)
1798 * htons (WS2_32.9)
1800 u_short WINAPI WS_htons(u_short hostshort)
1802 return htons(hostshort);
1805 /***********************************************************************
1806 * WSAHtonl (WS2_32.46)
1807 * From MSDN decription of error codes, this function should also
1808 * check if WinSock has been initialized and the socket is a valid
1809 * socket. But why? This function only translates a host byte order
1810 * u_long into a network byte order u_long...
1812 int WINAPI WSAHtonl(SOCKET s, u_long hostlong, u_long *lpnetlong)
1814 if (lpnetlong)
1816 *lpnetlong = htonl(hostlong);
1817 return 0;
1819 WSASetLastError(WSAEFAULT);
1820 return SOCKET_ERROR;
1823 /***********************************************************************
1824 * WSAHtons (WS2_32.47)
1825 * From MSDN decription of error codes, this function should also
1826 * check if WinSock has been initialized and the socket is a valid
1827 * socket. But why? This function only translates a host byte order
1828 * u_short into a network byte order u_short...
1830 int WINAPI WSAHtons(SOCKET s, u_short hostshort, u_short *lpnetshort)
1833 if (lpnetshort)
1835 *lpnetshort = htons(hostshort);
1836 return 0;
1838 WSASetLastError(WSAEFAULT);
1839 return SOCKET_ERROR;
1843 /***********************************************************************
1844 * inet_addr (WINSOCK.10)
1845 * inet_addr (WS2_32.11)
1847 u_long WINAPI WS_inet_addr(const char *cp)
1849 return inet_addr(cp);
1853 /***********************************************************************
1854 * ntohl (WINSOCK.14)
1855 * ntohl (WS2_32.14)
1857 u_long WINAPI WS_ntohl(u_long netlong)
1859 return ntohl(netlong);
1863 /***********************************************************************
1864 * ntohs (WINSOCK.15)
1865 * ntohs (WS2_32.15)
1867 u_short WINAPI WS_ntohs(u_short netshort)
1869 return ntohs(netshort);
1873 /***********************************************************************
1874 * inet_ntoa (WS2_32.12)
1876 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1878 /* use "buffer for dummies" here because some applications have a
1879 * propensity to decode addresses in ws_hostent structure without
1880 * saving them first...
1882 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1884 char* s = inet_ntoa(*((struct in_addr*)&in));
1885 if( s )
1887 strcpy(dbuffer, s);
1888 return dbuffer;
1890 SetLastError(wsaErrno());
1891 return NULL;
1894 /**********************************************************************
1895 * WSAIoctl (WS2_32.50)
1898 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1900 INT WINAPI WSAIoctl(SOCKET s,
1901 DWORD dwIoControlCode,
1902 LPVOID lpvInBuffer,
1903 DWORD cbInBuffer,
1904 LPVOID lpbOutBuffer,
1905 DWORD cbOutBuffer,
1906 LPDWORD lpcbBytesReturned,
1907 LPWSAOVERLAPPED lpOverlapped,
1908 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1910 int fd = get_sock_fd( s, 0, NULL );
1912 if (fd == -1) return SOCKET_ERROR;
1914 TRACE("%d, 0x%08lx, %p, %ld, %p, %ld, %p, %p, %p\n",
1915 s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpbOutBuffer,
1916 cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
1918 switch( dwIoControlCode )
1920 case SIO_GET_INTERFACE_LIST:
1922 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1923 DWORD size, numInt, apiReturn;
1925 TRACE("-> SIO_GET_INTERFACE_LIST request\n");
1927 if (!lpbOutBuffer)
1929 release_sock_fd( s, fd );
1930 WSASetLastError(WSAEFAULT);
1931 return SOCKET_ERROR;
1933 if (!lpcbBytesReturned)
1935 release_sock_fd( s, fd );
1936 WSASetLastError(WSAEFAULT);
1937 return SOCKET_ERROR;
1940 apiReturn = GetAdaptersInfo(NULL, &size);
1941 if (apiReturn == ERROR_NO_DATA)
1943 numInt = 0;
1945 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
1947 PIP_ADAPTER_INFO table = HeapAlloc(GetProcessHeap(),0,size);
1949 if (table)
1951 if (GetAdaptersInfo(table, &size) == NO_ERROR)
1953 PIP_ADAPTER_INFO ptr;
1955 if (size*sizeof(INTERFACE_INFO)/sizeof(IP_ADAPTER_INFO) > cbOutBuffer)
1957 WARN("Buffer too small = %lu, cbOutBuffer = %lu\n", size, cbOutBuffer);
1958 HeapFree(GetProcessHeap(),0,table);
1959 release_sock_fd( s, fd );
1960 WSASetLastError(WSAEFAULT);
1961 return SOCKET_ERROR;
1963 for (ptr = table, numInt = 0; ptr;
1964 ptr = ptr->Next, intArray++, numInt++)
1966 unsigned int addr, mask, bcast;
1967 struct ifreq ifInfo;
1969 /* Socket Status Flags */
1970 lstrcpynA(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
1971 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1973 ERR("Error obtaining status flags for socket!\n");
1974 HeapFree(GetProcessHeap(),0,table);
1975 release_sock_fd( s, fd );
1976 WSASetLastError(WSAEINVAL);
1977 return SOCKET_ERROR;
1979 else
1981 /* set flags; the values of IFF_* are not the same
1982 under Linux and Windows, therefore must generate
1983 new flags */
1984 intArray->iiFlags = 0;
1985 if (ifInfo.ifr_flags & IFF_BROADCAST)
1986 intArray->iiFlags |= WS_IFF_BROADCAST;
1987 #ifdef IFF_POINTOPOINT
1988 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
1989 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
1990 #endif
1991 if (ifInfo.ifr_flags & IFF_LOOPBACK)
1992 intArray->iiFlags |= WS_IFF_LOOPBACK;
1993 if (ifInfo.ifr_flags & IFF_UP)
1994 intArray->iiFlags |= WS_IFF_UP;
1995 if (ifInfo.ifr_flags & IFF_MULTICAST)
1996 intArray->iiFlags |= WS_IFF_MULTICAST;
1999 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
2000 mask = inet_addr(ptr->IpAddressList.IpMask.String);
2001 bcast = addr | (addr & !mask);
2002 intArray->iiAddress.AddressIn.sin_family = AF_INET;
2003 intArray->iiAddress.AddressIn.sin_port = 0;
2004 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
2005 addr;
2006 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2007 intArray->iiNetmask.AddressIn.sin_port = 0;
2008 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
2009 mask;
2010 intArray->iiBroadcastAddress.AddressIn.sin_family =
2011 AF_INET;
2012 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
2013 intArray->iiBroadcastAddress.AddressIn.sin_addr.
2014 WS_s_addr = bcast;
2017 else
2019 ERR("Unable to get interface table!\n");
2020 release_sock_fd( s, fd );
2021 HeapFree(GetProcessHeap(),0,table);
2022 WSASetLastError(WSAEINVAL);
2023 return SOCKET_ERROR;
2025 HeapFree(GetProcessHeap(),0,table);
2027 else
2029 release_sock_fd( s, fd );
2030 WSASetLastError(WSAEINVAL);
2031 return SOCKET_ERROR;
2034 else
2036 ERR("Unable to get interface table!\n");
2037 release_sock_fd( s, fd );
2038 WSASetLastError(WSAEINVAL);
2039 return SOCKET_ERROR;
2041 /* Calculate the size of the array being returned */
2042 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2043 break;
2046 case SIO_ADDRESS_LIST_CHANGE:
2047 FIXME("-> SIO_ADDRESS_LIST_CHANGE request: stub\n");
2048 /* FIXME: error and return code depend on whether socket was created
2049 * with WSA_FLAG_OVERLAPPED, but there is no easy way to get this */
2050 break;
2052 default:
2053 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2054 release_sock_fd( s, fd );
2055 WSASetLastError(WSAEOPNOTSUPP);
2056 return SOCKET_ERROR;
2059 /* Function executed with no errors */
2060 release_sock_fd( s, fd );
2061 return 0;
2065 /***********************************************************************
2066 * ioctlsocket (WS2_32.10)
2068 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2070 int fd;
2071 long newcmd = cmd;
2073 TRACE("socket %04x, cmd %08lx, ptr %p\n", s, cmd, argp);
2075 switch( cmd )
2077 case WS_FIONREAD:
2078 newcmd=FIONREAD;
2079 break;
2081 case WS_FIONBIO:
2082 if( _get_sock_mask(s) )
2084 /* AsyncSelect()'ed sockets are always nonblocking */
2085 if (*argp) return 0;
2086 SetLastError(WSAEINVAL);
2087 return SOCKET_ERROR;
2089 fd = get_sock_fd( s, 0, NULL );
2090 if (fd != -1)
2092 int ret;
2093 if (*argp)
2095 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2096 ret = fcntl( fd, F_SETFL, O_NONBLOCK );
2098 else
2100 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2101 ret = fcntl( fd, F_SETFL, 0 );
2103 release_sock_fd( s, fd );
2104 if (!ret) return 0;
2105 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2107 return SOCKET_ERROR;
2109 case WS_SIOCATMARK:
2110 newcmd=SIOCATMARK;
2111 break;
2113 case WS__IOW('f',125,u_long):
2114 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2115 SetLastError(WSAEINVAL);
2116 return SOCKET_ERROR;
2118 case SIOCGIFBRDADDR:
2119 case SIOCGIFNETMASK:
2120 case SIOCGIFADDR:
2121 /* These don't need any special handling. They are used by
2122 WsControl, and are here to suppress an unnecessary warning. */
2123 break;
2125 default:
2126 /* Netscape tries hard to use bogus ioctl 0x667e */
2127 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2128 break;
2131 fd = get_sock_fd( s, 0, NULL );
2132 if (fd != -1)
2134 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2136 release_sock_fd( s, fd );
2137 return 0;
2139 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2140 release_sock_fd( s, fd );
2142 return SOCKET_ERROR;
2145 /***********************************************************************
2146 * listen (WS2_32.13)
2148 int WINAPI WS_listen(SOCKET s, int backlog)
2150 int fd = get_sock_fd( s, GENERIC_READ, NULL );
2152 TRACE("socket %04x, backlog %d\n", s, backlog);
2153 if (fd != -1)
2155 if (listen(fd, backlog) == 0)
2157 release_sock_fd( s, fd );
2158 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2159 FD_WINE_LISTENING,
2160 FD_CONNECT|FD_WINE_CONNECTED);
2161 return 0;
2163 SetLastError(wsaErrno());
2164 release_sock_fd( s, fd );
2166 return SOCKET_ERROR;
2169 /***********************************************************************
2170 * recv (WS2_32.16)
2172 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2174 DWORD n, dwFlags = flags;
2175 WSABUF wsabuf;
2177 wsabuf.len = len;
2178 wsabuf.buf = buf;
2180 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2181 return SOCKET_ERROR;
2182 else
2183 return n;
2186 /***********************************************************************
2187 * recvfrom (WS2_32.17)
2189 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2190 struct WS_sockaddr *from, int *fromlen)
2192 DWORD n, dwFlags = flags;
2193 WSABUF wsabuf;
2195 wsabuf.len = len;
2196 wsabuf.buf = buf;
2198 if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2199 return SOCKET_ERROR;
2200 else
2201 return n;
2204 /***********************************************************************
2205 * select (WS2_32.18)
2207 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2208 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2209 const struct WS_timeval* ws_timeout)
2211 int highfd = 0;
2212 fd_set readfds, writefds, exceptfds;
2213 fd_set *p_read, *p_write, *p_except;
2214 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2215 struct timeval timeout, *timeoutaddr = NULL;
2217 TRACE("read %p, write %p, excp %p timeout %p\n",
2218 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2220 p_read = fd_set_import(&readfds, ws_readfds, GENERIC_READ, &highfd, readfd);
2221 p_write = fd_set_import(&writefds, ws_writefds, GENERIC_WRITE, &highfd, writefd);
2222 p_except = fd_set_import(&exceptfds, ws_exceptfds, 0, &highfd, exceptfd);
2223 if (ws_timeout)
2225 timeoutaddr = &timeout;
2226 timeout.tv_sec=ws_timeout->tv_sec;
2227 timeout.tv_usec=ws_timeout->tv_usec;
2230 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2232 fd_set_export(&readfds, p_except, ws_readfds, readfd);
2233 fd_set_export(&writefds, p_except, ws_writefds, writefd);
2235 if (p_except && ws_exceptfds)
2237 unsigned int i, j;
2239 for (i = j = 0; i < ws_exceptfds->fd_count; i++)
2241 int fd = exceptfd[i];
2242 SOCKET s = ws_exceptfds->fd_array[i];
2243 if (fd == -1) continue;
2244 if (FD_ISSET(fd, &exceptfds)) ws_exceptfds->fd_array[j++] = s;
2245 release_sock_fd( s, fd );
2247 ws_exceptfds->fd_count = j;
2249 return highfd;
2251 fd_set_unimport(ws_readfds, readfd);
2252 fd_set_unimport(ws_writefds, writefd);
2253 fd_set_unimport(ws_exceptfds, exceptfd);
2255 if( highfd == 0 ) return 0;
2256 SetLastError(wsaErrno());
2257 return SOCKET_ERROR;
2261 /***********************************************************************
2262 * send (WS2_32.19)
2264 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2266 DWORD n;
2267 WSABUF wsabuf;
2269 wsabuf.len = len;
2270 wsabuf.buf = (char*) buf;
2272 if ( WSASendTo( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2273 return SOCKET_ERROR;
2274 else
2275 return n;
2278 /***********************************************************************
2279 * WSASend (WS2_32.72)
2281 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2282 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2283 LPWSAOVERLAPPED lpOverlapped,
2284 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2286 return WSASendTo( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2287 NULL, 0, lpOverlapped, lpCompletionRoutine );
2290 /***********************************************************************
2291 * WSASendDisconnect (WS2_32.73)
2293 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2295 return WS_shutdown( s, SD_SEND );
2299 /***********************************************************************
2300 * WSASendTo (WS2_32.74)
2302 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2303 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2304 const struct WS_sockaddr *to, int tolen,
2305 LPWSAOVERLAPPED lpOverlapped,
2306 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2308 unsigned int i;
2309 int n, fd, err = WSAENOTSOCK, flags, ret;
2310 struct iovec* iovec;
2311 struct ws2_async *wsa;
2312 IO_STATUS_BLOCK* iosb;
2314 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2315 s, lpBuffers, dwBufferCount, dwFlags,
2316 to, tolen, lpOverlapped, lpCompletionRoutine);
2318 fd = get_sock_fd( s, GENERIC_WRITE, &flags );
2319 TRACE( "fd=%d, flags=%x\n", fd, flags );
2321 if ( fd == -1 ) return SOCKET_ERROR;
2323 if (flags & FD_FLAG_SEND_SHUTDOWN)
2325 WSASetLastError( WSAESHUTDOWN );
2326 goto err_close;
2329 if ( !lpNumberOfBytesSent )
2331 err = WSAEFAULT;
2332 goto err_close;
2335 iovec = HeapAlloc(GetProcessHeap(), 0, dwBufferCount * sizeof(struct iovec) );
2337 if ( !iovec )
2339 err = WSAEFAULT;
2340 goto err_close;
2343 for ( i = 0; i < dwBufferCount; i++ )
2345 iovec[i].iov_base = lpBuffers[i].buf;
2346 iovec[i].iov_len = lpBuffers[i].len;
2349 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2351 wsa = WS2_make_async( s, fd, ws2m_write, iovec, dwBufferCount,
2352 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2353 lpOverlapped, lpCompletionRoutine, &iosb );
2354 if ( !wsa )
2356 err = WSAEFAULT;
2357 goto err_free;
2360 if ( ( ret = ws2_queue_async( wsa, iosb ) ) )
2362 err = NtStatusToWSAError( ret );
2364 if ( !lpOverlapped )
2365 HeapFree( GetProcessHeap(), 0, iosb );
2366 HeapFree( GetProcessHeap(), 0, wsa );
2367 goto err_free;
2370 /* Try immediate completion */
2371 if ( lpOverlapped )
2373 if ( WSAGetOverlappedResult( s, lpOverlapped,
2374 lpNumberOfBytesSent, FALSE, &dwFlags) )
2375 return 0;
2377 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
2378 goto error;
2381 WSASetLastError( WSA_IO_PENDING );
2382 return SOCKET_ERROR;
2385 if (_is_blocking(s))
2387 /* FIXME: exceptfds? */
2388 int timeout = GET_SNDTIMEO(fd);
2389 if( !do_block(fd, POLLOUT, timeout)) {
2390 err = WSAETIMEDOUT;
2391 goto err_free; /* msdn says a timeout in send is fatal */
2395 n = WS2_send( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2396 if ( n == -1 )
2398 err = wsaErrno();
2399 if ( err == WSAEWOULDBLOCK )
2400 _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2401 goto err_free;
2404 TRACE(" -> %i bytes\n", n);
2405 *lpNumberOfBytesSent = n;
2407 HeapFree( GetProcessHeap(), 0, iovec );
2408 release_sock_fd( s, fd );
2409 return 0;
2411 err_free:
2412 HeapFree( GetProcessHeap(), 0, iovec );
2414 err_close:
2415 release_sock_fd( s, fd );
2417 error:
2418 WARN(" -> ERROR %d\n", err);
2419 WSASetLastError(err);
2420 return SOCKET_ERROR;
2423 /***********************************************************************
2424 * sendto (WS2_32.20)
2426 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2427 const struct WS_sockaddr *to, int tolen)
2429 DWORD n;
2430 WSABUF wsabuf;
2432 wsabuf.len = len;
2433 wsabuf.buf = (char*) buf;
2435 if ( WSASendTo(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2436 return SOCKET_ERROR;
2437 else
2438 return n;
2441 /***********************************************************************
2442 * setsockopt (WS2_32.21)
2444 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2445 const char *optval, int optlen)
2447 int fd;
2448 int woptval;
2449 struct linger linger;
2450 struct timeval tval;
2452 TRACE("socket: %04x, level %d, name %d, ptr %p, len %d\n",
2453 s, level, optname, optval, optlen);
2455 /* SO_OPENTYPE does not require a valid socket handle. */
2456 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2458 if (optlen < sizeof(int) || !optval)
2460 SetLastError(WSAEFAULT);
2461 return SOCKET_ERROR;
2463 get_per_thread_data()->opentype = *(int *)optval;
2464 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2465 return 0;
2468 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2469 * socket. This will either not happen under windows or it is ignored in
2470 * windows (but it works in linux and therefore prevents the game from
2471 * finding games outside the current network) */
2472 if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE )
2474 FIXME("Does windows ignore SO_DONTROUTE?\n");
2475 return 0;
2478 #ifdef HAVE_IPX
2479 if(level == NSPROTO_IPX)
2481 switch(optname)
2483 case IPX_PTYPE:
2484 fd = get_sock_fd( s, 0, NULL );
2485 TRACE("trying to set IPX_PTYPE: %d (fd: %d)\n", *(int*)optval, fd);
2487 /* We try to set the ipx type on ipx socket level. */
2488 #ifdef SOL_IPX
2489 if(setsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
2491 ERR("IPX: could not set ipx option type; expect weird behaviour\n");
2492 return SOCKET_ERROR;
2494 #else
2496 struct ipx val;
2497 /* Should we retrieve val using a getsockopt call and then
2498 * set the modified one? */
2499 val.ipx_pt = *optval;
2500 setsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, sizeof(struct ipx));
2502 #endif
2503 release_sock_fd( s, fd );
2504 return 0;
2505 case IPX_FILTERPTYPE:
2506 /* Sets the receive filter packet type, at the moment we don't support it */
2507 FIXME("IPX_FILTERPTYPE: %x\n", *optval);
2509 /* Returning 0 is better for now than returning a SOCKET_ERROR */
2510 return 0;
2511 default:
2512 FIXME("opt_name:%x\n", optname);
2513 return SOCKET_ERROR;
2515 return 0;
2517 #endif
2519 /* Is a privileged and useless operation, so we don't. */
2520 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET))
2522 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2523 return 0;
2526 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2527 /* This is unique to WinSock and takes special conversion */
2528 linger.l_onoff = *((int*)optval) ? 0: 1;
2529 linger.l_linger = 0;
2530 optname=SO_LINGER;
2531 optval = (char*)&linger;
2532 optlen = sizeof(struct linger);
2533 level = SOL_SOCKET;
2535 else
2537 if (!convert_sockopt(&level, &optname)) {
2538 ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2539 SetLastError(WSAENOPROTOOPT);
2540 return SOCKET_ERROR;
2542 if (optname == SO_LINGER && optval) {
2543 linger.l_onoff = ((LINGER*)optval)->l_onoff;
2544 linger.l_linger = ((LINGER*)optval)->l_linger;
2545 /* FIXME: what is documented behavior if SO_LINGER optval
2546 is null?? */
2547 optval = (char*)&linger;
2548 optlen = sizeof(struct linger);
2550 else if (optval && optlen < sizeof(int))
2552 woptval= *((INT16 *) optval);
2553 optval= (char*) &woptval;
2554 optlen=sizeof(int);
2556 if (level == SOL_SOCKET && is_timeout_option(optname))
2558 if (optlen == sizeof(UINT32)) {
2559 /* WinSock passes miliseconds instead of struct timeval */
2560 tval.tv_usec = (*(PUINT32)optval % 1000) * 1000;
2561 tval.tv_sec = *(PUINT32)optval / 1000;
2562 /* min of 500 milisec */
2563 if (tval.tv_sec == 0 && tval.tv_usec < 500000)
2564 tval.tv_usec = 500000;
2565 optlen = sizeof(struct timeval);
2566 optval = (char*)&tval;
2567 } else if (optlen == sizeof(struct timeval)) {
2568 WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2569 } else {
2570 WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2571 return 0;
2574 if (level == SOL_SOCKET && optname == SO_RCVBUF && *(int*)optval < 2048)
2576 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2577 return 0;
2582 fd = get_sock_fd( s, 0, NULL );
2583 if (fd == -1) return SOCKET_ERROR;
2585 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2587 release_sock_fd( s, fd );
2588 return 0;
2590 TRACE("Setting socket error, %d\n", wsaErrno());
2591 SetLastError(wsaErrno());
2592 release_sock_fd( s, fd );
2593 return SOCKET_ERROR;
2596 /***********************************************************************
2597 * shutdown (WS2_32.22)
2599 int WINAPI WS_shutdown(SOCKET s, int how)
2601 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2602 unsigned int clear_flags = 0;
2604 fd = get_sock_fd( s, 0, &flags );
2605 TRACE("socket %04x, how %i %x\n", s, how, flags );
2607 if (fd == -1)
2608 return SOCKET_ERROR;
2610 switch( how )
2612 case 0: /* drop receives */
2613 clear_flags |= FD_READ;
2614 break;
2615 case 1: /* drop sends */
2616 clear_flags |= FD_WRITE;
2617 break;
2618 case 2: /* drop all */
2619 clear_flags |= FD_READ|FD_WRITE;
2620 default:
2621 clear_flags |= FD_WINE_LISTENING;
2624 if ( flags & FD_FLAG_OVERLAPPED ) {
2626 switch ( how )
2628 case SD_RECEIVE:
2629 fd0 = fd;
2630 break;
2631 case SD_SEND:
2632 fd1 = fd;
2633 break;
2634 case SD_BOTH:
2635 default:
2636 fd0 = fd;
2637 fd1 = get_sock_fd( s, 0, NULL );
2638 break;
2641 if ( fd0 != -1 )
2643 err = WS2_register_async_shutdown( s, fd0, ws2m_sd_read );
2644 if ( err )
2646 release_sock_fd( s, fd0 );
2647 goto error;
2650 if ( fd1 != -1 )
2652 err = WS2_register_async_shutdown( s, fd1, ws2m_sd_write );
2653 if ( err )
2655 release_sock_fd( s, fd1 );
2656 goto error;
2660 else /* non-overlapped mode */
2662 if ( shutdown( fd, how ) )
2664 err = wsaErrno();
2665 release_sock_fd( s, fd );
2666 goto error;
2668 release_sock_fd( s, fd );
2671 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2672 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2673 return 0;
2675 error:
2676 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2677 WSASetLastError( err );
2678 return SOCKET_ERROR;
2681 /***********************************************************************
2682 * socket (WS2_32.23)
2684 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2686 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2688 return WSASocketA( af, type, protocol, NULL, 0,
2689 get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
2693 /***********************************************************************
2694 * gethostbyaddr (WS2_32.51)
2696 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
2698 struct WS_hostent *retval = NULL;
2699 struct hostent* host;
2701 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2702 char *extrabuf;
2703 int ebufsize=1024;
2704 struct hostent hostentry;
2705 int locerr=ENOBUFS;
2706 host = NULL;
2707 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2708 while(extrabuf) {
2709 int res = gethostbyaddr_r(addr, len, type,
2710 &hostentry, extrabuf, ebufsize, &host, &locerr);
2711 if( res != ERANGE) break;
2712 ebufsize *=2;
2713 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2715 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2716 #else
2717 EnterCriticalSection( &csWSgetXXXbyYYY );
2718 host = gethostbyaddr(addr, len, type);
2719 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2720 #endif
2721 if( host != NULL ) retval = WS_dup_he(host);
2722 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2723 HeapFree(GetProcessHeap(),0,extrabuf);
2724 #else
2725 LeaveCriticalSection( &csWSgetXXXbyYYY );
2726 #endif
2727 TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
2728 return retval;
2731 /***********************************************************************
2732 * gethostbyname (WS2_32.52)
2734 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2736 struct WS_hostent *retval = NULL;
2737 struct hostent* host;
2738 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2739 char *extrabuf;
2740 int ebufsize=1024;
2741 struct hostent hostentry;
2742 int locerr = ENOBUFS;
2743 #endif
2744 char buf[100];
2745 if( !name) {
2746 name = buf;
2747 if( gethostname( buf, 100) == -1) {
2748 SetLastError( WSAENOBUFS); /* appropriate ? */
2749 return retval;
2752 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2753 host = NULL;
2754 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2755 while(extrabuf) {
2756 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2757 if( res != ERANGE) break;
2758 ebufsize *=2;
2759 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2761 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2762 #else
2763 EnterCriticalSection( &csWSgetXXXbyYYY );
2764 host = gethostbyname(name);
2765 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2766 #endif
2767 if (host) retval = WS_dup_he(host);
2768 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2769 HeapFree(GetProcessHeap(),0,extrabuf);
2770 #else
2771 LeaveCriticalSection( &csWSgetXXXbyYYY );
2772 #endif
2773 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2774 return retval;
2778 /***********************************************************************
2779 * getprotobyname (WS2_32.53)
2781 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
2783 struct WS_protoent* retval = NULL;
2784 #ifdef HAVE_GETPROTOBYNAME
2785 struct protoent* proto;
2786 EnterCriticalSection( &csWSgetXXXbyYYY );
2787 if( (proto = getprotobyname(name)) != NULL )
2789 retval = WS_dup_pe(proto);
2791 else {
2792 MESSAGE("protocol %s not found; You might want to add "
2793 "this to /etc/protocols\n", debugstr_a(name) );
2794 SetLastError(WSANO_DATA);
2796 LeaveCriticalSection( &csWSgetXXXbyYYY );
2797 #endif
2798 TRACE( "%s ret %p\n", debugstr_a(name), retval );
2799 return retval;
2803 /***********************************************************************
2804 * getprotobynumber (WS2_32.54)
2806 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
2808 struct WS_protoent* retval = NULL;
2809 #ifdef HAVE_GETPROTOBYNUMBER
2810 struct protoent* proto;
2811 EnterCriticalSection( &csWSgetXXXbyYYY );
2812 if( (proto = getprotobynumber(number)) != NULL )
2814 retval = WS_dup_pe(proto);
2816 else {
2817 MESSAGE("protocol number %d not found; You might want to add "
2818 "this to /etc/protocols\n", number );
2819 SetLastError(WSANO_DATA);
2821 LeaveCriticalSection( &csWSgetXXXbyYYY );
2822 #endif
2823 TRACE("%i ret %p\n", number, retval);
2824 return retval;
2828 /***********************************************************************
2829 * getservbyname (WS2_32.55)
2831 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
2833 struct WS_servent* retval = NULL;
2834 struct servent* serv;
2835 char *name_str;
2836 char *proto_str = NULL;
2838 if (!(name_str = strdup_lower(name))) return NULL;
2840 if (proto && *proto)
2842 if (!(proto_str = strdup_lower(proto)))
2844 HeapFree( GetProcessHeap(), 0, name_str );
2845 return NULL;
2849 EnterCriticalSection( &csWSgetXXXbyYYY );
2850 serv = getservbyname(name_str, proto_str);
2851 if( serv != NULL )
2853 retval = WS_dup_se(serv);
2855 else SetLastError(WSANO_DATA);
2856 LeaveCriticalSection( &csWSgetXXXbyYYY );
2857 HeapFree( GetProcessHeap(), 0, proto_str );
2858 HeapFree( GetProcessHeap(), 0, name_str );
2859 TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
2860 return retval;
2864 /***********************************************************************
2865 * getservbyport (WS2_32.56)
2867 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
2869 struct WS_servent* retval = NULL;
2870 #ifdef HAVE_GETSERVBYPORT
2871 struct servent* serv;
2872 char *proto_str = NULL;
2874 if (proto && *proto)
2876 if (!(proto_str = strdup_lower(proto))) return NULL;
2878 EnterCriticalSection( &csWSgetXXXbyYYY );
2879 if( (serv = getservbyport(port, proto_str)) != NULL ) {
2880 retval = WS_dup_se(serv);
2882 else SetLastError(WSANO_DATA);
2883 LeaveCriticalSection( &csWSgetXXXbyYYY );
2884 HeapFree( GetProcessHeap(), 0, proto_str );
2885 #endif
2886 TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
2887 return retval;
2891 /***********************************************************************
2892 * gethostname (WS2_32.57)
2894 int WINAPI WS_gethostname(char *name, int namelen)
2896 TRACE("name %p, len %d\n", name, namelen);
2898 if (gethostname(name, namelen) == 0)
2900 TRACE("<- '%s'\n", name);
2901 return 0;
2903 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2904 TRACE("<- ERROR !\n");
2905 return SOCKET_ERROR;
2909 /* ------------------------------------- Windows sockets extensions -- *
2911 * ------------------------------------------------------------------- */
2913 /***********************************************************************
2914 * WSAEnumNetworkEvents (WS2_32.36)
2916 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2918 int ret;
2920 TRACE("%08x, hEvent %p, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2922 SERVER_START_REQ( get_socket_event )
2924 req->handle = SOCKET2HANDLE(s);
2925 req->service = TRUE;
2926 req->c_event = hEvent;
2927 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
2928 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
2930 SERVER_END_REQ;
2931 if (!ret) return 0;
2932 SetLastError(WSAEINVAL);
2933 return SOCKET_ERROR;
2936 /***********************************************************************
2937 * WSAEventSelect (WS2_32.39)
2939 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, long lEvent)
2941 int ret;
2943 TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
2945 SERVER_START_REQ( set_socket_event )
2947 req->handle = SOCKET2HANDLE(s);
2948 req->mask = lEvent;
2949 req->event = hEvent;
2950 req->window = 0;
2951 req->msg = 0;
2952 ret = wine_server_call( req );
2954 SERVER_END_REQ;
2955 if (!ret) return 0;
2956 SetLastError(WSAEINVAL);
2957 return SOCKET_ERROR;
2960 /**********************************************************************
2961 * WSAGetOverlappedResult (WS2_32.40)
2963 BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
2964 LPDWORD lpcbTransfer, BOOL fWait,
2965 LPDWORD lpdwFlags )
2967 DWORD r;
2969 TRACE( "socket %04x ovl %p trans %p, wait %d flags %p\n",
2970 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
2972 if ( lpOverlapped == NULL )
2974 ERR( "Invalid pointer\n" );
2975 WSASetLastError(WSA_INVALID_PARAMETER);
2976 return FALSE;
2979 if ( fWait )
2981 if (lpOverlapped->hEvent)
2982 while ( WaitForSingleObjectEx(lpOverlapped->hEvent,
2983 INFINITE, TRUE) == STATUS_USER_APC );
2984 else /* busy loop */
2985 while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING )
2986 Sleep( 10 );
2989 else if ( lpOverlapped->Internal == STATUS_PENDING )
2991 /* Wait in order to give APCs a chance to run. */
2992 /* This is cheating, so we must set the event again in case of success -
2993 it may be a non-manual reset event. */
2994 while ( (r = WaitForSingleObjectEx(lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
2995 if ( r == WAIT_OBJECT_0 && lpOverlapped->hEvent )
2996 NtSetEvent( lpOverlapped->hEvent, NULL );
2999 if ( lpcbTransfer )
3000 *lpcbTransfer = lpOverlapped->InternalHigh;
3002 if ( lpdwFlags )
3003 *lpdwFlags = lpOverlapped->u.s.Offset;
3005 switch ( lpOverlapped->Internal )
3007 case STATUS_SUCCESS:
3008 return TRUE;
3009 case STATUS_PENDING:
3010 WSASetLastError( WSA_IO_INCOMPLETE );
3011 if (fWait) ERR("PENDING status after waiting!\n");
3012 return FALSE;
3013 default:
3014 WSASetLastError( NtStatusToWSAError( lpOverlapped->Internal ));
3015 return FALSE;
3020 /***********************************************************************
3021 * WSAAsyncSelect (WS2_32.101)
3023 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, long lEvent)
3025 int ret;
3027 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3029 SERVER_START_REQ( set_socket_event )
3031 req->handle = SOCKET2HANDLE(s);
3032 req->mask = lEvent;
3033 req->event = 0;
3034 req->window = hWnd;
3035 req->msg = uMsg;
3036 ret = wine_server_call( req );
3038 SERVER_END_REQ;
3039 if (!ret) return 0;
3040 SetLastError(WSAEINVAL);
3041 return SOCKET_ERROR;
3044 /***********************************************************************
3045 * WSACreateEvent (WS2_32.31)
3048 WSAEVENT WINAPI WSACreateEvent(void)
3050 /* Create a manual-reset event, with initial state: unsignaled */
3051 TRACE("\n");
3053 return CreateEventW(NULL, TRUE, FALSE, NULL);
3056 /***********************************************************************
3057 * WSACloseEvent (WS2_32.29)
3060 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3062 TRACE ("event=%p\n", event);
3064 return CloseHandle(event);
3067 /***********************************************************************
3068 * WSASocketA (WS2_32.78)
3071 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3072 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3073 GROUP g, DWORD dwFlags)
3075 INT len;
3076 WSAPROTOCOL_INFOW info;
3078 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3079 af, type, protocol, lpProtocolInfo, g, dwFlags);
3081 if (!lpProtocolInfo) return WSASocketW(af, type, protocol, NULL, g, dwFlags);
3083 memcpy(&info, lpProtocolInfo, FIELD_OFFSET(WSAPROTOCOL_INFOW, szProtocol));
3084 len = MultiByteToWideChar(CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3085 info.szProtocol, WSAPROTOCOL_LEN * sizeof(WCHAR) + 1);
3087 if (!len)
3089 WSASetLastError( WSAEINVAL);
3090 return SOCKET_ERROR;
3093 return WSASocketW(af, type, protocol, &info, g, dwFlags);
3096 /***********************************************************************
3097 * WSASocketW (WS2_32.79)
3100 SOCKET WINAPI WSASocketW(int af, int type, int protocol,
3101 LPWSAPROTOCOL_INFOW lpProtocolInfo,
3102 GROUP g, DWORD dwFlags)
3104 SOCKET ret;
3107 FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
3108 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3111 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3112 af, type, protocol, lpProtocolInfo, g, dwFlags );
3114 /* hack for WSADuplicateSocket */
3115 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3116 ret = lpProtocolInfo->dwCatalogEntryId;
3117 TRACE("\tgot duplicate %04x\n", ret);
3118 return ret;
3121 /* check the socket family */
3122 switch(af)
3124 #ifdef HAVE_IPX
3125 case WS_AF_IPX: af = AF_IPX;
3126 #endif
3127 case AF_INET:
3128 case AF_UNSPEC:
3129 break;
3130 default:
3131 SetLastError(WSAEAFNOSUPPORT);
3132 return INVALID_SOCKET;
3135 /* check the socket type */
3136 switch(type)
3138 case WS_SOCK_STREAM:
3139 type=SOCK_STREAM;
3140 break;
3141 case WS_SOCK_DGRAM:
3142 type=SOCK_DGRAM;
3143 break;
3144 case WS_SOCK_RAW:
3145 type=SOCK_RAW;
3146 break;
3147 default:
3148 SetLastError(WSAESOCKTNOSUPPORT);
3149 return INVALID_SOCKET;
3152 /* check the protocol type */
3153 if ( protocol < 0 ) /* don't support negative values */
3155 SetLastError(WSAEPROTONOSUPPORT);
3156 return INVALID_SOCKET;
3159 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3160 switch(protocol)
3162 case IPPROTO_TCP:
3163 if (type == SOCK_STREAM) { af = AF_INET; break; }
3164 case IPPROTO_UDP:
3165 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3166 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3169 SERVER_START_REQ( create_socket )
3171 req->family = af;
3172 req->type = type;
3173 req->protocol = protocol;
3174 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3175 req->flags = dwFlags;
3176 req->inherit = TRUE;
3177 set_error( wine_server_call( req ) );
3178 ret = HANDLE2SOCKET( reply->handle );
3180 SERVER_END_REQ;
3181 if (ret)
3183 TRACE("\tcreated %04x\n", ret );
3184 return ret;
3187 if (GetLastError() == WSAEACCES) /* raw socket denied */
3189 if (type == SOCK_RAW)
3190 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3191 else
3192 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3193 SetLastError(WSAESOCKTNOSUPPORT);
3196 WARN("\t\tfailed!\n");
3197 return INVALID_SOCKET;
3200 /***********************************************************************
3201 * WSAJoinLeaf (WS2_32.58)
3204 SOCKET WINAPI WSAJoinLeaf(
3205 SOCKET s,
3206 const struct WS_sockaddr *addr,
3207 int addrlen,
3208 LPWSABUF lpCallerData,
3209 LPWSABUF lpCalleeData,
3210 LPQOS lpSQOS,
3211 LPQOS lpGQOS,
3212 DWORD dwFlags)
3214 FIXME("stub.\n");
3215 return INVALID_SOCKET;
3218 /***********************************************************************
3219 * __WSAFDIsSet (WS2_32.151)
3221 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3223 int i = set->fd_count;
3225 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3227 while (i--)
3228 if (set->fd_array[i] == s) return 1;
3229 return 0;
3232 /***********************************************************************
3233 * WSAIsBlocking (WINSOCK.114)
3234 * WSAIsBlocking (WS2_32.114)
3236 BOOL WINAPI WSAIsBlocking(void)
3238 /* By default WinSock should set all its sockets to non-blocking mode
3239 * and poll in PeekMessage loop when processing "blocking" ones. This
3240 * function is supposed to tell if the program is in this loop. Our
3241 * blocking calls are truly blocking so we always return FALSE.
3243 * Note: It is allowed to call this function without prior WSAStartup().
3246 TRACE("\n");
3247 return FALSE;
3250 /***********************************************************************
3251 * WSACancelBlockingCall (WINSOCK.113)
3252 * WSACancelBlockingCall (WS2_32.113)
3254 INT WINAPI WSACancelBlockingCall(void)
3256 TRACE("\n");
3257 return 0;
3260 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
3262 FIXME("How was this called?\n");
3263 return x();
3267 /***********************************************************************
3268 * WSASetBlockingHook (WS2_32.109)
3270 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3272 FARPROC prev = blocking_hook;
3273 blocking_hook = lpBlockFunc;
3274 TRACE("hook %p\n", lpBlockFunc);
3275 return prev;
3279 /***********************************************************************
3280 * WSAUnhookBlockingHook (WS2_32.110)
3282 INT WINAPI WSAUnhookBlockingHook(void)
3284 blocking_hook = WSA_DefaultBlockingHook;
3285 return 0;
3289 /* ----------------------------------- end of API stuff */
3291 /* ----------------------------------- helper functions -
3293 * TODO: Merge WS_dup_..() stuff into one function that
3294 * would operate with a generic structure containing internal
3295 * pointers (via a template of some kind).
3298 static int list_size(char** l, int item_size)
3300 int i,j = 0;
3301 if(l)
3302 { for(i=0;l[i];i++)
3303 j += (item_size) ? item_size : strlen(l[i]) + 1;
3304 j += (i + 1) * sizeof(char*); }
3305 return j;
3308 static int list_dup(char** l_src, char** l_to, int item_size)
3310 char *p;
3311 int i;
3313 for (i = 0; l_src[i]; i++) ;
3314 p = (char *)(l_to + i + 1);
3315 for (i = 0; l_src[i]; i++)
3317 int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3318 memcpy(p, l_src[i], count);
3319 l_to[i] = p;
3320 p += count;
3322 l_to[i] = NULL;
3323 return p - (char *)l_to;
3326 /* ----- hostent */
3328 /* duplicate hostent entry
3329 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3330 * Dito for protoent and servent.
3332 static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
3334 char *p;
3335 struct WS_hostent *p_to;
3337 int size = (sizeof(*p_he) +
3338 strlen(p_he->h_name) + 1 +
3339 list_size(p_he->h_aliases, 0) +
3340 list_size(p_he->h_addr_list, p_he->h_length));
3342 if (!(p_to = check_buffer_he(size))) return NULL;
3343 p_to->h_addrtype = p_he->h_addrtype;
3344 p_to->h_length = p_he->h_length;
3346 p = (char *)(p_to + 1);
3347 p_to->h_name = p;
3348 strcpy(p, p_he->h_name);
3349 p += strlen(p) + 1;
3351 p_to->h_aliases = (char **)p;
3352 p += list_dup(p_he->h_aliases, p_to->h_aliases, 0);
3354 p_to->h_addr_list = (char **)p;
3355 list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length);
3356 return p_to;
3359 /* ----- protoent */
3361 static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe)
3363 char *p;
3364 struct WS_protoent *p_to;
3366 int size = (sizeof(*p_pe) +
3367 strlen(p_pe->p_name) + 1 +
3368 list_size(p_pe->p_aliases, 0));
3370 if (!(p_to = check_buffer_pe(size))) return NULL;
3371 p_to->p_proto = p_pe->p_proto;
3373 p = (char *)(p_to + 1);
3374 p_to->p_name = p;
3375 strcpy(p, p_pe->p_name);
3376 p += strlen(p) + 1;
3378 p_to->p_aliases = (char **)p;
3379 list_dup(p_pe->p_aliases, p_to->p_aliases, 0);
3380 return p_to;
3383 /* ----- servent */
3385 static struct WS_servent *WS_dup_se(const struct servent* p_se)
3387 char *p;
3388 struct WS_servent *p_to;
3390 int size = (sizeof(*p_se) +
3391 strlen(p_se->s_proto) + 1 +
3392 strlen(p_se->s_name) + 1 +
3393 list_size(p_se->s_aliases, 0));
3395 if (!(p_to = check_buffer_se(size))) return NULL;
3396 p_to->s_port = p_se->s_port;
3398 p = (char *)(p_to + 1);
3399 p_to->s_name = p;
3400 strcpy(p, p_se->s_name);
3401 p += strlen(p) + 1;
3403 p_to->s_proto = p;
3404 strcpy(p, p_se->s_proto);
3405 p += strlen(p) + 1;
3407 p_to->s_aliases = (char **)p;
3408 list_dup(p_se->s_aliases, p_to->s_aliases, 0);
3409 return p_to;
3412 /* ----------------------------------- error handling */
3414 UINT wsaErrno(void)
3416 int loc_errno = errno;
3417 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3419 switch(loc_errno)
3421 case EINTR: return WSAEINTR;
3422 case EBADF: return WSAEBADF;
3423 case EPERM:
3424 case EACCES: return WSAEACCES;
3425 case EFAULT: return WSAEFAULT;
3426 case EINVAL: return WSAEINVAL;
3427 case EMFILE: return WSAEMFILE;
3428 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3429 case EINPROGRESS: return WSAEINPROGRESS;
3430 case EALREADY: return WSAEALREADY;
3431 case ENOTSOCK: return WSAENOTSOCK;
3432 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3433 case EMSGSIZE: return WSAEMSGSIZE;
3434 case EPROTOTYPE: return WSAEPROTOTYPE;
3435 case ENOPROTOOPT: return WSAENOPROTOOPT;
3436 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3437 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3438 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3439 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3440 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3441 case EADDRINUSE: return WSAEADDRINUSE;
3442 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3443 case ENETDOWN: return WSAENETDOWN;
3444 case ENETUNREACH: return WSAENETUNREACH;
3445 case ENETRESET: return WSAENETRESET;
3446 case ECONNABORTED: return WSAECONNABORTED;
3447 case EPIPE:
3448 case ECONNRESET: return WSAECONNRESET;
3449 case ENOBUFS: return WSAENOBUFS;
3450 case EISCONN: return WSAEISCONN;
3451 case ENOTCONN: return WSAENOTCONN;
3452 case ESHUTDOWN: return WSAESHUTDOWN;
3453 case ETOOMANYREFS: return WSAETOOMANYREFS;
3454 case ETIMEDOUT: return WSAETIMEDOUT;
3455 case ECONNREFUSED: return WSAECONNREFUSED;
3456 case ELOOP: return WSAELOOP;
3457 case ENAMETOOLONG: return WSAENAMETOOLONG;
3458 case EHOSTDOWN: return WSAEHOSTDOWN;
3459 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3460 case ENOTEMPTY: return WSAENOTEMPTY;
3461 #ifdef EPROCLIM
3462 case EPROCLIM: return WSAEPROCLIM;
3463 #endif
3464 #ifdef EUSERS
3465 case EUSERS: return WSAEUSERS;
3466 #endif
3467 #ifdef EDQUOT
3468 case EDQUOT: return WSAEDQUOT;
3469 #endif
3470 #ifdef ESTALE
3471 case ESTALE: return WSAESTALE;
3472 #endif
3473 #ifdef EREMOTE
3474 case EREMOTE: return WSAEREMOTE;
3475 #endif
3477 /* just in case we ever get here and there are no problems */
3478 case 0: return 0;
3479 default:
3480 WARN("Unknown errno %d!\n", loc_errno);
3481 return WSAEOPNOTSUPP;
3485 UINT wsaHerrno(int loc_errno)
3488 WARN("h_errno %d.\n", loc_errno);
3490 switch(loc_errno)
3492 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3493 case TRY_AGAIN: return WSATRY_AGAIN;
3494 case NO_RECOVERY: return WSANO_RECOVERY;
3495 case NO_DATA: return WSANO_DATA;
3496 case ENOBUFS: return WSAENOBUFS;
3498 case 0: return 0;
3499 default:
3500 WARN("Unknown h_errno %d!\n", loc_errno);
3501 return WSAEOPNOTSUPP;
3506 /***********************************************************************
3507 * WSARecv (WS2_32.67)
3509 int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3510 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3511 LPWSAOVERLAPPED lpOverlapped,
3512 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3514 return WSARecvFrom(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3515 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3518 /***********************************************************************
3519 * WSARecvFrom (WS2_32.69)
3521 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3522 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3523 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3524 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3527 unsigned int i;
3528 int n, fd, err = WSAENOTSOCK, flags, ret;
3529 struct iovec* iovec;
3530 struct ws2_async *wsa;
3531 IO_STATUS_BLOCK* iosb;
3533 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3534 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3535 (lpFromlen ? *lpFromlen : -1L),
3536 lpOverlapped, lpCompletionRoutine);
3538 fd = get_sock_fd( s, GENERIC_READ, &flags );
3539 TRACE( "fd=%d, flags=%x\n", fd, flags );
3541 if (fd == -1) return SOCKET_ERROR;
3543 if (flags & FD_FLAG_RECV_SHUTDOWN)
3545 WSASetLastError( WSAESHUTDOWN );
3546 goto err_close;
3549 iovec = HeapAlloc( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3550 if ( !iovec )
3552 err = WSAEFAULT;
3553 goto err_close;
3556 for (i = 0; i < dwBufferCount; i++)
3558 iovec[i].iov_base = lpBuffers[i].buf;
3559 iovec[i].iov_len = lpBuffers[i].len;
3562 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3564 wsa = WS2_make_async( s, fd, ws2m_read, iovec, dwBufferCount,
3565 lpFlags, lpFrom, lpFromlen,
3566 lpOverlapped, lpCompletionRoutine, &iosb );
3568 if ( !wsa )
3570 err = WSAEFAULT;
3571 goto err_free;
3574 if ( ( ret = ws2_queue_async( wsa, iosb )) )
3576 err = NtStatusToWSAError( ret );
3578 if ( !lpOverlapped )
3579 HeapFree( GetProcessHeap(), 0, iosb );
3580 HeapFree( GetProcessHeap(), 0, wsa );
3581 goto err_free;
3584 /* Try immediate completion */
3585 if ( lpOverlapped )
3587 if ( WSAGetOverlappedResult( s, lpOverlapped,
3588 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3589 return 0;
3591 if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
3592 goto error;
3595 WSASetLastError( WSA_IO_PENDING );
3596 return SOCKET_ERROR;
3599 if ( _is_blocking(s) )
3601 /* block here */
3602 /* FIXME: OOB and exceptfds? */
3603 int timeout = GET_RCVTIMEO(fd);
3604 if( !do_block(fd, POLLIN, timeout)) {
3605 err = WSAETIMEDOUT;
3606 /* a timeout is not fatal */
3607 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3608 goto err_free;
3612 n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3613 if ( n == -1 )
3615 err = wsaErrno();
3616 goto err_free;
3619 TRACE(" -> %i bytes\n", n);
3620 *lpNumberOfBytesRecvd = n;
3622 HeapFree(GetProcessHeap(), 0, iovec);
3623 release_sock_fd( s, fd );
3624 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3626 return 0;
3628 err_free:
3629 HeapFree(GetProcessHeap(), 0, iovec);
3631 err_close:
3632 release_sock_fd( s, fd );
3634 error:
3635 WARN(" -> ERROR %d\n", err);
3636 WSASetLastError( err );
3637 return SOCKET_ERROR;
3640 /***********************************************************************
3641 * WSCInstallProvider (WS2_32.88)
3643 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
3644 LPCWSTR lpszProviderDllPath,
3645 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
3646 DWORD dwNumberOfEntries,
3647 LPINT lpErrno )
3649 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
3650 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
3651 dwNumberOfEntries, lpErrno);
3652 *lpErrno = 0;
3653 return 0;
3657 /***********************************************************************
3658 * WSCDeinstallProvider (WS2_32.83)
3660 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
3662 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
3663 *lpErrno = 0;
3664 return 0;
3668 /***********************************************************************
3669 * WSAAccept (WS2_32.26)
3671 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
3672 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
3675 int ret = 0, size = 0;
3676 WSABUF CallerId, CallerData, CalleeId, CalleeData;
3677 /* QOS SQOS, GQOS; */
3678 GROUP g;
3679 SOCKET cs;
3680 SOCKADDR src_addr, dst_addr;
3682 TRACE("Socket %04x, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
3683 s, addr, addrlen, lpfnCondition, dwCallbackData);
3686 size = sizeof(src_addr);
3687 cs = WS_accept(s, &src_addr, &size);
3689 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
3691 CallerId.buf = (char *)&src_addr;
3692 CallerId.len = sizeof(src_addr);
3694 CallerData.buf = NULL;
3695 CallerData.len = (ULONG)NULL;
3697 WS_getsockname(cs, &dst_addr, &size);
3699 CalleeId.buf = (char *)&dst_addr;
3700 CalleeId.len = sizeof(dst_addr);
3703 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
3704 &CalleeId, &CalleeData, &g, dwCallbackData);
3706 switch (ret)
3708 case CF_ACCEPT:
3709 if (addr && addrlen)
3710 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
3711 return cs;
3712 case CF_DEFER:
3713 SERVER_START_REQ( set_socket_deferred )
3715 req->handle = SOCKET2HANDLE(s);
3716 req->deferred = SOCKET2HANDLE(cs);
3717 if ( !wine_server_call_err ( req ) )
3719 SetLastError( WSATRY_AGAIN );
3720 WS_closesocket( cs );
3723 SERVER_END_REQ;
3724 return SOCKET_ERROR;
3725 case CF_REJECT:
3726 WS_closesocket(cs);
3727 SetLastError(WSAECONNREFUSED);
3728 return SOCKET_ERROR;
3729 default:
3730 FIXME("Unknown return type from Condition function\n");
3731 SetLastError(WSAENOTSOCK);
3732 return SOCKET_ERROR;
3736 /***********************************************************************
3737 * WSADuplicateSocketA (WS2_32.32)
3739 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
3741 HANDLE hProcess;
3743 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3744 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3745 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
3746 /* I don't know what the real Windoze does next, this is a hack */
3747 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
3748 * the target use the global duplicate, or we could copy a reference to us to the structure
3749 * and let the target duplicate it from us, but let's do it as simple as possible */
3750 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3751 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3752 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3753 0, FALSE, DUPLICATE_SAME_ACCESS);
3754 CloseHandle(hProcess);
3755 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3756 return 0;
3759 /***********************************************************************
3760 * WSADuplicateSocketW (WS2_32.33)
3762 int WINAPI WSADuplicateSocketW( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo )
3764 HANDLE hProcess;
3766 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3768 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3769 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3770 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3771 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3772 0, FALSE, DUPLICATE_SAME_ACCESS);
3773 CloseHandle(hProcess);
3774 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3775 return 0;
3778 /***********************************************************************
3779 * WSAInstallServiceClassA (WS2_32.48)
3781 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
3783 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
3784 WSASetLastError(WSAEACCES);
3785 return SOCKET_ERROR;
3788 /***********************************************************************
3789 * WSAInstallServiceClassW (WS2_32.49)
3791 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
3793 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
3794 WSASetLastError(WSAEACCES);
3795 return SOCKET_ERROR;
3798 /***********************************************************************
3799 * WSARemoveServiceClass (WS2_32.70)
3801 int WINAPI WSARemoveServiceClass(LPGUID info)
3803 FIXME("Request to remove service %p\n",info);
3804 WSASetLastError(WSATYPE_NOT_FOUND);
3805 return SOCKET_ERROR;
3808 /***********************************************************************
3809 * WSAStringToAddressA (WS2_32.80)
3811 INT WINAPI WSAStringToAddressA(LPSTR AddressString,
3812 INT AddressFamily,
3813 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3814 LPSOCKADDR lpAddress,
3815 LPINT lpAddressLength)
3817 INT res=0;
3818 struct in_addr inetaddr;
3819 LPSTR workBuffer=NULL,ptrPort;
3821 TRACE( "(%s, %x, %p, %p, %p)\n", AddressString, AddressFamily, lpProtocolInfo,
3822 lpAddress, lpAddressLength );
3824 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
3826 if (AddressString)
3828 workBuffer = HeapAlloc( GetProcessHeap(), 0, strlen(AddressString)+1 );
3829 if (workBuffer)
3831 strcpy(workBuffer,AddressString);
3832 switch (AddressFamily)
3834 case AF_INET:
3835 /* caller wants to know the size of the socket buffer */
3836 if (*lpAddressLength < sizeof(SOCKADDR_IN))
3838 *lpAddressLength = sizeof(SOCKADDR_IN);
3839 res = WSAEFAULT;
3841 else
3843 /* caller wants to translate an AdressString into a SOCKADDR */
3844 if (lpAddress)
3846 memset(lpAddress,0,sizeof(SOCKADDR_IN));
3847 ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET;
3848 ptrPort = strchr(workBuffer,':');
3849 if (ptrPort)
3851 ((LPSOCKADDR_IN)lpAddress)->sin_port = (u_short)atoi(ptrPort+1);
3852 *ptrPort = '\0';
3854 else
3855 ((LPSOCKADDR_IN)lpAddress)->sin_port = 0;
3856 if (inet_aton(workBuffer, &inetaddr) > 0)
3858 ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr.s_addr;
3859 res = 0;
3861 else
3862 res = WSAEINVAL;
3865 if (lpProtocolInfo)
3866 FIXME("(%s, %x, %p, %p, %p) - ProtocolInfo not implemented!\n",
3867 AddressString, AddressFamily,
3868 lpProtocolInfo, lpAddress, lpAddressLength);
3870 break;
3871 default:
3872 FIXME("(%s, %x, %p, %p, %p) - AddressFamiliy not implemented!\n",
3873 AddressString, AddressFamily,
3874 lpProtocolInfo, lpAddress, lpAddressLength);
3876 HeapFree( GetProcessHeap(), 0, workBuffer );
3878 else
3879 res = WSA_NOT_ENOUGH_MEMORY;
3881 else
3882 res = WSAEINVAL;
3884 if (!res) return 0;
3885 WSASetLastError(res);
3886 return SOCKET_ERROR;
3889 /***********************************************************************
3890 * WSAStringToAddressW (WS2_32.81)
3892 * Does anybody know if this functions allows to use hebrew/arabic/chinese... digits?
3893 * If this should be the case, it would be required to map these digits
3894 * to Unicode digits (0-9) using FoldString first.
3896 INT WINAPI WSAStringToAddressW(LPWSTR AddressString,
3897 INT AddressFamily,
3898 LPWSAPROTOCOL_INFOW lpProtocolInfo,
3899 LPSOCKADDR lpAddress,
3900 LPINT lpAddressLength)
3902 INT sBuffer,res=0;
3903 LPSTR workBuffer=NULL;
3904 WSAPROTOCOL_INFOA infoA;
3905 LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL;
3907 TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_w(AddressString), AddressFamily, lpProtocolInfo,
3908 lpAddress, lpAddressLength );
3910 if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
3912 /* if ProtocolInfo is available - convert to ANSI variant */
3913 if (lpProtocolInfo)
3915 lpProtoInfoA = &infoA;
3916 memcpy( lpProtoInfoA, lpProtocolInfo, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
3918 if (!WideCharToMultiByte( CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3919 lpProtoInfoA->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL ))
3921 WSASetLastError( WSAEINVAL);
3922 return SOCKET_ERROR;
3926 if (AddressString)
3928 /* Translate AddressString to ANSI code page - assumes that only
3929 standard digits 0-9 are used with this API call */
3930 sBuffer = WideCharToMultiByte( CP_ACP, 0, AddressString, -1, NULL, 0, NULL, NULL );
3931 workBuffer = HeapAlloc( GetProcessHeap(), 0, sBuffer );
3933 if (workBuffer)
3935 WideCharToMultiByte( CP_ACP, 0, AddressString, -1, workBuffer, sBuffer, NULL, NULL );
3936 res = WSAStringToAddressA(workBuffer,AddressFamily,lpProtoInfoA,
3937 lpAddress,lpAddressLength);
3938 HeapFree( GetProcessHeap(), 0, workBuffer );
3939 return res;
3941 else
3942 res = WSA_NOT_ENOUGH_MEMORY;
3944 else
3945 res = WSAEINVAL;
3947 WSASetLastError(res);
3948 return SOCKET_ERROR;
3951 /***********************************************************************
3952 * WSAAddressToStringA (WS2_32.27)
3954 * See WSAAddressToStringW
3956 INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len,
3957 LPWSAPROTOCOL_INFOA info, LPSTR string,
3958 LPDWORD lenstr )
3960 INT size;
3961 CHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
3962 CHAR *p;
3964 TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
3966 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
3967 if (!string || !lenstr) return SOCKET_ERROR;
3969 /* sin_family is garanteed to be the first u_short */
3970 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
3972 sprintf( buffer, "%u.%u.%u.%u:%u",
3973 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
3974 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
3975 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
3976 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
3977 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
3979 p = strchr( buffer, ':' );
3980 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
3982 size = strlen( buffer );
3984 if (*lenstr < size)
3986 *lenstr = size;
3987 return SOCKET_ERROR;
3990 strcpy( string, buffer );
3991 return 0;
3994 /***********************************************************************
3995 * WSAAddressToStringW (WS2_32.28)
3997 * Convert a sockaddr address into a readable address string.
3999 * PARAMS
4000 * sockaddr [I] Pointer to a sockaddr structure.
4001 * len [I] Size of the sockaddr structure.
4002 * info [I] Pointer to a WSAPROTOCOL_INFOW structure (optional).
4003 * string [I/O] Pointer to a buffer to receive the address string.
4004 * lenstr [I/O] Size of the receive buffer in WCHARs.
4006 * RETURNS
4007 * Success: 0
4008 * Failure: SOCKET_ERROR
4010 * NOTES
4011 * The 'info' parameter is ignored.
4013 * BUGS
4014 * Only supports AF_INET addresses.
4016 INT WINAPI WSAAddressToStringW( LPSOCKADDR sockaddr, DWORD len,
4017 LPWSAPROTOCOL_INFOW info, LPWSTR string,
4018 LPDWORD lenstr )
4020 INT size;
4021 WCHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
4022 static const WCHAR format[] = { '%','u','.','%','u','.','%','u','.','%','u',':','%','u',0 };
4023 WCHAR *p;
4025 TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
4027 if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
4028 if (!string || !lenstr) return SOCKET_ERROR;
4030 /* sin_family is garanteed to be the first u_short */
4031 if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
4033 sprintfW( buffer, format,
4034 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
4035 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
4036 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
4037 (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
4038 ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
4040 p = strchrW( buffer, ':' );
4041 if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
4043 size = lstrlenW( buffer );
4045 if (*lenstr < size)
4047 *lenstr = size;
4048 return SOCKET_ERROR;
4051 lstrcpyW( string, buffer );
4052 return 0;
4055 /***********************************************************************
4056 * WSAEnumNameSpaceProvidersA (WS2_32.34)
4058 INT WINAPI WSAEnumNameSpaceProvidersA( LPDWORD len, LPWSANAMESPACE_INFOA buffer )
4060 FIXME( "(%p %p) Stub!\n", len, buffer );
4061 return 0;
4064 /***********************************************************************
4065 * WSAEnumNameSpaceProvidersW (WS2_32.35)
4067 INT WINAPI WSAEnumNameSpaceProvidersW( LPDWORD len, LPWSANAMESPACE_INFOW buffer )
4069 FIXME( "(%p %p) Stub!\n", len, buffer );
4070 return 0;
4073 /***********************************************************************
4074 * WSAGetQOSByName (WS2_32.41)
4076 BOOL WINAPI WSAGetQOSByName( SOCKET s, LPWSABUF lpQOSName, LPQOS lpQOS )
4078 FIXME( "(0x%04x %p %p) Stub!\n", s, lpQOSName, lpQOS );
4079 return FALSE;
4082 /***********************************************************************
4083 * WSAGetServiceClassInfoA (WS2_32.42)
4085 INT WINAPI WSAGetServiceClassInfoA( LPGUID provider, LPGUID service, LPDWORD len,
4086 LPWSASERVICECLASSINFOA info )
4088 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4089 len, info );
4090 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4091 return SOCKET_ERROR;
4094 /***********************************************************************
4095 * WSAGetServiceClassInfoW (WS2_32.43)
4097 INT WINAPI WSAGetServiceClassInfoW( LPGUID provider, LPGUID service, LPDWORD len,
4098 LPWSASERVICECLASSINFOW info )
4100 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4101 len, info );
4102 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4103 return SOCKET_ERROR;
4106 /***********************************************************************
4107 * WSAGetServiceClassNameByClassIdA (WS2_32.44)
4109 INT WINAPI WSAGetServiceClassNameByClassIdA( LPGUID class, LPSTR service, LPDWORD len )
4111 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4112 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4113 return SOCKET_ERROR;
4116 /***********************************************************************
4117 * WSAGetServiceClassNameByClassIdW (WS2_32.45)
4119 INT WINAPI WSAGetServiceClassNameByClassIdW( LPGUID class, LPWSTR service, LPDWORD len )
4121 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4122 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4123 return SOCKET_ERROR;
4126 /***********************************************************************
4127 * WSALookupServiceBeginA (WS2_32.59)
4129 INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
4130 DWORD dwControlFlags,
4131 LPHANDLE lphLookup)
4133 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4134 lphLookup);
4135 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4136 return SOCKET_ERROR;
4139 /***********************************************************************
4140 * WSALookupServiceBeginW (WS2_32.60)
4142 INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
4143 DWORD dwControlFlags,
4144 LPHANDLE lphLookup)
4146 FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4147 lphLookup);
4148 WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4149 return SOCKET_ERROR;
4152 /***********************************************************************
4153 * WSALookupServiceBeginW (WS2_32.61)
4155 INT WINAPI WSALookupServiceEnd( HANDLE lookup )
4157 FIXME("(%p) Stub!\n", lookup );
4158 return 0;
4161 /***********************************************************************
4162 * WSALookupServiceNextA (WS2_32.62)
4164 INT WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETA results )
4166 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4167 return 0;
4170 /***********************************************************************
4171 * WSALookupServiceNextW (WS2_32.63)
4173 INT WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETW results )
4175 FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4176 return 0;
4179 /***********************************************************************
4180 * WSANtohl (WS2_32.64)
4182 INT WINAPI WSANtohl( SOCKET s, u_long netlong, u_long* lphostlong )
4184 TRACE( "(0x%04x 0x%08lx %p)\n", s, netlong, lphostlong );
4186 if (!lphostlong) return WSAEFAULT;
4188 *lphostlong = ntohl( netlong );
4189 return 0;
4192 /***********************************************************************
4193 * WSANtohs (WS2_32.65)
4195 INT WINAPI WSANtohs( SOCKET s, u_short netshort, u_short* lphostshort )
4197 TRACE( "(0x%04x 0x%08x %p)\n", s, netshort, lphostshort );
4199 if (!lphostshort) return WSAEFAULT;
4201 *lphostshort = ntohs( netshort );
4202 return 0;
4205 /***********************************************************************
4206 * WSAProviderConfigChange (WS2_32.66)
4208 INT WINAPI WSAProviderConfigChange( LPHANDLE handle, LPWSAOVERLAPPED overlapped,
4209 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
4211 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
4212 return SOCKET_ERROR;
4215 /***********************************************************************
4216 * WSARecvDisconnect (WS2_32.68)
4218 INT WINAPI WSARecvDisconnect( SOCKET s, LPWSABUF disconnectdata )
4220 TRACE( "(0x%04x %p)\n", s, disconnectdata );
4222 return WS_shutdown( s, 0 );
4225 /***********************************************************************
4226 * WSASetServiceA (WS2_32.76)
4228 INT WINAPI WSASetServiceA( LPWSAQUERYSETA query, WSAESETSERVICEOP operation, DWORD flags )
4230 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4231 return 0;
4234 /***********************************************************************
4235 * WSASetServiceW (WS2_32.77)
4237 INT WINAPI WSASetServiceW( LPWSAQUERYSETW query, WSAESETSERVICEOP operation, DWORD flags )
4239 FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4240 return 0;
4243 /***********************************************************************
4244 * WSCEnableNSProvider (WS2_32.84)
4246 INT WINAPI WSCEnableNSProvider( LPGUID provider, BOOL enable )
4248 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
4249 return 0;
4252 /***********************************************************************
4253 * WSCGetProviderPath (WS2_32.86)
4255 INT WINAPI WSCGetProviderPath( LPGUID provider, LPWSTR path, LPINT len, LPINT errcode )
4257 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errcode );
4259 if (!errcode || !provider || !len) return WSAEFAULT;
4261 *errcode = WSAEINVAL;
4262 return SOCKET_ERROR;
4265 /***********************************************************************
4266 * WSCInstallNameSpace (WS2_32.87)
4268 INT WINAPI WSCInstallNameSpace( LPWSTR identifier, LPWSTR path, DWORD namespace,
4269 DWORD version, LPGUID provider )
4271 FIXME( "(%s %s 0x%08lx 0x%08lx %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
4272 namespace, version, debugstr_guid(provider) );
4273 return 0;
4276 /***********************************************************************
4277 * WSCUnInstallNameSpace (WS2_32.89)
4279 INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
4281 FIXME("(%p) Stub!\n", lpProviderId);
4282 return NO_ERROR;
4285 /***********************************************************************
4286 * WSCWriteProviderOrder (WS2_32.91)
4288 INT WINAPI WSCWriteProviderOrder( LPDWORD entry, DWORD number )
4290 FIXME("(%p 0x%08lx) Stub!\n", entry, number);
4291 return 0;