- made async.h ready for use in ntdll: replaced all calls to kernel32
[wine/wine64.git] / dlls / winsock / socket.c
blob38dfd8728278bf60727a8cfbcbc47b1a3dbeb166
1 /*
2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
5 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * NOTE: If you make any changes to fix a particular app, make sure
22 * they don't break something else like Netscape or telnet and ftp
23 * clients and servers (www.winsite.com got a lot of those).
26 #include "config.h"
27 #include "wine/port.h"
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #ifdef HAVE_SYS_IPC_H
33 # include <sys/ipc.h>
34 #endif
35 #ifdef HAVE_SYS_IOCTL_H
36 # include <sys/ioctl.h>
37 #endif
38 #ifdef HAVE_SYS_FILIO_H
39 # include <sys/filio.h>
40 #endif
41 #ifdef HAVE_SYS_SOCKIO_H
42 # include <sys/sockio.h>
43 #endif
45 #if defined(__EMX__)
46 # include <sys/so_ioctl.h>
47 #endif
49 #ifdef HAVE_SYS_PARAM_H
50 # include <sys/param.h>
51 #endif
53 #ifdef HAVE_SYS_MSG_H
54 # include <sys/msg.h>
55 #endif
56 #ifdef HAVE_SYS_WAIT_H
57 # include <sys/wait.h>
58 #endif
59 #ifdef HAVE_SYS_UIO_H
60 # include <sys/uio.h>
61 #endif
62 #ifdef HAVE_SYS_SOCKET_H
63 #include <sys/socket.h>
64 #endif
65 #ifdef HAVE_NETINET_IN_H
66 # include <netinet/in.h>
67 #endif
68 #ifdef HAVE_NETINET_TCP_H
69 # include <netinet/tcp.h>
70 #endif
71 #ifdef HAVE_ARPA_INET_H
72 # include <arpa/inet.h>
73 #endif
74 #include <ctype.h>
75 #include <fcntl.h>
76 #include <errno.h>
77 #ifdef HAVE_SYS_ERRNO_H
78 #include <sys/errno.h>
79 #endif
80 #ifdef HAVE_NETDB_H
81 #include <netdb.h>
82 #endif
83 #ifdef HAVE_UNISTD_H
84 # include <unistd.h>
85 #endif
86 #include <stdlib.h>
87 #ifdef HAVE_ARPA_NAMESER_H
88 # include <arpa/nameser.h>
89 #endif
90 #ifdef HAVE_RESOLV_H
91 # include <resolv.h>
92 #endif
93 #ifdef HAVE_NET_IF_H
94 # include <net/if.h>
95 #endif
96 #ifdef HAVE_IPX_GNU
97 # include <netipx/ipx.h>
98 # define HAVE_IPX
99 #endif
100 #ifdef HAVE_IPX_LINUX
101 # include <asm/types.h>
102 # include <linux/ipx.h>
103 # define HAVE_IPX
104 #endif
106 #ifdef HAVE_SYS_TIME_H
107 # include <sys/time.h>
108 #endif
110 #define NONAMELESSUNION
111 #define NONAMELESSSTRUCT
112 #include "wine/winbase16.h"
113 #include "wingdi.h"
114 #include "winuser.h"
115 #include "winerror.h"
116 #include "winsock2.h"
117 #include "ws2tcpip.h"
118 #include "wsipx.h"
119 #include "wine/winsock16.h"
120 #include "winnt.h"
121 #include "wownt32.h"
122 #include "iphlpapi.h"
123 #include "wine/server.h"
124 #include "wine/debug.h"
126 #ifdef __FreeBSD__
127 # define sipx_network sipx_addr.x_net
128 # define sipx_node sipx_addr.x_host.c_host
129 #endif /* __FreeBSD__ */
131 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
133 /* critical section to protect some non-rentrant net function */
134 extern CRITICAL_SECTION csWSgetXXXbyYYY;
136 #define DEBUG_SOCKADDR 0
137 #define dump_sockaddr(a) \
138 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
139 ((struct sockaddr_in *)a)->sin_family, \
140 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
141 ntohs(((struct sockaddr_in *)a)->sin_port))
143 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
144 #define SOCKET2HANDLE(s) ((HANDLE)(s))
145 #define HANDLE2SOCKET(h) ((SOCKET)(h))
147 /****************************************************************
148 * Async IO declarations
149 ****************************************************************/
150 #include "async.h"
152 static DWORD ws2_async_get_count (const struct async_private *ovp);
153 static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
154 static void ws2_async_cleanup ( struct async_private *ovp );
156 static struct async_ops ws2_async_ops =
158 ws2_async_get_count,
159 ws2_async_call_completion,
160 ws2_async_cleanup
163 static struct async_ops ws2_nocomp_async_ops =
165 ws2_async_get_count,
166 NULL, /* call_completion */
167 ws2_async_cleanup
170 typedef struct ws2_async
172 async_private async;
173 LPWSAOVERLAPPED user_overlapped;
174 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
175 struct iovec *iovec;
176 int n_iovecs;
177 struct WS_sockaddr *addr;
178 union {
179 int val; /* for send operations */
180 int *ptr; /* for recv operations */
181 } addrlen;
182 DWORD flags;
183 } ws2_async;
185 /****************************************************************/
187 /* ----------------------------------- internal data */
189 /* ws_... struct conversion flags */
191 #define WS_DUP_LINEAR 0x0001
192 #define WS_DUP_SEGPTR 0x0002 /* internal pointers are SEGPTRs */
193 /* by default, internal pointers are linear */
194 typedef struct /* WSAAsyncSelect() control struct */
196 HANDLE service, event, sock;
197 HWND hWnd;
198 UINT uMsg;
199 LONG lEvent;
200 } ws_select_info;
202 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
203 #define WS_MAX_UDP_DATAGRAM 1024
205 static void *he_buffer; /* typecast for Win16/32 ws_hostent */
206 static SEGPTR he_buffer_seg;
207 static void *se_buffer; /* typecast for Win16/32 ws_servent */
208 static SEGPTR se_buffer_seg;
209 static void *pe_buffer; /* typecast for Win16/32 ws_protoent */
210 static SEGPTR pe_buffer_seg;
211 static char* local_buffer;
212 static SEGPTR dbuffer_seg;
213 static INT num_startup; /* reference counter */
214 static FARPROC blocking_hook;
216 /* function prototypes */
217 static int WS_dup_he(struct hostent* p_he, int flag);
218 static int WS_dup_pe(struct protoent* p_pe, int flag);
219 static int WS_dup_se(struct servent* p_se, int flag);
221 typedef void WIN_hostent;
222 typedef void WIN_protoent;
223 typedef void WIN_servent;
225 int WSAIOCTL_GetInterfaceCount(void);
226 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
228 UINT16 wsaErrno(void);
229 UINT16 wsaHerrno(int errnr);
231 static HANDLE _WSHeap = 0;
233 #define WS_ALLOC(size) \
234 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
235 #define WS_FREE(ptr) \
236 HeapFree(_WSHeap, 0, (ptr) )
238 #define MAP_OPTION(opt) { WS_##opt, opt }
240 static const int ws_sock_map[][2] =
242 MAP_OPTION( SO_DEBUG ),
243 MAP_OPTION( SO_REUSEADDR ),
244 MAP_OPTION( SO_KEEPALIVE ),
245 MAP_OPTION( SO_DONTROUTE ),
246 MAP_OPTION( SO_BROADCAST ),
247 MAP_OPTION( SO_LINGER ),
248 MAP_OPTION( SO_OOBINLINE ),
249 MAP_OPTION( SO_SNDBUF ),
250 MAP_OPTION( SO_RCVBUF ),
251 MAP_OPTION( SO_ERROR ),
252 MAP_OPTION( SO_TYPE ),
253 #ifdef SO_RCVTIMEO
254 MAP_OPTION( SO_RCVTIMEO ),
255 #endif
256 #ifdef SO_SNDTIMEO
257 MAP_OPTION( SO_SNDTIMEO ),
258 #endif
259 { 0, 0 }
262 static const int ws_tcp_map[][2] =
264 #ifdef TCP_NODELAY
265 MAP_OPTION( TCP_NODELAY ),
266 #endif
267 { 0, 0 }
270 static const int ws_ip_map[][2] =
272 MAP_OPTION( IP_MULTICAST_IF ),
273 MAP_OPTION( IP_MULTICAST_TTL ),
274 MAP_OPTION( IP_MULTICAST_LOOP ),
275 MAP_OPTION( IP_ADD_MEMBERSHIP ),
276 MAP_OPTION( IP_DROP_MEMBERSHIP ),
277 MAP_OPTION( IP_OPTIONS ),
278 MAP_OPTION( IP_HDRINCL ),
279 MAP_OPTION( IP_TOS ),
280 MAP_OPTION( IP_TTL ),
281 { 0, 0 }
284 static DWORD opentype_tls_index = -1; /* TLS index for SO_OPENTYPE flag */
286 inline static DWORD NtStatusToWSAError ( const DWORD status )
288 /* We only need to cover the status codes set by server async request handling */
289 DWORD wserr;
290 switch ( status )
292 case STATUS_SUCCESS: wserr = 0; break;
293 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
294 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
295 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
296 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
297 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
298 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
299 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
300 default:
301 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
302 /* It is not a NT status code but a winsock error */
303 wserr = status;
304 else
306 wserr = RtlNtStatusToDosError( status );
307 FIXME ( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
310 return wserr;
313 /* set last error code from NT status without mapping WSA errors */
314 inline static unsigned int set_error( unsigned int err )
316 if (err)
318 err = NtStatusToWSAError ( err );
319 SetLastError( err );
321 return err;
324 static char* check_buffer(int size);
326 inline static int _get_sock_fd(SOCKET s)
328 int fd;
330 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), GENERIC_READ, &fd, NULL, NULL ) ))
331 return -1;
332 return fd;
335 inline static int _get_sock_fd_type( SOCKET s, DWORD access, enum fd_type *type, int *flags )
337 int fd;
338 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, type, flags ) )) return -1;
339 if ( ( (access & GENERIC_READ) && (*flags & FD_FLAG_RECV_SHUTDOWN ) ) ||
340 ( (access & GENERIC_WRITE) && (*flags & FD_FLAG_SEND_SHUTDOWN ) ) )
342 close (fd);
343 WSASetLastError ( WSAESHUTDOWN );
344 return -1;
346 return fd;
349 static void _enable_event( HANDLE s, unsigned int event,
350 unsigned int sstate, unsigned int cstate )
352 SERVER_START_REQ( enable_socket_event )
354 req->handle = s;
355 req->mask = event;
356 req->sstate = sstate;
357 req->cstate = cstate;
358 wine_server_call( req );
360 SERVER_END_REQ;
363 static int _is_blocking(SOCKET s)
365 int ret;
366 SERVER_START_REQ( get_socket_event )
368 req->handle = SOCKET2HANDLE(s);
369 req->service = FALSE;
370 req->c_event = 0;
371 wine_server_call( req );
372 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
374 SERVER_END_REQ;
375 return ret;
378 static unsigned int _get_sock_mask(SOCKET s)
380 unsigned int ret;
381 SERVER_START_REQ( get_socket_event )
383 req->handle = SOCKET2HANDLE(s);
384 req->service = FALSE;
385 req->c_event = 0;
386 wine_server_call( req );
387 ret = reply->mask;
389 SERVER_END_REQ;
390 return ret;
393 static void _sync_sock_state(SOCKET s)
395 /* do a dummy wineserver request in order to let
396 the wineserver run through its select loop once */
397 (void)_is_blocking(s);
400 static int _get_sock_error(SOCKET s, unsigned int bit)
402 int events[FD_MAX_EVENTS];
404 SERVER_START_REQ( get_socket_event )
406 req->handle = SOCKET2HANDLE(s);
407 req->service = FALSE;
408 req->c_event = 0;
409 wine_server_set_reply( req, events, sizeof(events) );
410 wine_server_call( req );
412 SERVER_END_REQ;
413 return events[bit];
416 static void WINSOCK_DeleteIData(void)
418 /* delete scratch buffers */
420 UnMapLS( he_buffer_seg );
421 UnMapLS( se_buffer_seg );
422 UnMapLS( pe_buffer_seg );
423 UnMapLS( dbuffer_seg );
424 if (he_buffer) HeapFree( GetProcessHeap(), 0, he_buffer );
425 if (se_buffer) HeapFree( GetProcessHeap(), 0, se_buffer );
426 if (pe_buffer) HeapFree( GetProcessHeap(), 0, pe_buffer );
427 if (local_buffer) HeapFree( GetProcessHeap(), 0, local_buffer );
428 he_buffer = NULL;
429 se_buffer = NULL;
430 pe_buffer = NULL;
431 local_buffer = NULL;
432 he_buffer_seg = 0;
433 se_buffer_seg = 0;
434 pe_buffer_seg = 0;
435 dbuffer_seg = 0;
436 num_startup = 0;
439 /***********************************************************************
440 * DllMain (WS2_32.init)
442 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
444 TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
445 switch (fdwReason) {
446 case DLL_PROCESS_ATTACH:
447 opentype_tls_index = TlsAlloc();
448 break;
449 case DLL_PROCESS_DETACH:
450 TlsFree( opentype_tls_index );
451 WINSOCK_DeleteIData();
452 break;
454 return TRUE;
457 /***********************************************************************
458 * convert_sockopt()
460 * Converts socket flags from Windows format.
461 * Return 1 if converted, 0 if not (error).
463 static int convert_sockopt(INT *level, INT *optname)
465 int i;
466 switch (*level)
468 case WS_SOL_SOCKET:
469 *level = SOL_SOCKET;
470 for(i=0; ws_sock_map[i][0]; i++)
472 if( ws_sock_map[i][0] == *optname )
474 *optname = ws_sock_map[i][1];
475 return 1;
478 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
479 break;
480 case WS_IPPROTO_TCP:
481 *level = IPPROTO_TCP;
482 for(i=0; ws_tcp_map[i][0]; i++)
484 if ( ws_tcp_map[i][0] == *optname )
486 *optname = ws_tcp_map[i][1];
487 return 1;
490 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
491 break;
492 case WS_IPPROTO_IP:
493 *level = IPPROTO_IP;
494 for(i=0; ws_ip_map[i][0]; i++)
496 if (ws_ip_map[i][0] == *optname )
498 *optname = ws_ip_map[i][1];
499 return 1;
502 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
503 break;
504 default: FIXME("Unimplemented or unknown socket level\n");
506 return 0;
509 /* ----------------------------------- Per-thread info (or per-process?) */
511 static int wsi_strtolo(const char* name, const char* opt)
513 /* Stuff a lowercase copy of the string into the local buffer */
515 int i = strlen(name) + 2;
516 char* p = check_buffer(i + ((opt)?strlen(opt):0));
518 if( p )
520 do *p++ = tolower(*name); while(*name++);
521 i = (p - local_buffer);
522 if( opt ) do *p++ = tolower(*opt); while(*opt++);
523 return i;
525 return 0;
528 static fd_set* fd_set_import( fd_set* fds, void* wsfds, int* highfd, int lfd[], BOOL b32 )
530 /* translate Winsock fd set into local fd set */
532 if( wsfds )
534 #define wsfds16 ((ws_fd_set16*)wsfds)
535 #define wsfds32 ((WS_fd_set*)wsfds)
536 int i, count;
538 FD_ZERO(fds);
539 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
541 for( i = 0; i < count; i++ )
543 int s = (b32) ? wsfds32->fd_array[i]
544 : wsfds16->fd_array[i];
545 int fd = _get_sock_fd(s);
546 if (fd != -1)
548 lfd[ i ] = fd;
549 if( fd > *highfd ) *highfd = fd;
550 FD_SET(fd, fds);
552 else lfd[ i ] = -1;
554 #undef wsfds32
555 #undef wsfds16
556 return fds;
558 return NULL;
561 inline static int sock_error_p(int s)
563 unsigned int optval, optlen;
565 optlen = sizeof(optval);
566 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
567 if (optval) WARN("\t[%i] error: %d\n", s, optval);
568 return optval != 0;
571 static int fd_set_export( fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
573 int num_err = 0;
575 /* translate local fd set into Winsock fd set, adding
576 * errors to exceptfds (only if app requested it) */
578 if( wsfds )
580 #define wsfds16 ((ws_fd_set16*)wsfds)
581 #define wsfds32 ((WS_fd_set*)wsfds)
582 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
584 for( i = 0, j = 0; i < count; i++ )
586 if( lfd[i] >= 0 )
588 int fd = lfd[i];
589 if( FD_ISSET(fd, fds) )
591 if ( exceptfds && sock_error_p(fd) )
593 FD_SET(fd, exceptfds);
594 num_err++;
596 else if( b32 )
597 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
598 else
599 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
601 close(fd);
602 lfd[i] = -1;
606 if( b32 ) wsfds32->fd_count = j;
607 else wsfds16->fd_count = j;
609 TRACE("\n");
610 #undef wsfds32
611 #undef wsfds16
613 return num_err;
616 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
618 if ( wsfds )
620 #define wsfds16 ((ws_fd_set16*)wsfds)
621 #define wsfds32 ((WS_fd_set*)wsfds)
622 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
624 for( i = 0; i < count; i++ )
625 if ( lfd[i] >= 0 )
626 close(lfd[i]);
628 TRACE("\n");
629 #undef wsfds32
630 #undef wsfds16
634 static int do_block( int fd, int mask )
636 fd_set fds[3];
637 int i, r;
639 FD_ZERO(&fds[0]);
640 FD_ZERO(&fds[1]);
641 FD_ZERO(&fds[2]);
642 for (i=0; i<3; i++)
643 if (mask & (1<<i))
644 FD_SET(fd, &fds[i]);
645 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
646 if (i <= 0) return -1;
647 r = 0;
648 for (i=0; i<3; i++)
649 if (FD_ISSET(fd, &fds[i]))
650 r |= 1<<i;
651 return r;
654 void* __ws_memalloc( int size )
656 return WS_ALLOC(size);
659 void __ws_memfree(void* ptr)
661 WS_FREE(ptr);
665 /* ----------------------------------- API -----
667 * Init / cleanup / error checking.
670 /***********************************************************************
671 * WSAStartup (WINSOCK.115)
673 * Create socket control struct, attach it to the global list and
674 * update a pointer in the task struct.
676 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA16 lpWSAData)
678 static const WSADATA16 data =
680 0x0101, 0x0101,
681 "WINE Sockets 1.1",
682 #ifdef linux
683 "Linux/i386",
684 #elif defined(__NetBSD__)
685 "NetBSD/i386",
686 #elif defined(sunos)
687 "SunOS",
688 #elif defined(__FreeBSD__)
689 "FreeBSD",
690 #elif defined(__OpenBSD__)
691 "OpenBSD/i386",
692 #else
693 "Unknown",
694 #endif
695 WS_MAX_SOCKETS_PER_PROCESS,
696 WS_MAX_UDP_DATAGRAM,
700 TRACE("verReq=%x\n", wVersionRequested);
702 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
703 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
705 if (!lpWSAData) return WSAEINVAL;
707 /* initialize socket heap */
709 if( !_WSHeap )
711 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
712 if( !_WSHeap )
714 ERR("Fatal: failed to create WinSock heap\n");
715 return 0;
718 if( _WSHeap == 0 ) return WSASYSNOTREADY;
720 num_startup++;
722 /* return winsock information */
724 memcpy(lpWSAData, &data, sizeof(data));
726 TRACE("succeeded\n");
727 return 0;
730 /***********************************************************************
731 * WSAStartup (WS2_32.115)
733 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
735 TRACE("verReq=%x\n", wVersionRequested);
737 if (LOBYTE(wVersionRequested) < 1)
738 return WSAVERNOTSUPPORTED;
740 if (!lpWSAData) return WSAEINVAL;
742 /* initialize socket heap */
744 if( !_WSHeap )
746 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
747 if( !_WSHeap )
749 ERR("Fatal: failed to create WinSock heap\n");
750 return 0;
753 if( _WSHeap == 0 ) return WSASYSNOTREADY;
755 num_startup++;
757 /* that's the whole of the negotiation for now */
758 lpWSAData->wVersion = wVersionRequested;
759 /* return winsock information */
760 lpWSAData->wHighVersion = 0x0202;
761 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
762 strcpy(lpWSAData->szSystemStatus, "Running" );
763 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
764 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
765 /* don't do anything with lpWSAData->lpVendorInfo */
766 /* (some apps don't allocate the space for this field) */
768 TRACE("succeeded\n");
769 return 0;
773 /***********************************************************************
774 * WSACleanup (WINSOCK.116)
775 * WSACleanup (WS2_32.116)
777 INT WINAPI WSACleanup(void)
779 if (num_startup)
781 if (--num_startup > 0) return 0;
782 WINSOCK_DeleteIData();
783 return 0;
785 SetLastError(WSANOTINITIALISED);
786 return SOCKET_ERROR;
790 /***********************************************************************
791 * WSAGetLastError (WINSOCK.111)
792 * WSAGetLastError (WS2_32.111)
794 INT WINAPI WSAGetLastError(void)
796 return GetLastError();
799 /***********************************************************************
800 * WSASetLastError (WS2_32.112)
802 void WINAPI WSASetLastError(INT iError) {
803 SetLastError(iError);
806 /***********************************************************************
807 * WSASetLastError (WINSOCK.112)
809 void WINAPI WSASetLastError16(INT16 iError)
811 WSASetLastError(iError);
814 static char* check_buffer(int size)
816 static int local_buflen;
818 if (local_buffer)
820 if (local_buflen >= size ) return local_buffer;
821 HeapFree( GetProcessHeap(), 0, local_buffer );
823 local_buffer = HeapAlloc( GetProcessHeap(), 0, (local_buflen = size) );
824 return local_buffer;
827 static struct ws_hostent* check_buffer_he(int size)
829 static int he_len;
830 if (he_buffer)
832 if (he_len >= size ) return he_buffer;
833 UnMapLS( he_buffer_seg );
834 HeapFree( GetProcessHeap(), 0, he_buffer );
836 he_buffer = HeapAlloc( GetProcessHeap(), 0, (he_len = size) );
837 he_buffer_seg = MapLS( he_buffer );
838 return he_buffer;
841 static void* check_buffer_se(int size)
843 static int se_len;
844 if (se_buffer)
846 if (se_len >= size ) return se_buffer;
847 UnMapLS( se_buffer_seg );
848 HeapFree( GetProcessHeap(), 0, se_buffer );
850 se_buffer = HeapAlloc( GetProcessHeap(), 0, (se_len = size) );
851 se_buffer_seg = MapLS( se_buffer );
852 return se_buffer;
855 static struct ws_protoent* check_buffer_pe(int size)
857 static int pe_len;
858 if (pe_buffer)
860 if (pe_len >= size ) return pe_buffer;
861 UnMapLS( pe_buffer_seg );
862 HeapFree( GetProcessHeap(), 0, pe_buffer );
864 pe_buffer = HeapAlloc( GetProcessHeap(), 0, (pe_len = size) );
865 pe_buffer_seg = MapLS( he_buffer );
866 return pe_buffer;
869 /* ----------------------------------- i/o APIs */
871 #ifdef HAVE_IPX
872 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
873 #else
874 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
875 #endif
878 /**********************************************************************/
880 /* Returns the converted address if successful, NULL if it was too small to
881 * start with. Note that the returned pointer may be the original pointer
882 * if no conversion is necessary.
884 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
886 switch (wsaddr->sa_family)
888 #ifdef HAVE_IPX
889 case WS_AF_IPX:
891 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
892 struct sockaddr_ipx* uipx;
894 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
895 return NULL;
897 *uaddrlen=sizeof(struct sockaddr_ipx);
898 uipx=malloc(*uaddrlen);
899 uipx->sipx_family=AF_IPX;
900 uipx->sipx_port=wsipx->sa_socket;
901 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
902 * in one go
904 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
905 #ifdef IPX_FRAME_NONE
906 uipx->sipx_type=IPX_FRAME_NONE;
907 #endif
908 memset(&uipx->sipx_zero,0,sizeof(uipx->sipx_zero));
909 return (const struct sockaddr*)uipx;
911 #endif
913 default:
914 if (wsaddrlen<sizeof(struct WS_sockaddr))
915 return NULL;
917 /* No conversion needed, just return the original address */
918 *uaddrlen=wsaddrlen;
919 return (const struct sockaddr*)wsaddr;
921 return NULL;
924 /* Allocates a Unix sockaddr structure to receive the data */
925 inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
927 if (wsaddr==NULL)
929 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
931 /* This is not strictly the right thing to do. Hope it works however */
932 *uaddrlen=0;
934 return NULL;
937 if (*wsaddrlen==0)
938 *uaddrlen=0;
939 else
940 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
942 return malloc(*uaddrlen);
945 /* Returns 0 if successful, -1 if the buffer is too small */
946 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
948 int res;
950 switch(uaddr->sa_family)
952 #ifdef HAVE_IPX
953 case AF_IPX:
955 struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
956 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
958 res=-1;
959 switch (*wsaddrlen) /* how much can we copy? */
961 default:
962 res=0; /* enough */
963 *wsaddrlen=uaddrlen;
964 wsipx->sa_socket=uipx->sipx_port;
965 /* fall through */
966 case 13:
967 case 12:
968 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
969 /* fall through */
970 case 11:
971 case 10:
972 case 9:
973 case 8:
974 case 7:
975 case 6:
976 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
977 /* fall through */
978 case 5:
979 case 4:
980 case 3:
981 case 2:
982 wsipx->sa_family=WS_AF_IPX;
983 /* fall through */
984 case 1:
985 case 0:
986 /* way too small */
987 break;
990 break;
991 #endif
993 default:
994 /* No conversion needed */
995 memcpy(wsaddr,uaddr,*wsaddrlen);
996 if (*wsaddrlen<uaddrlen) {
997 res=-1;
998 } else {
999 *wsaddrlen=uaddrlen;
1000 res=0;
1003 return res;
1006 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
1007 * ws_sockaddr_alloc
1009 inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
1011 if (uaddr!=NULL && uaddr!=(const struct sockaddr*)wsaddr)
1012 free((void*)uaddr);
1015 /**************************************************************************
1016 * Functions for handling overlapped I/O
1017 **************************************************************************/
1019 static DWORD ws2_async_get_count (const struct async_private *ovp)
1021 return ovp->iosb->Information;
1024 static void ws2_async_cleanup ( struct async_private *ap )
1026 struct ws2_async *as = (struct ws2_async*) ap;
1028 TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->async.iosb );
1029 if ( !as->user_overlapped )
1031 #if 0
1032 /* FIXME: I don't think this is really used */
1033 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
1034 WSACloseEvent ( as->overlapped->hEvent );
1035 #endif
1036 HeapFree ( GetProcessHeap(), 0, as->async.iosb );
1039 if ( as->iovec )
1040 HeapFree ( GetProcessHeap(), 0, as->iovec );
1042 HeapFree ( GetProcessHeap(), 0, as );
1045 static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
1047 ws2_async* as = (ws2_async*) data;
1049 TRACE ("data: %p\n", as);
1051 as->completion_func ( NtStatusToWSAError (as->async.iosb->u.Status),
1052 as->async.iosb->Information,
1053 as->user_overlapped,
1054 as->flags );
1055 ws2_async_cleanup ( &as->async );
1058 /***********************************************************************
1059 * WS2_make_async (INTERNAL)
1062 static void WS2_async_recv (async_private *as);
1063 static void WS2_async_send (async_private *as);
1065 inline static struct ws2_async*
1066 WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferCount,
1067 LPDWORD lpFlags, struct WS_sockaddr *addr,
1068 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
1069 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1071 struct ws2_async *wsa = HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async ) );
1073 TRACE ( "wsa %p\n", wsa );
1075 if (!wsa)
1076 return NULL;
1078 wsa->async.ops = ( lpCompletionRoutine ? &ws2_async_ops : &ws2_nocomp_async_ops );
1079 wsa->async.handle = (HANDLE) s;
1080 wsa->async.fd = fd;
1081 wsa->async.type = type;
1082 switch (type)
1084 case ASYNC_TYPE_READ:
1085 wsa->flags = *lpFlags;
1086 wsa->async.func = WS2_async_recv;
1087 wsa->addrlen.ptr = addrlen;
1088 break;
1089 case ASYNC_TYPE_WRITE:
1090 wsa->flags = 0;
1091 wsa->async.func = WS2_async_send;
1092 wsa->addrlen.val = *addrlen;
1093 break;
1094 default:
1095 ERR ("Invalid async type: %d\n", type);
1097 wsa->user_overlapped = lpOverlapped;
1098 wsa->completion_func = lpCompletionRoutine;
1099 wsa->iovec = iovec;
1100 wsa->n_iovecs = dwBufferCount;
1101 wsa->addr = addr;
1103 if ( lpOverlapped )
1105 wsa->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
1106 wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
1108 else
1110 wsa->async.iosb = HeapAlloc ( GetProcessHeap(), 0,
1111 sizeof (IO_STATUS_BLOCK) );
1112 if ( !wsa->async.iosb )
1113 goto error;
1114 wsa->async.event = INVALID_HANDLE_VALUE;
1117 wsa->async.iosb->Information = 0;
1118 TRACE ( "wsa %p, ops %p, h %p, ev %p, fd %d, func %p, iosb %p, uov %p, cfunc %p\n",
1119 wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
1120 wsa->async.iosb, wsa->user_overlapped, wsa->completion_func );
1122 return wsa;
1124 error:
1125 TRACE ("Error\n");
1126 HeapFree ( GetProcessHeap(), 0, wsa );
1127 return NULL;
1130 /***********************************************************************
1131 * WS2_recv (INTERNAL)
1133 * Work horse for both synchronous and asynchronous recv() operations.
1135 static int WS2_recv ( int fd, struct iovec* iov, int count,
1136 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1137 LPDWORD lpFlags )
1139 struct msghdr hdr;
1140 int n;
1141 TRACE ( "fd %d, iovec %p, count %d addr %p, len %p, flags %lx\n",
1142 fd, iov, count, lpFrom, lpFromlen, *lpFlags);
1144 hdr.msg_name = NULL;
1146 if ( lpFrom )
1148 #if DEBUG_SOCKADDR
1149 dump_sockaddr (lpFrom);
1150 #endif
1152 hdr.msg_namelen = *lpFromlen;
1153 hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
1154 if ( !hdr.msg_name )
1156 WSASetLastError ( WSAEFAULT );
1157 n = -1;
1158 goto out;
1161 else
1162 hdr.msg_namelen = 0;
1164 hdr.msg_iov = iov;
1165 hdr.msg_iovlen = count;
1166 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1167 hdr.msg_accrights = NULL;
1168 hdr.msg_accrightslen = 0;
1169 #else
1170 hdr.msg_control = NULL;
1171 hdr.msg_controllen = 0;
1172 hdr.msg_flags = 0;
1173 #endif
1175 if ( (n = recvmsg (fd, &hdr, *lpFlags)) == -1 )
1177 TRACE ( "recvmsg error %d\n", errno);
1178 goto out;
1181 if ( lpFrom &&
1182 ws_sockaddr_u2ws ( hdr.msg_name, hdr.msg_namelen,
1183 lpFrom, lpFromlen ) != 0 )
1185 /* The from buffer was too small, but we read the data
1186 * anyway. Is that really bad?
1188 WSASetLastError ( WSAEFAULT );
1189 WARN ( "Address buffer too small\n" );
1192 out:
1194 ws_sockaddr_free ( hdr.msg_name, lpFrom );
1195 TRACE ("-> %d\n", n);
1196 return n;
1199 /***********************************************************************
1200 * WS2_async_recv (INTERNAL)
1202 * Handler for overlapped recv() operations.
1204 static void WS2_async_recv ( async_private *as )
1206 ws2_async* wsa = (ws2_async*) as;
1207 int result, err;
1209 TRACE ( "async %p\n", wsa );
1211 if ( wsa->async.iosb->u.Status != STATUS_PENDING )
1213 TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
1214 return;
1217 result = WS2_recv ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1218 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1220 if (result >= 0)
1222 wsa->async.iosb->u.Status = STATUS_SUCCESS;
1223 wsa->async.iosb->Information = result;
1224 TRACE ( "received %d bytes\n", result );
1225 _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
1226 return;
1229 err = wsaErrno ();
1230 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1232 wsa->async.iosb->u.Status = STATUS_PENDING;
1233 _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
1234 TRACE ( "still pending\n" );
1236 else
1238 wsa->async.iosb->u.Status = err;
1239 TRACE ( "Error: %x\n", err );
1243 /***********************************************************************
1244 * WS2_send (INTERNAL)
1246 * Work horse for both synchronous and asynchronous send() operations.
1248 static int WS2_send ( int fd, struct iovec* iov, int count,
1249 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1251 struct msghdr hdr;
1252 int n = -1;
1253 TRACE ( "fd %d, iovec %p, count %d addr %p, len %d, flags %lx\n",
1254 fd, iov, count, to, tolen, dwFlags);
1256 hdr.msg_name = NULL;
1258 if ( to )
1260 #if DEBUG_SOCKADDR
1261 dump_sockaddr (to);
1262 #endif
1263 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
1264 if ( !hdr.msg_name )
1266 WSASetLastError ( WSAEFAULT );
1267 goto out;
1270 else
1271 hdr.msg_namelen = 0;
1273 hdr.msg_iov = iov;
1274 hdr.msg_iovlen = count;
1275 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1276 hdr.msg_accrights = NULL;
1277 hdr.msg_accrightslen = 0;
1278 #else
1279 hdr.msg_control = NULL;
1280 hdr.msg_controllen = 0;
1281 hdr.msg_flags = 0;
1282 #endif
1284 n = sendmsg (fd, &hdr, dwFlags);
1286 out:
1287 ws_sockaddr_free ( hdr.msg_name, to );
1288 return n;
1291 /***********************************************************************
1292 * WS2_async_send (INTERNAL)
1294 * Handler for overlapped send() operations.
1296 static void WS2_async_send ( async_private *as )
1298 ws2_async* wsa = (ws2_async*) as;
1299 int result, err;
1301 TRACE ( "async %p\n", wsa );
1303 if ( wsa->async.iosb->u.Status != STATUS_PENDING )
1305 TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
1306 return;
1309 result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1310 wsa->addr, wsa->addrlen.val, wsa->flags );
1312 if (result >= 0)
1314 wsa->async.iosb->u.Status = STATUS_SUCCESS;
1315 wsa->async.iosb->Information = result;
1316 TRACE ( "sent %d bytes\n", result );
1317 _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
1318 return;
1321 err = wsaErrno ();
1322 if ( err == WSAEINTR )
1324 wsa->async.iosb->u.Status = STATUS_PENDING;
1325 _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
1326 TRACE ( "still pending\n" );
1328 else
1330 /* We set the status to a winsock error code and check for that
1331 later in NtStatusToWSAError () */
1332 wsa->async.iosb->u.Status = err;
1333 TRACE ( "Error: %x\n", err );
1337 /***********************************************************************
1338 * WS2_async_shutdown (INTERNAL)
1340 * Handler for shutdown() operations on overlapped sockets.
1342 static void WS2_async_shutdown ( async_private *as )
1344 ws2_async* wsa = (ws2_async*) as;
1345 int err = 1;
1347 TRACE ( "async %p %d\n", wsa, wsa->async.type );
1348 switch ( wsa->async.type )
1350 case ASYNC_TYPE_READ:
1351 err = shutdown ( wsa->async.fd, 0 );
1352 break;
1353 case ASYNC_TYPE_WRITE:
1354 err = shutdown ( wsa->async.fd, 1 );
1355 break;
1356 default:
1357 ERR ("invalid type: %d\n", wsa->async.type );
1360 if ( err )
1361 wsa->async.iosb->u.Status = wsaErrno ();
1362 else
1363 wsa->async.iosb->u.Status = STATUS_SUCCESS;
1366 /***********************************************************************
1367 * WS2_register_async_shutdown (INTERNAL)
1369 * Helper function for WS_shutdown() on overlapped sockets.
1371 static int WS2_register_async_shutdown ( SOCKET s, int fd, int type )
1373 struct ws2_async *wsa;
1374 int ret, err = WSAEFAULT;
1375 DWORD dwflags = 0;
1376 int len = 0;
1377 LPWSAOVERLAPPED ovl = HeapAlloc (GetProcessHeap(), 0, sizeof ( WSAOVERLAPPED ));
1379 TRACE ("s %d fd %d type %d\n", s, fd, type);
1380 if (!ovl)
1381 goto out;
1383 ovl->hEvent = WSACreateEvent ();
1384 if ( ovl->hEvent == WSA_INVALID_EVENT )
1385 goto out_free;
1387 wsa = WS2_make_async ( s, fd, type, NULL, 0,
1388 &dwflags, NULL, &len, ovl, NULL );
1389 if ( !wsa )
1390 goto out_close;
1392 /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
1393 wsa->user_overlapped = NULL;
1394 wsa->async.func = WS2_async_shutdown;
1395 if ( (ret = register_new_async ( &wsa->async )) )
1397 err = NtStatusToWSAError ( ret );
1398 goto out;
1400 /* Try immediate completion */
1401 while ( WaitForSingleObjectEx ( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1402 return 0;
1404 out_close:
1405 WSACloseEvent ( ovl->hEvent );
1406 out_free:
1407 HeapFree ( GetProcessHeap(), 0, ovl );
1408 out:
1409 return err;
1412 /***********************************************************************
1413 * accept (WS2_32.1)
1415 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1416 int *addrlen32)
1418 int fd = _get_sock_fd(s);
1420 TRACE("socket %04x\n", (UINT16)s );
1421 if (fd != -1)
1423 SOCKET as;
1424 if (_is_blocking(s))
1426 /* block here */
1427 do_block(fd, 5);
1428 _sync_sock_state(s); /* let wineserver notice connection */
1429 /* retrieve any error codes from it */
1430 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1431 /* FIXME: care about the error? */
1433 close(fd);
1434 SERVER_START_REQ( accept_socket )
1436 req->lhandle = SOCKET2HANDLE(s);
1437 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1438 req->inherit = TRUE;
1439 set_error( wine_server_call( req ) );
1440 as = HANDLE2SOCKET( reply->handle );
1442 SERVER_END_REQ;
1443 if (as)
1445 if (addr)
1446 WS_getpeername(as, addr, addrlen32);
1447 return as;
1450 else
1452 SetLastError(WSAENOTSOCK);
1454 return INVALID_SOCKET;
1457 /***********************************************************************
1458 * accept (WINSOCK.1)
1460 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct WS_sockaddr* addr,
1461 INT16* addrlen16 )
1463 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
1464 SOCKET retSocket = WS_accept( s, addr, &addrlen32 );
1465 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
1466 return (SOCKET16)retSocket;
1469 /***********************************************************************
1470 * bind (WS2_32.2)
1472 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1474 int fd = _get_sock_fd(s);
1475 int res;
1477 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
1478 #if DEBUG_SOCKADDR
1479 dump_sockaddr(name);
1480 #endif
1482 res=SOCKET_ERROR;
1483 if (fd != -1)
1485 if (!name || !SUPPORTED_PF(name->sa_family))
1487 SetLastError(WSAEAFNOSUPPORT);
1489 else
1491 const struct sockaddr* uaddr;
1492 int uaddrlen;
1494 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1495 if (uaddr == NULL)
1497 SetLastError(WSAEFAULT);
1499 else
1501 int on = 1;
1502 /* The game GrandPrixLegends binds more than one time, but does
1503 * not do a SO_REUSEADDR - Stevens says this is ok */
1504 TRACE( "Setting WS_SO_REUSEADDR on socket before we bind it\n");
1505 WS_setsockopt( s, WS_SOL_SOCKET, WS_SO_REUSEADDR, (char*)&on, sizeof(on) );
1507 if (bind(fd, uaddr, uaddrlen) < 0)
1509 int loc_errno = errno;
1510 WARN("\tfailure - errno = %i\n", errno);
1511 errno = loc_errno;
1512 switch (errno)
1514 case EBADF:
1515 SetLastError(WSAENOTSOCK);
1516 break;
1517 case EADDRNOTAVAIL:
1518 SetLastError(WSAEINVAL);
1519 break;
1520 default:
1521 SetLastError(wsaErrno());
1522 break;
1525 else
1527 res=0; /* success */
1529 ws_sockaddr_free(uaddr,name);
1532 close(fd);
1534 else
1536 SetLastError(WSAENOTSOCK);
1538 return res;
1541 /***********************************************************************
1542 * bind (WINSOCK.2)
1544 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1546 return (INT16)WS_bind( s, name, namelen );
1549 /***********************************************************************
1550 * closesocket (WS2_32.3)
1552 int WINAPI WS_closesocket(SOCKET s)
1554 TRACE("socket %08x\n", s);
1555 if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1556 return SOCKET_ERROR;
1559 /***********************************************************************
1560 * closesocket (WINSOCK.3)
1562 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
1564 return (INT16)WS_closesocket(s);
1567 /***********************************************************************
1568 * connect (WS2_32.4)
1570 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1572 int fd = _get_sock_fd(s);
1574 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
1575 #if DEBUG_SOCKADDR
1576 dump_sockaddr(name);
1577 #endif
1579 if (fd != -1)
1581 const struct sockaddr* uaddr;
1582 int uaddrlen;
1584 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1585 if (uaddr == NULL)
1587 SetLastError(WSAEFAULT);
1589 else
1591 int rc;
1593 rc=connect(fd, uaddr, uaddrlen);
1594 ws_sockaddr_free(uaddr,name);
1595 if (rc == 0)
1596 goto connect_success;
1599 if (errno == EINPROGRESS)
1601 /* tell wineserver that a connection is in progress */
1602 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1603 FD_CONNECT|FD_READ|FD_WRITE,
1604 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1605 if (_is_blocking(s))
1607 int result;
1608 /* block here */
1609 do_block(fd, 7);
1610 _sync_sock_state(s); /* let wineserver notice connection */
1611 /* retrieve any error codes from it */
1612 result = _get_sock_error(s, FD_CONNECT_BIT);
1613 if (result)
1614 SetLastError(result);
1615 else
1617 goto connect_success;
1620 else
1622 SetLastError(WSAEWOULDBLOCK);
1625 else
1627 SetLastError(wsaErrno());
1629 close(fd);
1631 else
1633 SetLastError(WSAENOTSOCK);
1635 return SOCKET_ERROR;
1637 connect_success:
1638 close(fd);
1639 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1640 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1641 FD_CONNECT|FD_WINE_LISTENING);
1642 return 0;
1645 /***********************************************************************
1646 * connect (WINSOCK.4)
1648 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1650 return (INT16)WS_connect( s, name, namelen );
1653 /***********************************************************************
1654 * WSAConnect (WS2_32.30)
1656 int WINAPI WSAConnect ( SOCKET s, const struct WS_sockaddr* name, int namelen,
1657 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1658 LPQOS lpSQOS, LPQOS lpGQOS )
1660 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1661 FIXME ("unsupported parameters!\n");
1662 return WS_connect ( s, name, namelen );
1666 /***********************************************************************
1667 * getpeername (WS2_32.5)
1669 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1671 int fd;
1672 int res;
1674 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1676 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1677 if( (name == NULL) || (namelen == NULL) )
1679 SetLastError( WSAEFAULT );
1680 return SOCKET_ERROR;
1683 fd = _get_sock_fd(s);
1684 res = SOCKET_ERROR;
1686 if (fd != -1)
1688 struct sockaddr* uaddr;
1689 int uaddrlen;
1691 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1692 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1694 SetLastError(wsaErrno());
1696 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1698 /* The buffer was too small */
1699 SetLastError(WSAEFAULT);
1701 else
1703 res=0;
1705 ws_sockaddr_free(uaddr,name);
1706 close(fd);
1708 else
1710 SetLastError(WSAENOTSOCK);
1712 return res;
1715 /***********************************************************************
1716 * getpeername (WINSOCK.5)
1718 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct WS_sockaddr *name,
1719 INT16 *namelen16)
1721 INT namelen32 = *namelen16;
1722 INT retVal = WS_getpeername( s, name, &namelen32 );
1724 #if DEBUG_SOCKADDR
1725 dump_sockaddr(name);
1726 #endif
1728 *namelen16 = namelen32;
1729 return (INT16)retVal;
1732 /***********************************************************************
1733 * getsockname (WS2_32.6)
1735 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1737 int fd;
1738 int res;
1740 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1742 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1743 if( (name == NULL) || (namelen == NULL) )
1745 SetLastError( WSAEFAULT );
1746 return SOCKET_ERROR;
1749 fd = _get_sock_fd(s);
1750 res = SOCKET_ERROR;
1752 if (fd != -1)
1754 struct sockaddr* uaddr;
1755 int uaddrlen;
1757 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1758 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1760 SetLastError(wsaErrno());
1762 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1764 /* The buffer was too small */
1765 SetLastError(WSAEFAULT);
1767 else
1769 res=0;
1771 close(fd);
1773 else
1775 SetLastError(WSAENOTSOCK);
1777 return res;
1780 /***********************************************************************
1781 * getsockname (WINSOCK.6)
1783 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct WS_sockaddr *name,
1784 INT16 *namelen16)
1786 INT retVal;
1788 if( namelen16 )
1790 INT namelen32 = *namelen16;
1791 retVal = WS_getsockname( s, name, &namelen32 );
1792 *namelen16 = namelen32;
1794 #if DEBUG_SOCKADDR
1795 dump_sockaddr(name);
1796 #endif
1799 else retVal = SOCKET_ERROR;
1800 return (INT16)retVal;
1804 /***********************************************************************
1805 * getsockopt (WS2_32.7)
1807 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1808 INT optname, char *optval, INT *optlen)
1810 int fd;
1812 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1813 (int) optname, (int) optval, (int) *optlen);
1814 /* SO_OPENTYPE does not require a valid socket handle. */
1815 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1817 if (!optlen || *optlen < sizeof(int) || !optval)
1819 SetLastError(WSAEFAULT);
1820 return SOCKET_ERROR;
1822 *(int *)optval = (int)TlsGetValue( opentype_tls_index );
1823 *optlen = sizeof(int);
1824 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1825 return 0;
1828 fd = _get_sock_fd(s);
1829 if (fd != -1)
1831 if (!convert_sockopt(&level, &optname)) {
1832 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1833 } else {
1834 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1836 close(fd);
1837 return 0;
1839 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1841 close(fd);
1843 return SOCKET_ERROR;
1847 /***********************************************************************
1848 * getsockopt (WINSOCK.7)
1850 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1851 INT16 optname, char *optval, INT16 *optlen)
1853 INT optlen32;
1854 INT *p = &optlen32;
1855 INT retVal;
1856 if( optlen ) optlen32 = *optlen; else p = NULL;
1857 retVal = WS_getsockopt( s, (UINT16)level, optname, optval, p );
1858 if( optlen ) *optlen = optlen32;
1859 return (INT16)retVal;
1863 /***********************************************************************
1864 * htonl (WINSOCK.8)
1865 * htonl (WS2_32.8)
1867 u_long WINAPI WS_htonl(u_long hostlong)
1869 return htonl(hostlong);
1873 /***********************************************************************
1874 * htons (WINSOCK.9)
1875 * htons (WS2_32.9)
1877 u_short WINAPI WS_htons(u_short hostshort)
1879 return htons(hostshort);
1883 /***********************************************************************
1884 * inet_addr (WINSOCK.10)
1885 * inet_addr (WS2_32.11)
1887 u_long WINAPI WS_inet_addr(const char *cp)
1889 return inet_addr(cp);
1893 /***********************************************************************
1894 * ntohl (WINSOCK.14)
1895 * ntohl (WS2_32.14)
1897 u_long WINAPI WS_ntohl(u_long netlong)
1899 return ntohl(netlong);
1903 /***********************************************************************
1904 * ntohs (WINSOCK.15)
1905 * ntohs (WS2_32.15)
1907 u_short WINAPI WS_ntohs(u_short netshort)
1909 return ntohs(netshort);
1913 /***********************************************************************
1914 * inet_ntoa (WS2_32.12)
1916 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1918 /* use "buffer for dummies" here because some applications have
1919 * propensity to decode addresses in ws_hostent structure without
1920 * saving them first...
1922 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1924 char* s = inet_ntoa(*((struct in_addr*)&in));
1925 if( s )
1927 strcpy(dbuffer, s);
1928 return dbuffer;
1930 SetLastError(wsaErrno());
1931 return NULL;
1934 /***********************************************************************
1935 * inet_ntoa (WINSOCK.11)
1937 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1939 char* retVal;
1940 if (!(retVal = WS_inet_ntoa(*((struct WS_in_addr*)&in)))) return 0;
1941 if (!dbuffer_seg) dbuffer_seg = MapLS( retVal );
1942 return dbuffer_seg;
1946 /**********************************************************************
1947 * WSAIoctl (WS2_32.50)
1950 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1952 INT WINAPI WSAIoctl (SOCKET s,
1953 DWORD dwIoControlCode,
1954 LPVOID lpvInBuffer,
1955 DWORD cbInBuffer,
1956 LPVOID lpbOutBuffer,
1957 DWORD cbOutBuffer,
1958 LPDWORD lpcbBytesReturned,
1959 LPWSAOVERLAPPED lpOverlapped,
1960 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1962 int fd = _get_sock_fd(s);
1964 if (fd != -1)
1966 switch( dwIoControlCode )
1968 case SIO_GET_INTERFACE_LIST:
1970 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1971 DWORD size, numInt, apiReturn;
1973 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1974 /* FIXME: length of output buffer not checked */
1976 apiReturn = GetAdaptersInfo(NULL, &size);
1977 if (apiReturn == ERROR_NO_DATA)
1979 numInt = 0;
1981 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
1983 PIP_ADAPTER_INFO table = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(),0,size);
1985 if (table)
1987 if (GetAdaptersInfo(table, &size) == NO_ERROR)
1989 PIP_ADAPTER_INFO ptr;
1991 for (ptr = table, numInt = 0; ptr;
1992 ptr = ptr->Next, intArray++, numInt++)
1994 unsigned int addr, mask, bcast;
1995 struct ifreq ifInfo;
1997 /* Socket Status Flags */
1998 strncpy(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
1999 ifInfo.ifr_name[IFNAMSIZ-1] = '\0';
2000 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
2002 ERR ("Error obtaining status flags for socket!\n");
2003 HeapFree(GetProcessHeap(),0,table);
2004 close(fd);
2005 WSASetLastError(WSAEINVAL);
2006 return (SOCKET_ERROR);
2008 else
2010 /* set flags; the values of IFF_* are not the same
2011 under Linux and Windows, therefore must generate
2012 new flags */
2013 intArray->iiFlags = 0;
2014 if (ifInfo.ifr_flags & IFF_BROADCAST)
2015 intArray->iiFlags |= WS_IFF_BROADCAST;
2016 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
2017 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
2018 if (ifInfo.ifr_flags & IFF_LOOPBACK)
2019 intArray->iiFlags |= WS_IFF_LOOPBACK;
2020 if (ifInfo.ifr_flags & IFF_UP)
2021 intArray->iiFlags |= WS_IFF_UP;
2024 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
2025 mask = inet_addr(ptr->IpAddressList.IpMask.String);
2026 bcast = addr | (addr & !mask);
2027 intArray->iiAddress.AddressIn.sin_family = AF_INET;
2028 intArray->iiAddress.AddressIn.sin_port = 0;
2029 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
2030 addr;
2031 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2032 intArray->iiNetmask.AddressIn.sin_port = 0;
2033 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
2034 mask;
2035 intArray->iiBroadcastAddress.AddressIn.sin_family =
2036 AF_INET;
2037 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
2038 intArray->iiBroadcastAddress.AddressIn.sin_addr.
2039 WS_s_addr = bcast;
2041 HeapFree(GetProcessHeap(),0,table);
2043 else
2045 ERR ("Unable to get interface table!\n");
2046 close(fd);
2047 HeapFree(GetProcessHeap(),0,table);
2048 WSASetLastError(WSAEINVAL);
2049 return (SOCKET_ERROR);
2052 else
2054 close(fd);
2055 WSASetLastError(WSAEINVAL);
2056 return (SOCKET_ERROR);
2059 else
2061 ERR ("Unable to get interface table!\n");
2062 close(fd);
2063 WSASetLastError(WSAEINVAL);
2064 return (SOCKET_ERROR);
2066 /* Calculate the size of the array being returned */
2067 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2068 break;
2071 default:
2073 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2074 close(fd);
2075 WSASetLastError(WSAEOPNOTSUPP);
2076 return (SOCKET_ERROR);
2080 /* Function executed with no errors */
2081 close(fd);
2082 return (0);
2084 else
2086 WSASetLastError(WSAENOTSOCK);
2087 return (SOCKET_ERROR);
2092 /***********************************************************************
2093 * ioctlsocket (WS2_32.10)
2095 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2097 int fd = _get_sock_fd(s);
2099 TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
2100 if (fd != -1)
2102 long newcmd = cmd;
2104 switch( cmd )
2106 case WS_FIONREAD:
2107 newcmd=FIONREAD;
2108 break;
2110 case WS_FIONBIO:
2111 newcmd=FIONBIO;
2112 if( _get_sock_mask(s) )
2114 /* AsyncSelect()'ed sockets are always nonblocking */
2115 if (*argp) {
2116 close(fd);
2117 return 0;
2119 SetLastError(WSAEINVAL);
2120 close(fd);
2121 return SOCKET_ERROR;
2123 close(fd);
2124 if (*argp)
2125 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2126 else
2127 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2128 return 0;
2130 case WS_SIOCATMARK:
2131 newcmd=SIOCATMARK;
2132 break;
2134 case WS__IOW('f',125,u_long):
2135 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2136 SetLastError(WSAEINVAL);
2137 return SOCKET_ERROR;
2139 case SIOCGIFBRDADDR:
2140 case SIOCGIFNETMASK:
2141 case SIOCGIFADDR:
2142 /* These don't need any special handling. They are used by
2143 WsControl, and are here to suppress an unecessary warning. */
2144 break;
2147 default:
2148 /* Netscape tries hard to use bogus ioctl 0x667e */
2149 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2151 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2153 close(fd);
2154 return 0;
2156 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2157 close(fd);
2159 return SOCKET_ERROR;
2162 /***********************************************************************
2163 * ioctlsocket (WINSOCK.12)
2165 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
2167 return (INT16)WS_ioctlsocket( s, cmd, argp );
2171 /***********************************************************************
2172 * listen (WS2_32.13)
2174 int WINAPI WS_listen(SOCKET s, int backlog)
2176 int fd = _get_sock_fd(s);
2178 TRACE("socket %04x, backlog %d\n", s, backlog);
2179 if (fd != -1)
2181 if (listen(fd, backlog) == 0)
2183 close(fd);
2184 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2185 FD_WINE_LISTENING,
2186 FD_CONNECT|FD_WINE_CONNECTED);
2187 return 0;
2189 SetLastError(wsaErrno());
2191 else SetLastError(WSAENOTSOCK);
2192 return SOCKET_ERROR;
2195 /***********************************************************************
2196 * listen (WINSOCK.13)
2198 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
2200 return (INT16)WS_listen( s, backlog );
2204 /***********************************************************************
2205 * recv (WS2_32.16)
2207 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2209 DWORD n, dwFlags = flags;
2210 WSABUF wsabuf;
2212 wsabuf.len = len;
2213 wsabuf.buf = buf;
2215 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2216 return SOCKET_ERROR;
2217 else
2218 return n;
2221 /***********************************************************************
2222 * recv (WINSOCK.16)
2224 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2226 return (INT16)WS_recv( s, buf, len, flags );
2230 /***********************************************************************
2231 * recvfrom (WS2_32.17)
2233 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2234 struct WS_sockaddr *from, int *fromlen)
2236 DWORD n, dwFlags = flags;
2237 WSABUF wsabuf;
2239 wsabuf.len = len;
2240 wsabuf.buf = buf;
2242 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2243 return SOCKET_ERROR;
2244 else
2245 return n;
2248 /***********************************************************************
2249 * recvfrom (WINSOCK.17)
2251 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2252 struct WS_sockaddr *from, INT16 *fromlen16)
2254 INT fromlen32;
2255 INT *p = &fromlen32;
2256 INT retVal;
2258 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
2259 retVal = WS_recvfrom( s, buf, len, flags, from, p );
2260 if( fromlen16 ) *fromlen16 = fromlen32;
2261 return (INT16)retVal;
2264 /***********************************************************************
2265 * __ws_select
2267 static int __ws_select(BOOL b32,
2268 void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
2269 const struct WS_timeval *ws_timeout)
2271 int highfd = 0;
2272 fd_set readfds, writefds, exceptfds;
2273 fd_set *p_read, *p_write, *p_except;
2274 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2275 struct timeval timeout, *timeoutaddr = NULL;
2277 TRACE("read %p, write %p, excp %p timeout %p\n",
2278 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2280 p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
2281 p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
2282 p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
2283 if (ws_timeout)
2285 timeoutaddr = &timeout;
2286 timeout.tv_sec=ws_timeout->tv_sec;
2287 timeout.tv_usec=ws_timeout->tv_usec;
2290 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2292 fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
2293 fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
2295 if (p_except && ws_exceptfds)
2297 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
2298 #define wsfds32 ((WS_fd_set*)ws_exceptfds)
2299 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
2301 for (i = j = 0; i < count; i++)
2303 int fd = exceptfd[i];
2304 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
2306 if( b32 )
2307 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
2308 else
2309 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
2311 if( fd >= 0 ) close(fd);
2312 exceptfd[i] = -1;
2314 if( b32 )
2315 wsfds32->fd_count = j;
2316 else
2317 wsfds16->fd_count = j;
2318 #undef wsfds32
2319 #undef wsfds16
2321 return highfd;
2323 fd_set_unimport(ws_readfds, readfd, b32);
2324 fd_set_unimport(ws_writefds, writefd, b32);
2325 fd_set_unimport(ws_exceptfds, exceptfd, b32);
2326 if( ws_readfds ) ((WS_fd_set*)ws_readfds)->fd_count = 0;
2327 if( ws_writefds ) ((WS_fd_set*)ws_writefds)->fd_count = 0;
2328 if( ws_exceptfds ) ((WS_fd_set*)ws_exceptfds)->fd_count = 0;
2330 if( highfd == 0 ) return 0;
2331 SetLastError(wsaErrno());
2332 return SOCKET_ERROR;
2335 /***********************************************************************
2336 * select (WINSOCK.18)
2338 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
2339 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
2340 struct WS_timeval* timeout)
2342 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2345 /***********************************************************************
2346 * select (WS2_32.18)
2348 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2349 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2350 const struct WS_timeval* timeout)
2352 /* struct timeval is the same for both 32- and 16-bit code */
2353 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2357 /***********************************************************************
2358 * send (WS2_32.19)
2360 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2362 DWORD n;
2363 WSABUF wsabuf;
2365 wsabuf.len = len;
2366 wsabuf.buf = (char*) buf;
2368 if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2369 return SOCKET_ERROR;
2370 else
2371 return n;
2374 /***********************************************************************
2375 * WSASend (WS2_32.72)
2377 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2378 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2379 LPWSAOVERLAPPED lpOverlapped,
2380 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2382 return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2383 NULL, 0, lpOverlapped, lpCompletionRoutine );
2386 /***********************************************************************
2387 * WSASendDisconnect (WS2_32.73)
2389 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2391 return WS_shutdown ( s, SD_SEND );
2395 /***********************************************************************
2396 * WSASendTo (WS2_32.74)
2398 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2399 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2400 const struct WS_sockaddr *to, int tolen,
2401 LPWSAOVERLAPPED lpOverlapped,
2402 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2404 int i, n, fd, err = WSAENOTSOCK, flags, ret;
2405 struct iovec* iovec;
2406 struct ws2_async *wsa;
2407 enum fd_type type;
2409 TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2410 s, lpBuffers, dwBufferCount, dwFlags,
2411 to, tolen, lpOverlapped, lpCompletionRoutine);
2413 fd = _get_sock_fd_type( s, GENERIC_WRITE, &type, &flags );
2414 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
2416 if ( fd == -1 )
2418 err = WSAGetLastError ();
2419 goto error;
2422 iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
2424 if ( !iovec )
2426 err = WSAEFAULT;
2427 goto err_close;
2430 for ( i = 0; i < dwBufferCount; i++ )
2432 iovec[i].iov_base = lpBuffers[i].buf;
2433 iovec[i].iov_len = lpBuffers[i].len;
2436 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2438 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
2439 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2440 lpOverlapped, lpCompletionRoutine );
2441 if ( !wsa )
2443 err = WSAEFAULT;
2444 goto err_free;
2447 if ( ( ret = register_new_async ( &wsa->async )) )
2449 err = NtStatusToWSAError ( ret );
2451 if ( !lpOverlapped )
2452 HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
2453 HeapFree ( GetProcessHeap(), 0, wsa );
2454 goto err_free;
2457 /* Try immediate completion */
2458 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
2460 if ( WSAGetOverlappedResult ( s, lpOverlapped,
2461 lpNumberOfBytesSent, FALSE, &dwFlags) )
2462 return 0;
2464 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
2465 goto error;
2468 WSASetLastError ( WSA_IO_PENDING );
2469 return SOCKET_ERROR;
2472 if (_is_blocking(s))
2474 /* FIXME: exceptfds? */
2475 do_block(fd, 2);
2478 n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2479 if ( n == -1 )
2481 err = wsaErrno();
2482 if ( err == WSAEWOULDBLOCK )
2483 _enable_event (SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2484 goto err_free;
2487 TRACE(" -> %i bytes\n", n);
2488 *lpNumberOfBytesSent = n;
2490 HeapFree ( GetProcessHeap(), 0, iovec );
2491 close ( fd );
2492 return 0;
2494 err_free:
2495 HeapFree ( GetProcessHeap(), 0, iovec );
2497 err_close:
2498 close ( fd );
2500 error:
2501 WARN (" -> ERROR %d\n", err);
2502 WSASetLastError (err);
2503 return SOCKET_ERROR;
2506 /***********************************************************************
2507 * send (WINSOCK.19)
2509 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2511 return WS_send( s, buf, len, flags );
2514 /***********************************************************************
2515 * sendto (WS2_32.20)
2517 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2518 const struct WS_sockaddr *to, int tolen)
2520 DWORD n;
2521 WSABUF wsabuf;
2523 wsabuf.len = len;
2524 wsabuf.buf = (char*) buf;
2526 if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2527 return SOCKET_ERROR;
2528 else
2529 return n;
2532 /***********************************************************************
2533 * sendto (WINSOCK.20)
2535 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2536 struct WS_sockaddr *to, INT16 tolen)
2538 return (INT16)WS_sendto( s, buf, len, flags, to, tolen );
2541 /***********************************************************************
2542 * setsockopt (WS2_32.21)
2544 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2545 const char *optval, int optlen)
2547 int fd;
2549 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
2550 (int) optname, (int) optval, optlen);
2551 /* SO_OPENTYPE does not require a valid socket handle. */
2552 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2554 if (optlen < sizeof(int) || !optval)
2556 SetLastError(WSAEFAULT);
2557 return SOCKET_ERROR;
2559 TlsSetValue( opentype_tls_index, (LPVOID)*(int *)optval );
2560 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2561 return 0;
2564 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2565 * socket. This will either not happen under windows or it is ignored in
2566 * windows (but it works in linux and therefor prevents the game to find
2567 * games outsite the current network) */
2568 if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE )
2570 FIXME("Does windows ignore SO_DONTROUTE?\n");
2571 return 0;
2575 fd = _get_sock_fd(s);
2576 if (fd != -1)
2578 struct linger linger;
2579 int woptval;
2580 struct timeval tval;
2582 /* Is a privileged and useless operation, so we don't. */
2583 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
2584 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2585 return 0;
2588 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2589 /* This is unique to WinSock and takes special conversion */
2590 linger.l_onoff = *((int*)optval) ? 0: 1;
2591 linger.l_linger = 0;
2592 optname=SO_LINGER;
2593 optval = (char*)&linger;
2594 optlen = sizeof(struct linger);
2595 level = SOL_SOCKET;
2596 }else{
2597 if (!convert_sockopt(&level, &optname)) {
2598 ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2599 SetLastError(WSAENOPROTOOPT);
2600 close(fd);
2601 return SOCKET_ERROR;
2603 if (optname == SO_LINGER && optval) {
2604 /* yes, uses unsigned short in both win16/win32 */
2605 linger.l_onoff = ((UINT16*)optval)[0];
2606 linger.l_linger = ((UINT16*)optval)[1];
2607 /* FIXME: what is documented behavior if SO_LINGER optval
2608 is null?? */
2609 optval = (char*)&linger;
2610 optlen = sizeof(struct linger);
2611 } else if (optval && optlen < sizeof(int)){
2612 woptval= *((INT16 *) optval);
2613 optval= (char*) &woptval;
2614 optlen=sizeof(int);
2616 #ifdef SO_RCVTIMEO
2617 if (level == SOL_SOCKET && optname == SO_RCVTIMEO) {
2618 if (optlen == sizeof(UINT32)) {
2619 /* WinSock passes miliseconds instead of struct timeval */
2620 tval.tv_usec = *(PUINT32)optval % 1000;
2621 tval.tv_sec = *(PUINT32)optval / 1000;
2622 /* min of 500 milisec */
2623 if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2624 optlen = sizeof(struct timeval);
2625 optval = (char*)&tval;
2626 } else if (optlen == sizeof(struct timeval)) {
2627 WARN("SO_RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2628 } else {
2629 WARN("SO_RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2630 close(fd);
2631 return 0;
2634 #endif
2635 #ifdef SO_SNDTIMEO
2636 if (level == SOL_SOCKET && optname == SO_SNDTIMEO) {
2637 if (optlen == sizeof(UINT32)) {
2638 /* WinSock passes miliseconds instead of struct timeval */
2639 tval.tv_usec = *(PUINT32)optval % 1000;
2640 tval.tv_sec = *(PUINT32)optval / 1000;
2641 /* min of 500 milisec */
2642 if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2643 optlen = sizeof(struct timeval);
2644 optval = (char*)&tval;
2645 } else if (optlen == sizeof(struct timeval)) {
2646 WARN("SO_SNDTIMEO for %d bytes: assuming unixism\n", optlen);
2647 } else {
2648 WARN("SO_SNDTIMEO for %d bytes is weird: ignored\n", optlen);
2649 close(fd);
2650 return 0;
2653 #endif
2655 if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2656 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2657 close( fd);
2658 return 0;
2661 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2663 close(fd);
2664 return 0;
2666 TRACE("Setting socket error, %d\n", wsaErrno());
2667 SetLastError(wsaErrno());
2668 close(fd);
2670 else SetLastError(WSAENOTSOCK);
2671 return SOCKET_ERROR;
2674 /***********************************************************************
2675 * setsockopt (WINSOCK.21)
2677 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2678 char *optval, INT16 optlen)
2680 if( !optval ) return SOCKET_ERROR;
2681 return (INT16)WS_setsockopt( s, (UINT16)level, optname, optval, optlen );
2685 /***********************************************************************
2686 * shutdown (WS2_32.22)
2688 int WINAPI WS_shutdown(SOCKET s, int how)
2690 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2691 enum fd_type type;
2692 unsigned int clear_flags = 0;
2694 fd = _get_sock_fd_type ( s, 0, &type, &flags );
2695 TRACE("socket %04x, how %i %d %d \n", s, how, type, flags );
2697 if (fd == -1)
2698 return SOCKET_ERROR;
2700 switch( how )
2702 case 0: /* drop receives */
2703 clear_flags |= FD_READ;
2704 break;
2705 case 1: /* drop sends */
2706 clear_flags |= FD_WRITE;
2707 break;
2708 case 2: /* drop all */
2709 clear_flags |= FD_READ|FD_WRITE;
2710 default:
2711 clear_flags |= FD_WINE_LISTENING;
2714 if ( flags & FD_FLAG_OVERLAPPED ) {
2716 switch ( how )
2718 case SD_RECEIVE:
2719 fd0 = fd;
2720 break;
2721 case SD_SEND:
2722 fd1 = fd;
2723 break;
2724 case SD_BOTH:
2725 default:
2726 fd0 = fd;
2727 fd1 = _get_sock_fd ( s );
2730 if ( fd0 != -1 )
2732 err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
2733 if ( err )
2735 close ( fd0 );
2736 goto error;
2739 if ( fd1 != -1 )
2741 err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
2742 if ( err )
2744 close ( fd1 );
2745 goto error;
2749 else /* non-overlapped mode */
2751 if ( shutdown( fd, how ) )
2753 err = wsaErrno ();
2754 close ( fd );
2755 goto error;
2757 close(fd);
2760 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2761 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2762 return 0;
2764 error:
2765 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2766 WSASetLastError ( err );
2767 return SOCKET_ERROR;
2770 /***********************************************************************
2771 * shutdown (WINSOCK.22)
2773 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2775 return (INT16)WS_shutdown( s, how );
2779 /***********************************************************************
2780 * socket (WS2_32.23)
2782 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2784 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2786 return WSASocketA ( af, type, protocol, NULL, 0,
2787 (TlsGetValue(opentype_tls_index) ? 0 : WSA_FLAG_OVERLAPPED) );
2790 /***********************************************************************
2791 * socket (WINSOCK.23)
2793 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2795 return (SOCKET16)WS_socket( af, type, protocol );
2799 /* ----------------------------------- DNS services
2801 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2802 * Also, we have to use wsock32 stubs to convert structures and
2803 * error codes from Unix to WSA, hence there is no direct mapping in
2804 * the relay32/wsock32.spec.
2808 /***********************************************************************
2809 * __ws_gethostbyaddr
2811 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2813 WIN_hostent *retval = NULL;
2815 struct hostent* host;
2816 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2817 char *extrabuf;
2818 int ebufsize=1024;
2819 struct hostent hostentry;
2820 int locerr=ENOBUFS;
2821 host = NULL;
2822 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2823 while(extrabuf) {
2824 int res = gethostbyaddr_r(addr, len, type,
2825 &hostentry, extrabuf, ebufsize, &host, &locerr);
2826 if( res != ERANGE) break;
2827 ebufsize *=2;
2828 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2830 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2831 #else
2832 EnterCriticalSection( &csWSgetXXXbyYYY );
2833 host = gethostbyaddr(addr, len, type);
2834 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2835 #endif
2836 if( host != NULL )
2838 if( WS_dup_he(host, dup_flag) )
2839 retval = he_buffer;
2840 else
2841 SetLastError(WSAENOBUFS);
2843 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2844 HeapFree(GetProcessHeap(),0,extrabuf);
2845 #else
2846 LeaveCriticalSection( &csWSgetXXXbyYYY );
2847 #endif
2848 return retval;
2851 /***********************************************************************
2852 * gethostbyaddr (WINSOCK.51)
2854 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2856 TRACE("ptr %p, len %d, type %d\n", addr, len, type);
2857 if (!__ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR )) return 0;
2858 return he_buffer_seg;
2861 /***********************************************************************
2862 * gethostbyaddr (WS2_32.51)
2864 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len,
2865 int type)
2867 TRACE("ptr %08x, len %d, type %d\n",
2868 (unsigned) addr, len, type);
2869 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2872 /***********************************************************************
2873 * __ws_gethostbyname
2875 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2877 WIN_hostent *retval = NULL;
2878 struct hostent* host;
2879 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2880 char *extrabuf;
2881 int ebufsize=1024;
2882 struct hostent hostentry;
2883 int locerr = ENOBUFS;
2884 host = NULL;
2885 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2886 while(extrabuf) {
2887 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2888 if( res != ERANGE) break;
2889 ebufsize *=2;
2890 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2892 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2893 #else
2894 EnterCriticalSection( &csWSgetXXXbyYYY );
2895 host = gethostbyname(name);
2896 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2897 #endif
2898 if( host != NULL )
2900 if( WS_dup_he(host, dup_flag) )
2901 retval = he_buffer;
2902 else SetLastError(WSAENOBUFS);
2904 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2905 HeapFree(GetProcessHeap(),0,extrabuf);
2906 #else
2907 LeaveCriticalSection( &csWSgetXXXbyYYY );
2908 #endif
2909 return retval;
2912 /***********************************************************************
2913 * gethostbyname (WINSOCK.52)
2915 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2917 TRACE( "%s\n", debugstr_a(name) );
2918 if (!__ws_gethostbyname( name, WS_DUP_SEGPTR )) return 0;
2919 return he_buffer_seg;
2922 /***********************************************************************
2923 * gethostbyname (WS2_32.52)
2925 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2927 TRACE( "%s\n", debugstr_a(name) );
2928 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2932 /***********************************************************************
2933 * __ws_getprotobyname
2935 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2937 WIN_protoent* retval = NULL;
2938 #ifdef HAVE_GETPROTOBYNAME
2939 struct protoent* proto;
2940 EnterCriticalSection( &csWSgetXXXbyYYY );
2941 if( (proto = getprotobyname(name)) != NULL )
2943 if( WS_dup_pe(proto, dup_flag) )
2944 retval = pe_buffer;
2945 else SetLastError(WSAENOBUFS);
2947 else {
2948 MESSAGE("protocol %s not found; You might want to add "
2949 "this to /etc/protocols\n", debugstr_a(name) );
2950 SetLastError(WSANO_DATA);
2952 LeaveCriticalSection( &csWSgetXXXbyYYY );
2953 #endif
2954 return retval;
2957 /***********************************************************************
2958 * getprotobyname (WINSOCK.53)
2960 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2962 TRACE( "%s\n", debugstr_a(name) );
2963 if (!__ws_getprotobyname(name, WS_DUP_SEGPTR)) return 0;
2964 return pe_buffer_seg;
2967 /***********************************************************************
2968 * getprotobyname (WS2_32.53)
2970 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
2972 TRACE( "%s\n", debugstr_a(name) );
2973 return __ws_getprotobyname(name, WS_DUP_LINEAR);
2977 /***********************************************************************
2978 * __ws_getprotobynumber
2980 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2982 WIN_protoent* retval = NULL;
2983 #ifdef HAVE_GETPROTOBYNUMBER
2984 struct protoent* proto;
2985 EnterCriticalSection( &csWSgetXXXbyYYY );
2986 if( (proto = getprotobynumber(number)) != NULL )
2988 if( WS_dup_pe(proto, dup_flag) )
2989 retval = pe_buffer;
2990 else SetLastError(WSAENOBUFS);
2992 else {
2993 MESSAGE("protocol number %d not found; You might want to add "
2994 "this to /etc/protocols\n", number );
2995 SetLastError(WSANO_DATA);
2997 LeaveCriticalSection( &csWSgetXXXbyYYY );
2998 #endif
2999 return retval;
3002 /***********************************************************************
3003 * getprotobynumber (WINSOCK.54)
3005 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
3007 TRACE("%i\n", number);
3008 if (!__ws_getprotobynumber(number, WS_DUP_SEGPTR)) return 0;
3009 return pe_buffer_seg;
3012 /***********************************************************************
3013 * getprotobynumber (WS2_32.54)
3015 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
3017 TRACE("%i\n", number);
3018 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
3022 /***********************************************************************
3023 * __ws_getservbyname
3025 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
3027 WIN_servent* retval = NULL;
3028 struct servent* serv;
3029 int i = wsi_strtolo( name, proto );
3031 if( i ) {
3032 EnterCriticalSection( &csWSgetXXXbyYYY );
3033 serv = getservbyname(local_buffer,
3034 proto && *proto ? (local_buffer + i) : NULL);
3035 if( serv != NULL )
3037 if( WS_dup_se(serv, dup_flag) )
3038 retval = se_buffer;
3039 else SetLastError(WSAENOBUFS);
3041 else {
3042 MESSAGE("service %s protocol %s not found; You might want to add "
3043 "this to /etc/services\n", debugstr_a(local_buffer),
3044 proto ? debugstr_a(local_buffer+i):"*");
3045 SetLastError(WSANO_DATA);
3047 LeaveCriticalSection( &csWSgetXXXbyYYY );
3049 else SetLastError(WSAENOBUFS);
3050 return retval;
3053 /***********************************************************************
3054 * getservbyname (WINSOCK.55)
3056 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
3058 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3059 if (!__ws_getservbyname(name, proto, WS_DUP_SEGPTR)) return 0;
3060 return se_buffer_seg;
3063 /***********************************************************************
3064 * getservbyname (WS2_32.55)
3066 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
3068 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3069 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
3073 /***********************************************************************
3074 * __ws_getservbyport
3076 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
3078 WIN_servent* retval = NULL;
3079 #ifdef HAVE_GETSERVBYPORT
3080 struct servent* serv;
3081 if (!proto || wsi_strtolo( proto, NULL )) {
3082 EnterCriticalSection( &csWSgetXXXbyYYY );
3083 if( (serv = getservbyport(port, proto && *proto ? local_buffer :
3084 NULL)) != NULL ) {
3085 if( WS_dup_se(serv, dup_flag) )
3086 retval = se_buffer;
3087 else SetLastError(WSAENOBUFS);
3089 else {
3090 MESSAGE("service on port %lu protocol %s not found; You might want to add "
3091 "this to /etc/services\n", (unsigned long)ntohl(port),
3092 proto ? debugstr_a(local_buffer) : "*");
3093 SetLastError(WSANO_DATA);
3095 LeaveCriticalSection( &csWSgetXXXbyYYY );
3097 else SetLastError(WSAENOBUFS);
3098 #endif
3099 return retval;
3102 /***********************************************************************
3103 * getservbyport (WINSOCK.56)
3105 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
3107 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3108 if (!__ws_getservbyport(port, proto, WS_DUP_SEGPTR)) return 0;
3109 return se_buffer_seg;
3112 /***********************************************************************
3113 * getservbyport (WS2_32.56)
3115 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
3117 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3118 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
3122 /***********************************************************************
3123 * gethostname (WS2_32.57)
3125 int WINAPI WS_gethostname(char *name, int namelen)
3127 TRACE("name %p, len %d\n", name, namelen);
3129 if (gethostname(name, namelen) == 0)
3131 TRACE("<- '%s'\n", name);
3132 return 0;
3134 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
3135 TRACE("<- ERROR !\n");
3136 return SOCKET_ERROR;
3139 /***********************************************************************
3140 * gethostname (WINSOCK.57)
3142 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
3144 return (INT16)WS_gethostname(name, namelen);
3148 /* ------------------------------------- Windows sockets extensions -- *
3150 * ------------------------------------------------------------------- */
3152 /***********************************************************************
3153 * WSAEnumNetworkEvents (WS2_32.36)
3155 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
3157 int ret;
3159 TRACE("%08x, hEvent %p, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
3161 SERVER_START_REQ( get_socket_event )
3163 req->handle = SOCKET2HANDLE(s);
3164 req->service = TRUE;
3165 req->c_event = hEvent;
3166 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
3167 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
3169 SERVER_END_REQ;
3170 if (!ret) return 0;
3171 SetLastError(WSAEINVAL);
3172 return SOCKET_ERROR;
3175 /***********************************************************************
3176 * WSAEventSelect (WS2_32.39)
3178 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
3180 int ret;
3182 TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
3184 SERVER_START_REQ( set_socket_event )
3186 req->handle = SOCKET2HANDLE(s);
3187 req->mask = lEvent;
3188 req->event = hEvent;
3189 req->window = 0;
3190 req->msg = 0;
3191 ret = wine_server_call( req );
3193 SERVER_END_REQ;
3194 if (!ret) return 0;
3195 SetLastError(WSAEINVAL);
3196 return SOCKET_ERROR;
3199 /**********************************************************************
3200 * WSAGetOverlappedResult (WS2_32.40)
3202 BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
3203 LPDWORD lpcbTransfer, BOOL fWait,
3204 LPDWORD lpdwFlags )
3206 DWORD r;
3208 TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
3209 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
3211 if ( !(lpOverlapped && lpOverlapped->hEvent) )
3213 ERR ( "Invalid pointer\n" );
3214 WSASetLastError (WSA_INVALID_PARAMETER);
3215 return FALSE;
3218 if ( fWait )
3220 while ( WaitForSingleObjectEx (lpOverlapped->hEvent, INFINITE, TRUE) == STATUS_USER_APC );
3222 else if ( lpOverlapped->Internal == STATUS_PENDING )
3224 /* Wait in order to give APCs a chance to run. */
3225 /* This is cheating, so we must set the event again in case of success -
3226 it may be a non-manual reset event. */
3227 while ( (r = WaitForSingleObjectEx (lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
3228 if ( r == WAIT_OBJECT_0 )
3229 NtSetEvent ( lpOverlapped->hEvent, NULL );
3232 if ( lpcbTransfer )
3233 *lpcbTransfer = lpOverlapped->InternalHigh;
3235 if ( lpdwFlags )
3236 *lpdwFlags = lpOverlapped->Offset;
3238 switch ( lpOverlapped->Internal )
3240 case STATUS_SUCCESS:
3241 return TRUE;
3242 case STATUS_PENDING:
3243 WSASetLastError ( WSA_IO_INCOMPLETE );
3244 if (fWait) ERR ("PENDING status after waiting!\n");
3245 return FALSE;
3246 default:
3247 WSASetLastError ( NtStatusToWSAError ( lpOverlapped->Internal ));
3248 return FALSE;
3253 /***********************************************************************
3254 * WSAAsyncSelect (WS2_32.101)
3256 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
3258 int ret;
3260 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3262 SERVER_START_REQ( set_socket_event )
3264 req->handle = SOCKET2HANDLE(s);
3265 req->mask = lEvent;
3266 req->event = 0;
3267 req->window = hWnd;
3268 req->msg = uMsg;
3269 ret = wine_server_call( req );
3271 SERVER_END_REQ;
3272 if (!ret) return 0;
3273 SetLastError(WSAEINVAL);
3274 return SOCKET_ERROR;
3277 /***********************************************************************
3278 * WSAAsyncSelect (WINSOCK.101)
3280 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
3282 return (INT16)WSAAsyncSelect( s, HWND_32(hWnd), wMsg, lEvent );
3285 /***********************************************************************
3286 * WSARecvEx (WINSOCK.1107)
3288 * See description for WSARecvEx()
3290 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags)
3292 FIXME("(WSARecvEx16) partial packet return value not set \n");
3294 return WINSOCK_recv16(s, buf, len, *flags);
3298 /***********************************************************************
3299 * WSACreateEvent (WS2_32.31)
3302 WSAEVENT WINAPI WSACreateEvent(void)
3304 /* Create a manual-reset event, with initial state: unsignealed */
3305 TRACE("\n");
3307 return CreateEventA(NULL, TRUE, FALSE, NULL);
3310 /***********************************************************************
3311 * WSACloseEvent (WS2_32.29)
3314 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3316 TRACE ("event=%p\n", event);
3318 return CloseHandle(event);
3321 /***********************************************************************
3322 * WSASocketA (WS2_32.78)
3325 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3326 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3327 GROUP g, DWORD dwFlags)
3329 SOCKET ret;
3332 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
3333 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3336 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3337 af, type, protocol, lpProtocolInfo, g, dwFlags );
3339 /* hack for WSADuplicateSocket */
3340 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3341 ret = lpProtocolInfo->dwCatalogEntryId;
3342 TRACE("\tgot duplicate %04x\n", ret);
3343 return ret;
3346 /* check the socket family */
3347 switch(af)
3349 #ifdef HAVE_IPX
3350 case WS_AF_IPX: af = AF_IPX;
3351 #endif
3352 case AF_INET:
3353 case AF_UNSPEC:
3354 break;
3355 default:
3356 SetLastError(WSAEAFNOSUPPORT);
3357 return INVALID_SOCKET;
3360 /* check the socket type */
3361 switch(type)
3363 case WS_SOCK_STREAM:
3364 type=SOCK_STREAM;
3365 break;
3366 case WS_SOCK_DGRAM:
3367 type=SOCK_DGRAM;
3368 break;
3369 case WS_SOCK_RAW:
3370 type=SOCK_RAW;
3371 break;
3372 default:
3373 SetLastError(WSAESOCKTNOSUPPORT);
3374 return INVALID_SOCKET;
3377 /* check the protocol type */
3378 if ( protocol < 0 ) /* don't support negative values */
3380 SetLastError(WSAEPROTONOSUPPORT);
3381 return INVALID_SOCKET;
3384 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3385 switch(protocol)
3387 case IPPROTO_TCP:
3388 if (type == SOCK_STREAM) { af = AF_INET; break; }
3389 case IPPROTO_UDP:
3390 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3391 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3394 SERVER_START_REQ( create_socket )
3396 req->family = af;
3397 req->type = type;
3398 req->protocol = protocol;
3399 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3400 req->flags = dwFlags;
3401 req->inherit = TRUE;
3402 set_error( wine_server_call( req ) );
3403 ret = HANDLE2SOCKET( reply->handle );
3405 SERVER_END_REQ;
3406 if (ret)
3408 TRACE("\tcreated %04x\n", ret );
3409 return ret;
3412 if (GetLastError() == WSAEACCES) /* raw socket denied */
3414 if (type == SOCK_RAW)
3415 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3416 else
3417 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3418 SetLastError(WSAESOCKTNOSUPPORT);
3421 WARN("\t\tfailed!\n");
3422 return INVALID_SOCKET;
3426 /***********************************************************************
3427 * __WSAFDIsSet (WINSOCK.151)
3429 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
3431 int i = set->fd_count;
3433 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3435 while (i--)
3436 if (set->fd_array[i] == s) return 1;
3437 return 0;
3440 /***********************************************************************
3441 * __WSAFDIsSet (WS2_32.151)
3443 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3445 int i = set->fd_count;
3447 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3449 while (i--)
3450 if (set->fd_array[i] == s) return 1;
3451 return 0;
3454 /***********************************************************************
3455 * WSAIsBlocking (WINSOCK.114)
3456 * WSAIsBlocking (WS2_32.114)
3458 BOOL WINAPI WSAIsBlocking(void)
3460 /* By default WinSock should set all its sockets to non-blocking mode
3461 * and poll in PeekMessage loop when processing "blocking" ones. This
3462 * function is supposed to tell if the program is in this loop. Our
3463 * blocking calls are truly blocking so we always return FALSE.
3465 * Note: It is allowed to call this function without prior WSAStartup().
3468 TRACE("\n");
3469 return FALSE;
3472 /***********************************************************************
3473 * WSACancelBlockingCall (WINSOCK.113)
3474 * WSACancelBlockingCall (WS2_32.113)
3476 INT WINAPI WSACancelBlockingCall(void)
3478 TRACE("\n");
3479 return 0;
3483 /***********************************************************************
3484 * WSASetBlockingHook (WINSOCK.109)
3486 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
3488 FARPROC16 prev = (FARPROC16)blocking_hook;
3489 blocking_hook = (FARPROC)lpBlockFunc;
3490 TRACE("hook %p\n", lpBlockFunc);
3491 return prev;
3495 /***********************************************************************
3496 * WSASetBlockingHook (WS2_32.109)
3498 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3500 FARPROC prev = blocking_hook;
3501 blocking_hook = lpBlockFunc;
3502 TRACE("hook %p\n", lpBlockFunc);
3503 return prev;
3507 /***********************************************************************
3508 * WSAUnhookBlockingHook (WINSOCK.110)
3510 INT16 WINAPI WSAUnhookBlockingHook16(void)
3512 blocking_hook = NULL;
3513 return 0;
3517 /***********************************************************************
3518 * WSAUnhookBlockingHook (WS2_32.110)
3520 INT WINAPI WSAUnhookBlockingHook(void)
3522 blocking_hook = NULL;
3523 return 0;
3527 /* ----------------------------------- end of API stuff */
3529 /* ----------------------------------- helper functions -
3531 * TODO: Merge WS_dup_..() stuff into one function that
3532 * would operate with a generic structure containing internal
3533 * pointers (via a template of some kind).
3536 static int list_size(char** l, int item_size)
3538 int i,j = 0;
3539 if(l)
3540 { for(i=0;l[i];i++)
3541 j += (item_size) ? item_size : strlen(l[i]) + 1;
3542 j += (i + 1) * sizeof(char*); }
3543 return j;
3546 static int list_dup(char** l_src, char* ref, char* base, int item_size)
3548 /* base is either either equal to ref or 0 or SEGPTR */
3550 char* p = ref;
3551 char** l_to = (char**)ref;
3552 int i,j,k;
3554 for(j=0;l_src[j];j++) ;
3555 p += (j + 1) * sizeof(char*);
3556 for(i=0;i<j;i++)
3557 { l_to[i] = base + (p - ref);
3558 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3559 memcpy(p, l_src[i], k); p += k; }
3560 l_to[i] = NULL;
3561 return (p - ref);
3564 /* ----- hostent */
3566 static int hostent_size(struct hostent* p_he)
3568 int size = 0;
3569 if( p_he )
3570 { size = sizeof(struct hostent);
3571 size += strlen(p_he->h_name) + 1;
3572 size += list_size(p_he->h_aliases, 0);
3573 size += list_size(p_he->h_addr_list, p_he->h_length ); }
3574 return size;
3577 /* duplicate hostent entry
3578 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3579 * Dito for protoent and servent.
3581 static int WS_dup_he(struct hostent* p_he, int flag)
3583 /* Convert hostent structure into ws_hostent so that the data fits
3584 * into local_buffer. Internal pointers can be linear, SEGPTR, or
3585 * relative to local_buffer depending on "flag" value. Returns size
3586 * of the data copied.
3589 int size = hostent_size(p_he);
3590 if( size )
3592 char *p_name,*p_aliases,*p_addr,*p_base,*p;
3593 char *p_to;
3594 struct ws_hostent16 *p_to16;
3595 struct WS_hostent *p_to32;
3597 check_buffer_he(size);
3598 p_to = he_buffer;
3599 p_to16 = he_buffer;
3600 p_to32 = he_buffer;
3602 p = p_to;
3603 p_base = (flag & WS_DUP_SEGPTR) ? (char*)he_buffer_seg : he_buffer;
3604 p += (flag & WS_DUP_SEGPTR) ?
3605 sizeof(struct ws_hostent16) : sizeof(struct WS_hostent);
3606 p_name = p;
3607 strcpy(p, p_he->h_name); p += strlen(p) + 1;
3608 p_aliases = p;
3609 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3610 p_addr = p;
3611 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
3613 if (flag & WS_DUP_SEGPTR) /* Win16 */
3615 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
3616 p_to16->h_length = (INT16)p_he->h_length;
3617 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3618 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3619 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3620 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3622 else /* Win32 */
3624 p_to32->h_addrtype = p_he->h_addrtype;
3625 p_to32->h_length = p_he->h_length;
3626 p_to32->h_name = (p_base + (p_name - p_to));
3627 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3628 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3629 size += (sizeof(struct WS_hostent) - sizeof(struct hostent));
3632 return size;
3635 /* ----- protoent */
3637 static int protoent_size(struct protoent* p_pe)
3639 int size = 0;
3640 if( p_pe )
3641 { size = sizeof(struct protoent);
3642 size += strlen(p_pe->p_name) + 1;
3643 size += list_size(p_pe->p_aliases, 0); }
3644 return size;
3647 static int WS_dup_pe(struct protoent* p_pe, int flag)
3649 int size = protoent_size(p_pe);
3650 if( size )
3652 char *p_to;
3653 struct ws_protoent16 *p_to16;
3654 struct WS_protoent *p_to32;
3655 char *p_name,*p_aliases,*p_base,*p;
3657 check_buffer_pe(size);
3658 p_to = pe_buffer;
3659 p_to16 = pe_buffer;
3660 p_to32 = pe_buffer;
3661 p = p_to;
3662 p_base = (flag & WS_DUP_SEGPTR) ? (char*)pe_buffer_seg : pe_buffer;
3663 p += (flag & WS_DUP_SEGPTR) ?
3664 sizeof(struct ws_protoent16) : sizeof(struct WS_protoent);
3665 p_name = p;
3666 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3667 p_aliases = p;
3668 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3670 if (flag & WS_DUP_SEGPTR) /* Win16 */
3672 p_to16->p_proto = (INT16)p_pe->p_proto;
3673 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3674 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3675 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3677 else /* Win32 */
3679 p_to32->p_proto = p_pe->p_proto;
3680 p_to32->p_name = (p_base) + (p_name - p_to);
3681 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3682 size += (sizeof(struct WS_protoent) - sizeof(struct protoent));
3685 return size;
3688 /* ----- servent */
3690 static int servent_size(struct servent* p_se)
3692 int size = 0;
3693 if( p_se )
3694 { size += sizeof(struct servent);
3695 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3696 size += list_size(p_se->s_aliases, 0); }
3697 return size;
3700 static int WS_dup_se(struct servent* p_se, int flag)
3702 int size = servent_size(p_se);
3703 if( size )
3705 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3706 char *p_to;
3707 struct ws_servent16 *p_to16;
3708 struct WS_servent *p_to32;
3710 check_buffer_se(size);
3711 p_to = se_buffer;
3712 p_to16 = se_buffer;
3713 p_to32 = se_buffer;
3714 p = p_to;
3715 p_base = (flag & WS_DUP_SEGPTR) ? (char*)se_buffer_seg : se_buffer;
3716 p += (flag & WS_DUP_SEGPTR) ?
3717 sizeof(struct ws_servent16) : sizeof(struct WS_servent);
3718 p_name = p;
3719 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3720 p_proto = p;
3721 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3722 p_aliases = p;
3723 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3725 if (flag & WS_DUP_SEGPTR) /* Win16 */
3727 p_to16->s_port = (INT16)p_se->s_port;
3728 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3729 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3730 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3731 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3733 else /* Win32 */
3735 p_to32->s_port = p_se->s_port;
3736 p_to32->s_name = (p_base + (p_name - p_to));
3737 p_to32->s_proto = (p_base + (p_proto - p_to));
3738 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3739 size += (sizeof(struct WS_servent) - sizeof(struct servent));
3742 return size;
3745 /* ----------------------------------- error handling */
3747 UINT16 wsaErrno(void)
3749 int loc_errno = errno;
3750 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3752 switch(loc_errno)
3754 case EINTR: return WSAEINTR;
3755 case EBADF: return WSAEBADF;
3756 case EPERM:
3757 case EACCES: return WSAEACCES;
3758 case EFAULT: return WSAEFAULT;
3759 case EINVAL: return WSAEINVAL;
3760 case EMFILE: return WSAEMFILE;
3761 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3762 case EINPROGRESS: return WSAEINPROGRESS;
3763 case EALREADY: return WSAEALREADY;
3764 case ENOTSOCK: return WSAENOTSOCK;
3765 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3766 case EMSGSIZE: return WSAEMSGSIZE;
3767 case EPROTOTYPE: return WSAEPROTOTYPE;
3768 case ENOPROTOOPT: return WSAENOPROTOOPT;
3769 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3770 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3771 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3772 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3773 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3774 case EADDRINUSE: return WSAEADDRINUSE;
3775 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3776 case ENETDOWN: return WSAENETDOWN;
3777 case ENETUNREACH: return WSAENETUNREACH;
3778 case ENETRESET: return WSAENETRESET;
3779 case ECONNABORTED: return WSAECONNABORTED;
3780 case EPIPE:
3781 case ECONNRESET: return WSAECONNRESET;
3782 case ENOBUFS: return WSAENOBUFS;
3783 case EISCONN: return WSAEISCONN;
3784 case ENOTCONN: return WSAENOTCONN;
3785 case ESHUTDOWN: return WSAESHUTDOWN;
3786 case ETOOMANYREFS: return WSAETOOMANYREFS;
3787 case ETIMEDOUT: return WSAETIMEDOUT;
3788 case ECONNREFUSED: return WSAECONNREFUSED;
3789 case ELOOP: return WSAELOOP;
3790 case ENAMETOOLONG: return WSAENAMETOOLONG;
3791 case EHOSTDOWN: return WSAEHOSTDOWN;
3792 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3793 case ENOTEMPTY: return WSAENOTEMPTY;
3794 #ifdef EPROCLIM
3795 case EPROCLIM: return WSAEPROCLIM;
3796 #endif
3797 #ifdef EUSERS
3798 case EUSERS: return WSAEUSERS;
3799 #endif
3800 #ifdef EDQUOT
3801 case EDQUOT: return WSAEDQUOT;
3802 #endif
3803 #ifdef ESTALE
3804 case ESTALE: return WSAESTALE;
3805 #endif
3806 #ifdef EREMOTE
3807 case EREMOTE: return WSAEREMOTE;
3808 #endif
3810 /* just in case we ever get here and there are no problems */
3811 case 0: return 0;
3812 default:
3813 WARN("Unknown errno %d!\n", loc_errno);
3814 return WSAEOPNOTSUPP;
3818 UINT16 wsaHerrno(int loc_errno)
3821 WARN("h_errno %d.\n", loc_errno);
3823 switch(loc_errno)
3825 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3826 case TRY_AGAIN: return WSATRY_AGAIN;
3827 case NO_RECOVERY: return WSANO_RECOVERY;
3828 case NO_DATA: return WSANO_DATA;
3829 case ENOBUFS: return WSAENOBUFS;
3831 case 0: return 0;
3832 default:
3833 WARN("Unknown h_errno %d!\n", loc_errno);
3834 return WSAEOPNOTSUPP;
3839 /***********************************************************************
3840 * WSARecv (WS2_32.67)
3842 int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3843 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3844 LPWSAOVERLAPPED lpOverlapped,
3845 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3847 return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3848 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3851 /***********************************************************************
3852 * WSARecvFrom (WS2_32.69)
3854 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3855 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3856 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3857 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3860 int i, n, fd, err = WSAENOTSOCK, flags, ret;
3861 struct iovec* iovec;
3862 struct ws2_async *wsa;
3863 enum fd_type type;
3865 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3866 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3867 (lpFromlen ? *lpFromlen : -1L),
3868 lpOverlapped, lpCompletionRoutine);
3870 fd = _get_sock_fd_type( s, GENERIC_READ, &type, &flags );
3871 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
3873 if (fd == -1)
3875 err = WSAGetLastError ();
3876 goto error;
3879 iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3880 if ( !iovec )
3882 err = WSAEFAULT;
3883 goto err_close;
3886 for (i = 0; i < dwBufferCount; i++)
3888 iovec[i].iov_base = lpBuffers[i].buf;
3889 iovec[i].iov_len = lpBuffers[i].len;
3892 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3894 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
3895 lpFlags, lpFrom, lpFromlen,
3896 lpOverlapped, lpCompletionRoutine );
3898 if ( !wsa )
3900 err = WSAEFAULT;
3901 goto err_free;
3904 if ( ( ret = register_new_async ( &wsa->async )) )
3906 err = NtStatusToWSAError ( ret );
3908 if ( !lpOverlapped )
3909 HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
3910 HeapFree ( GetProcessHeap(), 0, wsa );
3911 goto err_free;
3914 /* Try immediate completion */
3915 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
3917 if ( WSAGetOverlappedResult ( s, lpOverlapped,
3918 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3919 return 0;
3921 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
3922 goto error;
3925 WSASetLastError ( WSA_IO_PENDING );
3926 return SOCKET_ERROR;
3929 if ( _is_blocking(s) )
3931 /* block here */
3932 /* FIXME: OOB and exceptfds? */
3933 do_block(fd, 1);
3936 n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3937 if ( n == -1 )
3939 err = wsaErrno();
3940 goto err_free;
3943 TRACE(" -> %i bytes\n", n);
3944 *lpNumberOfBytesRecvd = n;
3946 HeapFree (GetProcessHeap(), 0, iovec);
3947 close(fd);
3948 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3950 return 0;
3952 err_free:
3953 HeapFree (GetProcessHeap(), 0, iovec);
3955 err_close:
3956 close (fd);
3958 error:
3959 WARN(" -> ERROR %d\n", err);
3960 WSASetLastError ( err );
3961 return SOCKET_ERROR;
3964 /***********************************************************************
3965 * WSCInstallProvider (WS2_32.88)
3967 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
3968 LPCWSTR lpszProviderDllPath,
3969 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
3970 DWORD dwNumberOfEntries,
3971 LPINT lpErrno )
3973 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
3974 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
3975 dwNumberOfEntries, lpErrno);
3976 *lpErrno = 0;
3977 return 0;
3981 /***********************************************************************
3982 * WSCDeinstallProvider (WS2_32.83)
3984 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
3986 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
3987 *lpErrno = 0;
3988 return 0;
3992 /***********************************************************************
3993 * WSAAccept (WS2_32.26)
3995 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
3996 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
3999 int ret = 0, size = 0;
4000 WSABUF CallerId, CallerData, CalleeId, CalleeData;
4001 /* QOS SQOS, GQOS; */
4002 GROUP g;
4003 SOCKET cs;
4004 SOCKADDR src_addr, dst_addr;
4006 TRACE("Socket %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
4007 s, addr, addrlen, lpfnCondition, dwCallbackData);
4010 size = sizeof(src_addr);
4011 cs = WS_accept(s, &src_addr, &size);
4013 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
4015 CallerId.buf = (char *)&src_addr;
4016 CallerId.len = sizeof(src_addr);
4018 CallerData.buf = NULL;
4019 CallerData.len = (ULONG)NULL;
4021 WS_getsockname(cs, &dst_addr, &size);
4023 CalleeId.buf = (char *)&dst_addr;
4024 CalleeId.len = sizeof(dst_addr);
4027 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
4028 &CalleeId, &CalleeData, &g, dwCallbackData);
4030 switch (ret)
4032 case CF_ACCEPT:
4033 if (addr && addrlen)
4034 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
4035 return cs;
4036 case CF_DEFER:
4037 SERVER_START_REQ ( set_socket_deferred )
4039 req->handle = SOCKET2HANDLE (s);
4040 req->deferred = SOCKET2HANDLE (cs);
4041 if ( !wine_server_call_err ( req ) )
4043 SetLastError ( WSATRY_AGAIN );
4044 WS_closesocket ( cs );
4047 SERVER_END_REQ;
4048 return SOCKET_ERROR;
4049 case CF_REJECT:
4050 WS_closesocket(cs);
4051 SetLastError(WSAECONNREFUSED);
4052 return SOCKET_ERROR;
4053 default:
4054 FIXME("Unknown return type from Condition function\n");
4055 SetLastError(WSAENOTSOCK);
4056 return SOCKET_ERROR;
4060 /***********************************************************************
4061 * WSAEnumProtocolsA (WS2_32.37)
4063 int WINAPI WSAEnumProtocolsA(LPINT lpiProtocols, LPWSAPROTOCOL_INFOA lpProtocolBuffer, LPDWORD lpdwBufferLength)
4065 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4066 return 0;
4069 /***********************************************************************
4070 * WSAEnumProtocolsW (WS2_32.38)
4072 int WINAPI WSAEnumProtocolsW(LPINT lpiProtocols, LPWSAPROTOCOL_INFOW lpProtocolBuffer, LPDWORD lpdwBufferLength)
4074 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4075 return 0;
4078 /***********************************************************************
4079 * WSADuplicateSocketA (WS2_32.32)
4081 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
4083 HANDLE hProcess;
4085 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
4086 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
4087 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
4088 /* I don't know what the real Windoze does next, this is a hack */
4089 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
4090 * the target use the global duplicate, or we could copy a reference to us to the structure
4091 * and let the target duplicate it from us, but let's do it as simple as possible */
4092 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
4093 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
4094 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
4095 0, FALSE, DUPLICATE_SAME_ACCESS);
4096 CloseHandle(hProcess);
4097 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
4098 return 0;
4101 /***********************************************************************
4102 * WSAInstallServiceClassA (WS2_32.48)
4104 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
4106 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
4107 WSASetLastError(WSAEACCES);
4108 return SOCKET_ERROR;
4111 /***********************************************************************
4112 * WSAInstallServiceClassW (WS2_32.49)
4114 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
4116 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
4117 WSASetLastError(WSAEACCES);
4118 return SOCKET_ERROR;
4121 /***********************************************************************
4122 * WSARemoveServiceClass (WS2_32.70)
4124 int WINAPI WSARemoveServiceClass(LPGUID info)
4126 FIXME("Request to remove service %p\n",info);
4127 WSASetLastError(WSATYPE_NOT_FOUND);
4128 return SOCKET_ERROR;