Fixed header dependencies to be fully compatible with the Windows
[wine/multimedia.git] / dlls / winsock / socket.c
blobe59bd735b7a7ef123fa42596e759d5a4cee2412b
1 /*
2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
5 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * NOTE: If you make any changes to fix a particular app, make sure
22 * they don't break something else like Netscape or telnet and ftp
23 * clients and servers (www.winsite.com got a lot of those).
26 #include "config.h"
27 #include "wine/port.h"
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #ifdef HAVE_SYS_IPC_H
34 # include <sys/ipc.h>
35 #endif
36 #ifdef HAVE_SYS_IOCTL_H
37 # include <sys/ioctl.h>
38 #endif
39 #ifdef HAVE_SYS_FILIO_H
40 # include <sys/filio.h>
41 #endif
42 #ifdef HAVE_SYS_SOCKIO_H
43 # include <sys/sockio.h>
44 #endif
46 #if defined(__EMX__)
47 # include <sys/so_ioctl.h>
48 #endif
50 #ifdef HAVE_SYS_PARAM_H
51 # include <sys/param.h>
52 #endif
54 #ifdef HAVE_SYS_MSG_H
55 # include <sys/msg.h>
56 #endif
57 #ifdef HAVE_SYS_WAIT_H
58 # include <sys/wait.h>
59 #endif
60 #ifdef HAVE_SYS_UIO_H
61 # include <sys/uio.h>
62 #endif
63 #ifdef HAVE_SYS_SOCKET_H
64 #include <sys/socket.h>
65 #endif
66 #ifdef HAVE_NETINET_IN_H
67 # include <netinet/in.h>
68 #endif
69 #ifdef HAVE_NETINET_TCP_H
70 # include <netinet/tcp.h>
71 #endif
72 #ifdef HAVE_ARPA_INET_H
73 # include <arpa/inet.h>
74 #endif
75 #include <ctype.h>
76 #include <fcntl.h>
77 #include <errno.h>
78 #ifdef HAVE_SYS_ERRNO_H
79 #include <sys/errno.h>
80 #endif
81 #ifdef HAVE_NETDB_H
82 #include <netdb.h>
83 #endif
84 #ifdef HAVE_UNISTD_H
85 # include <unistd.h>
86 #endif
87 #include <stdlib.h>
88 #ifdef HAVE_ARPA_NAMESER_H
89 # include <arpa/nameser.h>
90 #endif
91 #ifdef HAVE_RESOLV_H
92 # include <resolv.h>
93 #endif
94 #ifdef HAVE_NET_IF_H
95 # include <net/if.h>
96 #endif
97 #ifdef HAVE_IPX_GNU
98 # include <netipx/ipx.h>
99 # define HAVE_IPX
100 #endif
101 #ifdef HAVE_IPX_LINUX
102 # include <asm/types.h>
103 # include <linux/ipx.h>
104 # define HAVE_IPX
105 #endif
107 #ifdef HAVE_SYS_POLL_H
108 # include <sys/poll.h>
109 #endif
110 #ifdef HAVE_SYS_TIME_H
111 # include <sys/time.h>
112 #endif
114 #define NONAMELESSUNION
115 #define NONAMELESSSTRUCT
116 #include "wine/winbase16.h"
117 #include "windef.h"
118 #include "winbase.h"
119 #include "wingdi.h"
120 #include "winuser.h"
121 #include "winerror.h"
122 #include "winsock2.h"
123 #include "ws2tcpip.h"
124 #include "wsipx.h"
125 #include "wine/winsock16.h"
126 #include "winnt.h"
127 #include "wownt32.h"
128 #include "iphlpapi.h"
129 #include "thread.h"
130 #include "wine/server.h"
131 #include "wine/debug.h"
133 #ifdef __FreeBSD__
134 # define sipx_network sipx_addr.x_net
135 # define sipx_node sipx_addr.x_host.c_host
136 #endif /* __FreeBSD__ */
138 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
140 /* critical section to protect some non-rentrant net function */
141 extern CRITICAL_SECTION csWSgetXXXbyYYY;
143 #define DEBUG_SOCKADDR 0
144 #define dump_sockaddr(a) \
145 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
146 ((struct sockaddr_in *)a)->sin_family, \
147 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
148 ntohs(((struct sockaddr_in *)a)->sin_port))
150 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
151 #define SOCKET2HANDLE(s) ((HANDLE)(s))
152 #define HANDLE2SOCKET(h) ((SOCKET)(h))
154 /****************************************************************
155 * Async IO declarations
156 ****************************************************************/
157 #include "async.h"
159 static DWORD ws2_async_get_count (const struct async_private *ovp);
160 static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
161 static void ws2_async_cleanup ( struct async_private *ovp );
163 static struct async_ops ws2_async_ops =
165 ws2_async_get_count,
166 ws2_async_call_completion,
167 ws2_async_cleanup
170 static struct async_ops ws2_nocomp_async_ops =
172 ws2_async_get_count,
173 NULL, /* call_completion */
174 ws2_async_cleanup
177 typedef struct ws2_async
179 async_private async;
180 LPWSAOVERLAPPED user_overlapped;
181 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
182 struct iovec *iovec;
183 int n_iovecs;
184 struct WS_sockaddr *addr;
185 union {
186 int val; /* for send operations */
187 int *ptr; /* for recv operations */
188 } addrlen;
189 DWORD flags;
190 } ws2_async;
192 /****************************************************************/
194 /* ----------------------------------- internal data */
196 /* ws_... struct conversion flags */
198 #define WS_DUP_LINEAR 0x0001
199 #define WS_DUP_SEGPTR 0x0002 /* internal pointers are SEGPTRs */
200 /* by default, internal pointers are linear */
201 typedef struct /* WSAAsyncSelect() control struct */
203 HANDLE service, event, sock;
204 HWND hWnd;
205 UINT uMsg;
206 LONG lEvent;
207 } ws_select_info;
209 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
210 #define WS_MAX_UDP_DATAGRAM 1024
211 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
213 static void *he_buffer; /* typecast for Win16/32 ws_hostent */
214 static SEGPTR he_buffer_seg;
215 static void *se_buffer; /* typecast for Win16/32 ws_servent */
216 static SEGPTR se_buffer_seg;
217 static void *pe_buffer; /* typecast for Win16/32 ws_protoent */
218 static SEGPTR pe_buffer_seg;
219 static char* local_buffer;
220 static SEGPTR dbuffer_seg;
221 static INT num_startup; /* reference counter */
222 static FARPROC blocking_hook = WSA_DefaultBlockingHook;
224 /* function prototypes */
225 static int WS_dup_he(struct hostent* p_he, int flag);
226 static int WS_dup_pe(struct protoent* p_pe, int flag);
227 static int WS_dup_se(struct servent* p_se, int flag);
229 typedef void WIN_hostent;
230 typedef void WIN_protoent;
231 typedef void WIN_servent;
233 int WSAIOCTL_GetInterfaceCount(void);
234 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
236 UINT16 wsaErrno(void);
237 UINT16 wsaHerrno(int errnr);
239 static HANDLE _WSHeap = 0;
241 #define WS_ALLOC(size) \
242 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
243 #define WS_FREE(ptr) \
244 HeapFree(_WSHeap, 0, (ptr) )
246 #define MAP_OPTION(opt) { WS_##opt, opt }
248 static const int ws_sock_map[][2] =
250 MAP_OPTION( SO_DEBUG ),
251 MAP_OPTION( SO_REUSEADDR ),
252 MAP_OPTION( SO_KEEPALIVE ),
253 MAP_OPTION( SO_DONTROUTE ),
254 MAP_OPTION( SO_BROADCAST ),
255 MAP_OPTION( SO_LINGER ),
256 MAP_OPTION( SO_OOBINLINE ),
257 MAP_OPTION( SO_SNDBUF ),
258 MAP_OPTION( SO_RCVBUF ),
259 MAP_OPTION( SO_ERROR ),
260 MAP_OPTION( SO_TYPE ),
261 #ifdef SO_RCVTIMEO
262 MAP_OPTION( SO_RCVTIMEO ),
263 #endif
264 #ifdef SO_SNDTIMEO
265 MAP_OPTION( SO_SNDTIMEO ),
266 #endif
267 { 0, 0 }
270 static const int ws_tcp_map[][2] =
272 #ifdef TCP_NODELAY
273 MAP_OPTION( TCP_NODELAY ),
274 #endif
275 { 0, 0 }
278 static const int ws_ip_map[][2] =
280 MAP_OPTION( IP_MULTICAST_IF ),
281 MAP_OPTION( IP_MULTICAST_TTL ),
282 MAP_OPTION( IP_MULTICAST_LOOP ),
283 MAP_OPTION( IP_ADD_MEMBERSHIP ),
284 MAP_OPTION( IP_DROP_MEMBERSHIP ),
285 MAP_OPTION( IP_OPTIONS ),
286 MAP_OPTION( IP_HDRINCL ),
287 MAP_OPTION( IP_TOS ),
288 MAP_OPTION( IP_TTL ),
289 { 0, 0 }
292 static DWORD opentype_tls_index = -1; /* TLS index for SO_OPENTYPE flag */
294 inline static DWORD NtStatusToWSAError ( const DWORD status )
296 /* We only need to cover the status codes set by server async request handling */
297 DWORD wserr;
298 switch ( status )
300 case STATUS_SUCCESS: wserr = 0; break;
301 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
302 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
303 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
304 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
305 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
306 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
307 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
308 default:
309 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
310 /* It is not a NT status code but a winsock error */
311 wserr = status;
312 else
314 wserr = RtlNtStatusToDosError( status );
315 FIXME ( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
318 return wserr;
321 /* set last error code from NT status without mapping WSA errors */
322 inline static unsigned int set_error( unsigned int err )
324 if (err)
326 err = NtStatusToWSAError ( err );
327 SetLastError( err );
329 return err;
332 static char* check_buffer(int size);
334 inline static int _get_sock_fd(SOCKET s)
336 int fd;
338 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), GENERIC_READ, &fd, NULL, NULL ) ))
339 return -1;
340 return fd;
343 inline static int _get_sock_fd_type( SOCKET s, DWORD access, enum fd_type *type, int *flags )
345 int fd;
346 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, type, flags ) )) return -1;
347 if ( ( (access & GENERIC_READ) && (*flags & FD_FLAG_RECV_SHUTDOWN ) ) ||
348 ( (access & GENERIC_WRITE) && (*flags & FD_FLAG_SEND_SHUTDOWN ) ) )
350 close (fd);
351 WSASetLastError ( WSAESHUTDOWN );
352 return -1;
354 return fd;
357 static void _enable_event( HANDLE s, unsigned int event,
358 unsigned int sstate, unsigned int cstate )
360 SERVER_START_REQ( enable_socket_event )
362 req->handle = s;
363 req->mask = event;
364 req->sstate = sstate;
365 req->cstate = cstate;
366 wine_server_call( req );
368 SERVER_END_REQ;
371 static int _is_blocking(SOCKET s)
373 int ret;
374 SERVER_START_REQ( get_socket_event )
376 req->handle = SOCKET2HANDLE(s);
377 req->service = FALSE;
378 req->c_event = 0;
379 wine_server_call( req );
380 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
382 SERVER_END_REQ;
383 return ret;
386 static unsigned int _get_sock_mask(SOCKET s)
388 unsigned int ret;
389 SERVER_START_REQ( get_socket_event )
391 req->handle = SOCKET2HANDLE(s);
392 req->service = FALSE;
393 req->c_event = 0;
394 wine_server_call( req );
395 ret = reply->mask;
397 SERVER_END_REQ;
398 return ret;
401 static void _sync_sock_state(SOCKET s)
403 /* do a dummy wineserver request in order to let
404 the wineserver run through its select loop once */
405 (void)_is_blocking(s);
408 static int _get_sock_error(SOCKET s, unsigned int bit)
410 int events[FD_MAX_EVENTS];
412 SERVER_START_REQ( get_socket_event )
414 req->handle = SOCKET2HANDLE(s);
415 req->service = FALSE;
416 req->c_event = 0;
417 wine_server_set_reply( req, events, sizeof(events) );
418 wine_server_call( req );
420 SERVER_END_REQ;
421 return events[bit];
424 static void WINSOCK_DeleteIData(void)
426 /* delete scratch buffers */
428 UnMapLS( he_buffer_seg );
429 UnMapLS( se_buffer_seg );
430 UnMapLS( pe_buffer_seg );
431 UnMapLS( dbuffer_seg );
432 if (he_buffer) HeapFree( GetProcessHeap(), 0, he_buffer );
433 if (se_buffer) HeapFree( GetProcessHeap(), 0, se_buffer );
434 if (pe_buffer) HeapFree( GetProcessHeap(), 0, pe_buffer );
435 if (local_buffer) HeapFree( GetProcessHeap(), 0, local_buffer );
436 he_buffer = NULL;
437 se_buffer = NULL;
438 pe_buffer = NULL;
439 local_buffer = NULL;
440 he_buffer_seg = 0;
441 se_buffer_seg = 0;
442 pe_buffer_seg = 0;
443 dbuffer_seg = 0;
444 num_startup = 0;
447 /***********************************************************************
448 * DllMain (WS2_32.init)
450 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
452 TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
453 switch (fdwReason) {
454 case DLL_PROCESS_ATTACH:
455 DisableThreadLibraryCalls(hInstDLL);
456 opentype_tls_index = TlsAlloc();
457 break;
458 case DLL_PROCESS_DETACH:
459 TlsFree( opentype_tls_index );
460 WINSOCK_DeleteIData();
461 break;
463 return TRUE;
466 /***********************************************************************
467 * convert_sockopt()
469 * Converts socket flags from Windows format.
470 * Return 1 if converted, 0 if not (error).
472 static int convert_sockopt(INT *level, INT *optname)
474 int i;
475 switch (*level)
477 case WS_SOL_SOCKET:
478 *level = SOL_SOCKET;
479 for(i=0; ws_sock_map[i][0]; i++)
481 if( ws_sock_map[i][0] == *optname )
483 *optname = ws_sock_map[i][1];
484 return 1;
487 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
488 break;
489 case WS_IPPROTO_TCP:
490 *level = IPPROTO_TCP;
491 for(i=0; ws_tcp_map[i][0]; i++)
493 if ( ws_tcp_map[i][0] == *optname )
495 *optname = ws_tcp_map[i][1];
496 return 1;
499 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
500 break;
501 case WS_IPPROTO_IP:
502 *level = IPPROTO_IP;
503 for(i=0; ws_ip_map[i][0]; i++)
505 if (ws_ip_map[i][0] == *optname )
507 *optname = ws_ip_map[i][1];
508 return 1;
511 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
512 break;
513 default: FIXME("Unimplemented or unknown socket level\n");
515 return 0;
518 /* ----------------------------------- Per-thread info (or per-process?) */
520 static int wsi_strtolo(const char* name, const char* opt)
522 /* Stuff a lowercase copy of the string into the local buffer */
524 int i = strlen(name) + 2;
525 char* p = check_buffer(i + ((opt)?strlen(opt):0));
527 if( p )
529 do *p++ = tolower(*name); while(*name++);
530 i = (p - local_buffer);
531 if( opt ) do *p++ = tolower(*opt); while(*opt++);
532 return i;
534 return 0;
537 static fd_set* fd_set_import( fd_set* fds, void* wsfds, int* highfd, int lfd[], BOOL b32 )
539 /* translate Winsock fd set into local fd set */
541 if( wsfds )
543 #define wsfds16 ((ws_fd_set16*)wsfds)
544 #define wsfds32 ((WS_fd_set*)wsfds)
545 int i, count;
547 FD_ZERO(fds);
548 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
550 for( i = 0; i < count; i++ )
552 int s = (b32) ? wsfds32->fd_array[i]
553 : wsfds16->fd_array[i];
554 int fd = _get_sock_fd(s);
555 if (fd != -1)
557 lfd[ i ] = fd;
558 if( fd > *highfd ) *highfd = fd;
559 FD_SET(fd, fds);
561 else lfd[ i ] = -1;
563 #undef wsfds32
564 #undef wsfds16
565 return fds;
567 return NULL;
570 inline static int sock_error_p(int s)
572 unsigned int optval, optlen;
574 optlen = sizeof(optval);
575 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
576 if (optval) WARN("\t[%i] error: %d\n", s, optval);
577 return optval != 0;
580 static int fd_set_export( fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
582 int num_err = 0;
584 /* translate local fd set into Winsock fd set, adding
585 * errors to exceptfds (only if app requested it) */
587 if( wsfds )
589 #define wsfds16 ((ws_fd_set16*)wsfds)
590 #define wsfds32 ((WS_fd_set*)wsfds)
591 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
593 for( i = 0, j = 0; i < count; i++ )
595 if( lfd[i] >= 0 )
597 int fd = lfd[i];
598 if( FD_ISSET(fd, fds) )
600 if ( exceptfds && sock_error_p(fd) )
602 FD_SET(fd, exceptfds);
603 num_err++;
605 else if( b32 )
606 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
607 else
608 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
610 close(fd);
611 lfd[i] = -1;
615 if( b32 ) wsfds32->fd_count = j;
616 else wsfds16->fd_count = j;
618 TRACE("\n");
619 #undef wsfds32
620 #undef wsfds16
622 return num_err;
625 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
627 if ( wsfds )
629 #define wsfds16 ((ws_fd_set16*)wsfds)
630 #define wsfds32 ((WS_fd_set*)wsfds)
631 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
633 for( i = 0; i < count; i++ )
634 if ( lfd[i] >= 0 )
635 close(lfd[i]);
637 TRACE("\n");
638 #undef wsfds32
639 #undef wsfds16
643 /* utility: given an fd, will block until one of the events occurs */
644 static inline int do_block( int fd, int events )
646 struct pollfd pfd;
648 pfd.fd = fd;
649 pfd.events = events;
650 poll(&pfd, 1, -1);
651 return pfd.revents;
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, POLLIN);
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, POLLIN | POLLOUT );
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");
1975 if (!lpbOutBuffer)
1977 close(fd);
1978 WSASetLastError(WSAEFAULT);
1979 return SOCKET_ERROR;
1981 if (!lpcbBytesReturned)
1983 close(fd);
1984 WSASetLastError(WSAEFAULT);
1985 return SOCKET_ERROR;
1988 apiReturn = GetAdaptersInfo(NULL, &size);
1989 if (apiReturn == ERROR_NO_DATA)
1991 numInt = 0;
1993 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
1995 PIP_ADAPTER_INFO table = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(),0,size);
1997 if (table)
1999 if (GetAdaptersInfo(table, &size) == NO_ERROR)
2001 PIP_ADAPTER_INFO ptr;
2003 if (size > cbOutBuffer)
2005 HeapFree(GetProcessHeap(),0,table);
2006 close(fd);
2007 WSASetLastError(WSAEFAULT);
2008 return (SOCKET_ERROR);
2010 for (ptr = table, numInt = 0; ptr;
2011 ptr = ptr->Next, intArray++, numInt++)
2013 unsigned int addr, mask, bcast;
2014 struct ifreq ifInfo;
2016 /* Socket Status Flags */
2017 strncpy(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
2018 ifInfo.ifr_name[IFNAMSIZ-1] = '\0';
2019 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
2021 ERR ("Error obtaining status flags for socket!\n");
2022 HeapFree(GetProcessHeap(),0,table);
2023 close(fd);
2024 WSASetLastError(WSAEINVAL);
2025 return (SOCKET_ERROR);
2027 else
2029 /* set flags; the values of IFF_* are not the same
2030 under Linux and Windows, therefore must generate
2031 new flags */
2032 intArray->iiFlags = 0;
2033 if (ifInfo.ifr_flags & IFF_BROADCAST)
2034 intArray->iiFlags |= WS_IFF_BROADCAST;
2035 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
2036 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
2037 if (ifInfo.ifr_flags & IFF_LOOPBACK)
2038 intArray->iiFlags |= WS_IFF_LOOPBACK;
2039 if (ifInfo.ifr_flags & IFF_UP)
2040 intArray->iiFlags |= WS_IFF_UP;
2043 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
2044 mask = inet_addr(ptr->IpAddressList.IpMask.String);
2045 bcast = addr | (addr & !mask);
2046 intArray->iiAddress.AddressIn.sin_family = AF_INET;
2047 intArray->iiAddress.AddressIn.sin_port = 0;
2048 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
2049 addr;
2050 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2051 intArray->iiNetmask.AddressIn.sin_port = 0;
2052 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
2053 mask;
2054 intArray->iiBroadcastAddress.AddressIn.sin_family =
2055 AF_INET;
2056 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
2057 intArray->iiBroadcastAddress.AddressIn.sin_addr.
2058 WS_s_addr = bcast;
2061 else
2063 ERR ("Unable to get interface table!\n");
2064 close(fd);
2065 HeapFree(GetProcessHeap(),0,table);
2066 WSASetLastError(WSAEINVAL);
2067 return (SOCKET_ERROR);
2069 HeapFree(GetProcessHeap(),0,table);
2071 else
2073 close(fd);
2074 WSASetLastError(WSAEINVAL);
2075 return (SOCKET_ERROR);
2078 else
2080 ERR ("Unable to get interface table!\n");
2081 close(fd);
2082 WSASetLastError(WSAEINVAL);
2083 return (SOCKET_ERROR);
2085 /* Calculate the size of the array being returned */
2086 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2087 break;
2090 default:
2092 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2093 close(fd);
2094 WSASetLastError(WSAEOPNOTSUPP);
2095 return (SOCKET_ERROR);
2099 /* Function executed with no errors */
2100 close(fd);
2101 return (0);
2103 else
2105 WSASetLastError(WSAENOTSOCK);
2106 return (SOCKET_ERROR);
2111 /***********************************************************************
2112 * ioctlsocket (WS2_32.10)
2114 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2116 int fd = _get_sock_fd(s);
2118 TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
2119 if (fd != -1)
2121 long newcmd = cmd;
2123 switch( cmd )
2125 case WS_FIONREAD:
2126 newcmd=FIONREAD;
2127 break;
2129 case WS_FIONBIO:
2130 newcmd=FIONBIO;
2131 if( _get_sock_mask(s) )
2133 /* AsyncSelect()'ed sockets are always nonblocking */
2134 if (*argp) {
2135 close(fd);
2136 return 0;
2138 SetLastError(WSAEINVAL);
2139 close(fd);
2140 return SOCKET_ERROR;
2142 close(fd);
2143 if (*argp)
2144 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2145 else
2146 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2147 return 0;
2149 case WS_SIOCATMARK:
2150 newcmd=SIOCATMARK;
2151 break;
2153 case WS__IOW('f',125,u_long):
2154 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2155 SetLastError(WSAEINVAL);
2156 return SOCKET_ERROR;
2158 case SIOCGIFBRDADDR:
2159 case SIOCGIFNETMASK:
2160 case SIOCGIFADDR:
2161 /* These don't need any special handling. They are used by
2162 WsControl, and are here to suppress an unecessary warning. */
2163 break;
2166 default:
2167 /* Netscape tries hard to use bogus ioctl 0x667e */
2168 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2170 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2172 close(fd);
2173 return 0;
2175 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2176 close(fd);
2178 return SOCKET_ERROR;
2181 /***********************************************************************
2182 * ioctlsocket (WINSOCK.12)
2184 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
2186 return (INT16)WS_ioctlsocket( s, cmd, argp );
2190 /***********************************************************************
2191 * listen (WS2_32.13)
2193 int WINAPI WS_listen(SOCKET s, int backlog)
2195 int fd = _get_sock_fd(s);
2197 TRACE("socket %04x, backlog %d\n", s, backlog);
2198 if (fd != -1)
2200 if (listen(fd, backlog) == 0)
2202 close(fd);
2203 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2204 FD_WINE_LISTENING,
2205 FD_CONNECT|FD_WINE_CONNECTED);
2206 return 0;
2208 SetLastError(wsaErrno());
2210 else SetLastError(WSAENOTSOCK);
2211 return SOCKET_ERROR;
2214 /***********************************************************************
2215 * listen (WINSOCK.13)
2217 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
2219 return (INT16)WS_listen( s, backlog );
2223 /***********************************************************************
2224 * recv (WS2_32.16)
2226 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2228 DWORD n, dwFlags = flags;
2229 WSABUF wsabuf;
2231 wsabuf.len = len;
2232 wsabuf.buf = buf;
2234 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2235 return SOCKET_ERROR;
2236 else
2237 return n;
2240 /***********************************************************************
2241 * recv (WINSOCK.16)
2243 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2245 return (INT16)WS_recv( s, buf, len, flags );
2249 /***********************************************************************
2250 * recvfrom (WS2_32.17)
2252 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2253 struct WS_sockaddr *from, int *fromlen)
2255 DWORD n, dwFlags = flags;
2256 WSABUF wsabuf;
2258 wsabuf.len = len;
2259 wsabuf.buf = buf;
2261 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2262 return SOCKET_ERROR;
2263 else
2264 return n;
2267 /***********************************************************************
2268 * recvfrom (WINSOCK.17)
2270 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2271 struct WS_sockaddr *from, INT16 *fromlen16)
2273 INT fromlen32;
2274 INT *p = &fromlen32;
2275 INT retVal;
2277 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
2278 retVal = WS_recvfrom( s, buf, len, flags, from, p );
2279 if( fromlen16 ) *fromlen16 = fromlen32;
2280 return (INT16)retVal;
2283 /***********************************************************************
2284 * __ws_select
2286 static int __ws_select(BOOL b32,
2287 void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
2288 const struct WS_timeval *ws_timeout)
2290 int highfd = 0;
2291 fd_set readfds, writefds, exceptfds;
2292 fd_set *p_read, *p_write, *p_except;
2293 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2294 struct timeval timeout, *timeoutaddr = NULL;
2296 TRACE("read %p, write %p, excp %p timeout %p\n",
2297 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2299 p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
2300 p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
2301 p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
2302 if (ws_timeout)
2304 timeoutaddr = &timeout;
2305 timeout.tv_sec=ws_timeout->tv_sec;
2306 timeout.tv_usec=ws_timeout->tv_usec;
2309 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2311 fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
2312 fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
2314 if (p_except && ws_exceptfds)
2316 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
2317 #define wsfds32 ((WS_fd_set*)ws_exceptfds)
2318 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
2320 for (i = j = 0; i < count; i++)
2322 int fd = exceptfd[i];
2323 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
2325 if( b32 )
2326 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
2327 else
2328 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
2330 if( fd >= 0 ) close(fd);
2331 exceptfd[i] = -1;
2333 if( b32 )
2334 wsfds32->fd_count = j;
2335 else
2336 wsfds16->fd_count = j;
2337 #undef wsfds32
2338 #undef wsfds16
2340 return highfd;
2342 fd_set_unimport(ws_readfds, readfd, b32);
2343 fd_set_unimport(ws_writefds, writefd, b32);
2344 fd_set_unimport(ws_exceptfds, exceptfd, b32);
2345 if( ws_readfds ) ((WS_fd_set*)ws_readfds)->fd_count = 0;
2346 if( ws_writefds ) ((WS_fd_set*)ws_writefds)->fd_count = 0;
2347 if( ws_exceptfds ) ((WS_fd_set*)ws_exceptfds)->fd_count = 0;
2349 if( highfd == 0 ) return 0;
2350 SetLastError(wsaErrno());
2351 return SOCKET_ERROR;
2354 /***********************************************************************
2355 * select (WINSOCK.18)
2357 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
2358 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
2359 struct WS_timeval* timeout)
2361 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2364 /***********************************************************************
2365 * select (WS2_32.18)
2367 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2368 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2369 const struct WS_timeval* timeout)
2371 /* struct timeval is the same for both 32- and 16-bit code */
2372 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2376 /***********************************************************************
2377 * send (WS2_32.19)
2379 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2381 DWORD n;
2382 WSABUF wsabuf;
2384 wsabuf.len = len;
2385 wsabuf.buf = (char*) buf;
2387 if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2388 return SOCKET_ERROR;
2389 else
2390 return n;
2393 /***********************************************************************
2394 * WSASend (WS2_32.72)
2396 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2397 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2398 LPWSAOVERLAPPED lpOverlapped,
2399 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2401 return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2402 NULL, 0, lpOverlapped, lpCompletionRoutine );
2405 /***********************************************************************
2406 * WSASendDisconnect (WS2_32.73)
2408 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2410 return WS_shutdown ( s, SD_SEND );
2414 /***********************************************************************
2415 * WSASendTo (WS2_32.74)
2417 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2418 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2419 const struct WS_sockaddr *to, int tolen,
2420 LPWSAOVERLAPPED lpOverlapped,
2421 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2423 int i, n, fd, err = WSAENOTSOCK, flags, ret;
2424 struct iovec* iovec;
2425 struct ws2_async *wsa;
2426 enum fd_type type;
2428 TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2429 s, lpBuffers, dwBufferCount, dwFlags,
2430 to, tolen, lpOverlapped, lpCompletionRoutine);
2432 fd = _get_sock_fd_type( s, GENERIC_WRITE, &type, &flags );
2433 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
2435 if ( fd == -1 )
2437 err = WSAGetLastError ();
2438 goto error;
2441 if ( !lpNumberOfBytesSent )
2443 err = WSAEFAULT;
2444 goto error;
2447 iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
2449 if ( !iovec )
2451 err = WSAEFAULT;
2452 goto err_close;
2455 for ( i = 0; i < dwBufferCount; i++ )
2457 iovec[i].iov_base = lpBuffers[i].buf;
2458 iovec[i].iov_len = lpBuffers[i].len;
2461 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2463 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
2464 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2465 lpOverlapped, lpCompletionRoutine );
2466 if ( !wsa )
2468 err = WSAEFAULT;
2469 goto err_free;
2472 if ( ( ret = register_new_async ( &wsa->async )) )
2474 err = NtStatusToWSAError ( ret );
2476 if ( !lpOverlapped )
2477 HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
2478 HeapFree ( GetProcessHeap(), 0, wsa );
2479 goto err_free;
2482 /* Try immediate completion */
2483 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
2485 if ( WSAGetOverlappedResult ( s, lpOverlapped,
2486 lpNumberOfBytesSent, FALSE, &dwFlags) )
2487 return 0;
2489 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
2490 goto error;
2493 WSASetLastError ( WSA_IO_PENDING );
2494 return SOCKET_ERROR;
2497 if (_is_blocking(s))
2499 /* FIXME: exceptfds? */
2500 do_block(fd, POLLOUT);
2503 n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2504 if ( n == -1 )
2506 err = wsaErrno();
2507 if ( err == WSAEWOULDBLOCK )
2508 _enable_event (SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2509 goto err_free;
2512 TRACE(" -> %i bytes\n", n);
2513 *lpNumberOfBytesSent = n;
2515 HeapFree ( GetProcessHeap(), 0, iovec );
2516 close ( fd );
2517 return 0;
2519 err_free:
2520 HeapFree ( GetProcessHeap(), 0, iovec );
2522 err_close:
2523 close ( fd );
2525 error:
2526 WARN (" -> ERROR %d\n", err);
2527 WSASetLastError (err);
2528 return SOCKET_ERROR;
2531 /***********************************************************************
2532 * send (WINSOCK.19)
2534 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2536 return WS_send( s, buf, len, flags );
2539 /***********************************************************************
2540 * sendto (WS2_32.20)
2542 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2543 const struct WS_sockaddr *to, int tolen)
2545 DWORD n;
2546 WSABUF wsabuf;
2548 wsabuf.len = len;
2549 wsabuf.buf = (char*) buf;
2551 if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2552 return SOCKET_ERROR;
2553 else
2554 return n;
2557 /***********************************************************************
2558 * sendto (WINSOCK.20)
2560 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2561 struct WS_sockaddr *to, INT16 tolen)
2563 return (INT16)WS_sendto( s, buf, len, flags, to, tolen );
2566 /***********************************************************************
2567 * setsockopt (WS2_32.21)
2569 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2570 const char *optval, int optlen)
2572 int fd;
2574 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
2575 (int) optname, (int) optval, optlen);
2576 /* SO_OPENTYPE does not require a valid socket handle. */
2577 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2579 if (optlen < sizeof(int) || !optval)
2581 SetLastError(WSAEFAULT);
2582 return SOCKET_ERROR;
2584 TlsSetValue( opentype_tls_index, (LPVOID)*(int *)optval );
2585 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2586 return 0;
2589 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2590 * socket. This will either not happen under windows or it is ignored in
2591 * windows (but it works in linux and therefor prevents the game to find
2592 * games outsite the current network) */
2593 if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE )
2595 FIXME("Does windows ignore SO_DONTROUTE?\n");
2596 return 0;
2600 fd = _get_sock_fd(s);
2601 if (fd != -1)
2603 struct linger linger;
2604 int woptval;
2605 struct timeval tval;
2607 /* Is a privileged and useless operation, so we don't. */
2608 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
2609 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2610 return 0;
2613 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2614 /* This is unique to WinSock and takes special conversion */
2615 linger.l_onoff = *((int*)optval) ? 0: 1;
2616 linger.l_linger = 0;
2617 optname=SO_LINGER;
2618 optval = (char*)&linger;
2619 optlen = sizeof(struct linger);
2620 level = SOL_SOCKET;
2621 }else{
2622 if (!convert_sockopt(&level, &optname)) {
2623 ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2624 SetLastError(WSAENOPROTOOPT);
2625 close(fd);
2626 return SOCKET_ERROR;
2628 if (optname == SO_LINGER && optval) {
2629 /* yes, uses unsigned short in both win16/win32 */
2630 linger.l_onoff = ((UINT16*)optval)[0];
2631 linger.l_linger = ((UINT16*)optval)[1];
2632 /* FIXME: what is documented behavior if SO_LINGER optval
2633 is null?? */
2634 optval = (char*)&linger;
2635 optlen = sizeof(struct linger);
2636 } else if (optval && optlen < sizeof(int)){
2637 woptval= *((INT16 *) optval);
2638 optval= (char*) &woptval;
2639 optlen=sizeof(int);
2641 #ifdef SO_RCVTIMEO
2642 if (level == SOL_SOCKET && optname == SO_RCVTIMEO) {
2643 if (optlen == sizeof(UINT32)) {
2644 /* WinSock passes miliseconds instead of struct timeval */
2645 tval.tv_usec = *(PUINT32)optval % 1000;
2646 tval.tv_sec = *(PUINT32)optval / 1000;
2647 /* min of 500 milisec */
2648 if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2649 optlen = sizeof(struct timeval);
2650 optval = (char*)&tval;
2651 } else if (optlen == sizeof(struct timeval)) {
2652 WARN("SO_RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2653 } else {
2654 WARN("SO_RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2655 close(fd);
2656 return 0;
2659 #endif
2660 #ifdef SO_SNDTIMEO
2661 if (level == SOL_SOCKET && optname == SO_SNDTIMEO) {
2662 if (optlen == sizeof(UINT32)) {
2663 /* WinSock passes miliseconds instead of struct timeval */
2664 tval.tv_usec = *(PUINT32)optval % 1000;
2665 tval.tv_sec = *(PUINT32)optval / 1000;
2666 /* min of 500 milisec */
2667 if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2668 optlen = sizeof(struct timeval);
2669 optval = (char*)&tval;
2670 } else if (optlen == sizeof(struct timeval)) {
2671 WARN("SO_SNDTIMEO for %d bytes: assuming unixism\n", optlen);
2672 } else {
2673 WARN("SO_SNDTIMEO for %d bytes is weird: ignored\n", optlen);
2674 close(fd);
2675 return 0;
2678 #endif
2680 if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2681 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2682 close( fd);
2683 return 0;
2686 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2688 close(fd);
2689 return 0;
2691 TRACE("Setting socket error, %d\n", wsaErrno());
2692 SetLastError(wsaErrno());
2693 close(fd);
2695 else SetLastError(WSAENOTSOCK);
2696 return SOCKET_ERROR;
2699 /***********************************************************************
2700 * setsockopt (WINSOCK.21)
2702 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2703 char *optval, INT16 optlen)
2705 if( !optval ) return SOCKET_ERROR;
2706 return (INT16)WS_setsockopt( s, (UINT16)level, optname, optval, optlen );
2710 /***********************************************************************
2711 * shutdown (WS2_32.22)
2713 int WINAPI WS_shutdown(SOCKET s, int how)
2715 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2716 enum fd_type type;
2717 unsigned int clear_flags = 0;
2719 fd = _get_sock_fd_type ( s, 0, &type, &flags );
2720 TRACE("socket %04x, how %i %d %d \n", s, how, type, flags );
2722 if (fd == -1)
2723 return SOCKET_ERROR;
2725 switch( how )
2727 case 0: /* drop receives */
2728 clear_flags |= FD_READ;
2729 break;
2730 case 1: /* drop sends */
2731 clear_flags |= FD_WRITE;
2732 break;
2733 case 2: /* drop all */
2734 clear_flags |= FD_READ|FD_WRITE;
2735 default:
2736 clear_flags |= FD_WINE_LISTENING;
2739 if ( flags & FD_FLAG_OVERLAPPED ) {
2741 switch ( how )
2743 case SD_RECEIVE:
2744 fd0 = fd;
2745 break;
2746 case SD_SEND:
2747 fd1 = fd;
2748 break;
2749 case SD_BOTH:
2750 default:
2751 fd0 = fd;
2752 fd1 = _get_sock_fd ( s );
2755 if ( fd0 != -1 )
2757 err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
2758 if ( err )
2760 close ( fd0 );
2761 goto error;
2764 if ( fd1 != -1 )
2766 err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
2767 if ( err )
2769 close ( fd1 );
2770 goto error;
2774 else /* non-overlapped mode */
2776 if ( shutdown( fd, how ) )
2778 err = wsaErrno ();
2779 close ( fd );
2780 goto error;
2782 close(fd);
2785 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2786 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2787 return 0;
2789 error:
2790 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2791 WSASetLastError ( err );
2792 return SOCKET_ERROR;
2795 /***********************************************************************
2796 * shutdown (WINSOCK.22)
2798 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2800 return (INT16)WS_shutdown( s, how );
2804 /***********************************************************************
2805 * socket (WS2_32.23)
2807 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2809 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2811 return WSASocketA ( af, type, protocol, NULL, 0,
2812 (TlsGetValue(opentype_tls_index) ? 0 : WSA_FLAG_OVERLAPPED) );
2815 /***********************************************************************
2816 * socket (WINSOCK.23)
2818 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2820 return (SOCKET16)WS_socket( af, type, protocol );
2824 /* ----------------------------------- DNS services
2826 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2827 * Also, we have to use wsock32 stubs to convert structures and
2828 * error codes from Unix to WSA, hence there is no direct mapping in
2829 * the relay32/wsock32.spec.
2833 /***********************************************************************
2834 * __ws_gethostbyaddr
2836 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2838 WIN_hostent *retval = NULL;
2840 struct hostent* host;
2841 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2842 char *extrabuf;
2843 int ebufsize=1024;
2844 struct hostent hostentry;
2845 int locerr=ENOBUFS;
2846 host = NULL;
2847 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2848 while(extrabuf) {
2849 int res = gethostbyaddr_r(addr, len, type,
2850 &hostentry, extrabuf, ebufsize, &host, &locerr);
2851 if( res != ERANGE) break;
2852 ebufsize *=2;
2853 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2855 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2856 #else
2857 EnterCriticalSection( &csWSgetXXXbyYYY );
2858 host = gethostbyaddr(addr, len, type);
2859 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2860 #endif
2861 if( host != NULL )
2863 if( WS_dup_he(host, dup_flag) )
2864 retval = he_buffer;
2865 else
2866 SetLastError(WSAENOBUFS);
2868 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2869 HeapFree(GetProcessHeap(),0,extrabuf);
2870 #else
2871 LeaveCriticalSection( &csWSgetXXXbyYYY );
2872 #endif
2873 return retval;
2876 /***********************************************************************
2877 * gethostbyaddr (WINSOCK.51)
2879 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2881 TRACE("ptr %p, len %d, type %d\n", addr, len, type);
2882 if (!__ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR )) return 0;
2883 return he_buffer_seg;
2886 /***********************************************************************
2887 * gethostbyaddr (WS2_32.51)
2889 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len,
2890 int type)
2892 TRACE("ptr %08x, len %d, type %d\n",
2893 (unsigned) addr, len, type);
2894 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2897 /***********************************************************************
2898 * __ws_gethostbyname
2900 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2902 WIN_hostent *retval = NULL;
2903 struct hostent* host;
2904 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2905 char *extrabuf;
2906 int ebufsize=1024;
2907 struct hostent hostentry;
2908 int locerr = ENOBUFS;
2909 #endif
2910 char buf[100];
2911 if( !name) {
2912 name = buf;
2913 if( gethostname( buf, 100) == -1) {
2914 SetLastError( WSAENOBUFS); /* appropriate ? */
2915 return retval;
2918 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2919 host = NULL;
2920 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2921 while(extrabuf) {
2922 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2923 if( res != ERANGE) break;
2924 ebufsize *=2;
2925 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2927 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2928 #else
2929 EnterCriticalSection( &csWSgetXXXbyYYY );
2930 host = gethostbyname(name);
2931 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2932 #endif
2933 if( host != NULL )
2935 if( WS_dup_he(host, dup_flag) )
2936 retval = he_buffer;
2937 else SetLastError(WSAENOBUFS);
2939 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2940 HeapFree(GetProcessHeap(),0,extrabuf);
2941 #else
2942 LeaveCriticalSection( &csWSgetXXXbyYYY );
2943 #endif
2944 return retval;
2947 /***********************************************************************
2948 * gethostbyname (WINSOCK.52)
2950 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2952 TRACE( "%s\n", debugstr_a(name) );
2953 if (!__ws_gethostbyname( name, WS_DUP_SEGPTR )) return 0;
2954 return he_buffer_seg;
2957 /***********************************************************************
2958 * gethostbyname (WS2_32.52)
2960 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2962 TRACE( "%s\n", debugstr_a(name) );
2963 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2967 /***********************************************************************
2968 * __ws_getprotobyname
2970 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2972 WIN_protoent* retval = NULL;
2973 #ifdef HAVE_GETPROTOBYNAME
2974 struct protoent* proto;
2975 EnterCriticalSection( &csWSgetXXXbyYYY );
2976 if( (proto = getprotobyname(name)) != NULL )
2978 if( WS_dup_pe(proto, dup_flag) )
2979 retval = pe_buffer;
2980 else SetLastError(WSAENOBUFS);
2982 else {
2983 MESSAGE("protocol %s not found; You might want to add "
2984 "this to /etc/protocols\n", debugstr_a(name) );
2985 SetLastError(WSANO_DATA);
2987 LeaveCriticalSection( &csWSgetXXXbyYYY );
2988 #endif
2989 return retval;
2992 /***********************************************************************
2993 * getprotobyname (WINSOCK.53)
2995 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2997 TRACE( "%s\n", debugstr_a(name) );
2998 if (!__ws_getprotobyname(name, WS_DUP_SEGPTR)) return 0;
2999 return pe_buffer_seg;
3002 /***********************************************************************
3003 * getprotobyname (WS2_32.53)
3005 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
3007 TRACE( "%s\n", debugstr_a(name) );
3008 return __ws_getprotobyname(name, WS_DUP_LINEAR);
3012 /***********************************************************************
3013 * __ws_getprotobynumber
3015 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
3017 WIN_protoent* retval = NULL;
3018 #ifdef HAVE_GETPROTOBYNUMBER
3019 struct protoent* proto;
3020 EnterCriticalSection( &csWSgetXXXbyYYY );
3021 if( (proto = getprotobynumber(number)) != NULL )
3023 if( WS_dup_pe(proto, dup_flag) )
3024 retval = pe_buffer;
3025 else SetLastError(WSAENOBUFS);
3027 else {
3028 MESSAGE("protocol number %d not found; You might want to add "
3029 "this to /etc/protocols\n", number );
3030 SetLastError(WSANO_DATA);
3032 LeaveCriticalSection( &csWSgetXXXbyYYY );
3033 #endif
3034 return retval;
3037 /***********************************************************************
3038 * getprotobynumber (WINSOCK.54)
3040 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
3042 TRACE("%i\n", number);
3043 if (!__ws_getprotobynumber(number, WS_DUP_SEGPTR)) return 0;
3044 return pe_buffer_seg;
3047 /***********************************************************************
3048 * getprotobynumber (WS2_32.54)
3050 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
3052 TRACE("%i\n", number);
3053 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
3057 /***********************************************************************
3058 * __ws_getservbyname
3060 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
3062 WIN_servent* retval = NULL;
3063 struct servent* serv;
3064 int i = wsi_strtolo( name, proto );
3066 if( i ) {
3067 EnterCriticalSection( &csWSgetXXXbyYYY );
3068 serv = getservbyname(local_buffer,
3069 proto && *proto ? (local_buffer + i) : NULL);
3070 if( serv != NULL )
3072 if( WS_dup_se(serv, dup_flag) )
3073 retval = se_buffer;
3074 else SetLastError(WSAENOBUFS);
3076 else {
3077 MESSAGE("service %s protocol %s not found; You might want to add "
3078 "this to /etc/services\n", debugstr_a(local_buffer),
3079 proto ? debugstr_a(local_buffer+i):"*");
3080 SetLastError(WSANO_DATA);
3082 LeaveCriticalSection( &csWSgetXXXbyYYY );
3084 else SetLastError(WSAENOBUFS);
3085 return retval;
3088 /***********************************************************************
3089 * getservbyname (WINSOCK.55)
3091 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
3093 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3094 if (!__ws_getservbyname(name, proto, WS_DUP_SEGPTR)) return 0;
3095 return se_buffer_seg;
3098 /***********************************************************************
3099 * getservbyname (WS2_32.55)
3101 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
3103 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3104 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
3108 /***********************************************************************
3109 * __ws_getservbyport
3111 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
3113 WIN_servent* retval = NULL;
3114 #ifdef HAVE_GETSERVBYPORT
3115 struct servent* serv;
3116 if (!proto || wsi_strtolo( proto, NULL )) {
3117 EnterCriticalSection( &csWSgetXXXbyYYY );
3118 if( (serv = getservbyport(port, proto && *proto ? local_buffer :
3119 NULL)) != NULL ) {
3120 if( WS_dup_se(serv, dup_flag) )
3121 retval = se_buffer;
3122 else SetLastError(WSAENOBUFS);
3124 else {
3125 MESSAGE("service on port %lu protocol %s not found; You might want to add "
3126 "this to /etc/services\n", (unsigned long)ntohl(port),
3127 proto ? debugstr_a(local_buffer) : "*");
3128 SetLastError(WSANO_DATA);
3130 LeaveCriticalSection( &csWSgetXXXbyYYY );
3132 else SetLastError(WSAENOBUFS);
3133 #endif
3134 return retval;
3137 /***********************************************************************
3138 * getservbyport (WINSOCK.56)
3140 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
3142 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3143 if (!__ws_getservbyport(port, proto, WS_DUP_SEGPTR)) return 0;
3144 return se_buffer_seg;
3147 /***********************************************************************
3148 * getservbyport (WS2_32.56)
3150 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
3152 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3153 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
3157 /***********************************************************************
3158 * gethostname (WS2_32.57)
3160 int WINAPI WS_gethostname(char *name, int namelen)
3162 TRACE("name %p, len %d\n", name, namelen);
3164 if (gethostname(name, namelen) == 0)
3166 TRACE("<- '%s'\n", name);
3167 return 0;
3169 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
3170 TRACE("<- ERROR !\n");
3171 return SOCKET_ERROR;
3174 /***********************************************************************
3175 * gethostname (WINSOCK.57)
3177 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
3179 return (INT16)WS_gethostname(name, namelen);
3183 /* ------------------------------------- Windows sockets extensions -- *
3185 * ------------------------------------------------------------------- */
3187 /***********************************************************************
3188 * WSAEnumNetworkEvents (WS2_32.36)
3190 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
3192 int ret;
3194 TRACE("%08x, hEvent %p, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
3196 SERVER_START_REQ( get_socket_event )
3198 req->handle = SOCKET2HANDLE(s);
3199 req->service = TRUE;
3200 req->c_event = hEvent;
3201 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
3202 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
3204 SERVER_END_REQ;
3205 if (!ret) return 0;
3206 SetLastError(WSAEINVAL);
3207 return SOCKET_ERROR;
3210 /***********************************************************************
3211 * WSAEventSelect (WS2_32.39)
3213 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
3215 int ret;
3217 TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
3219 SERVER_START_REQ( set_socket_event )
3221 req->handle = SOCKET2HANDLE(s);
3222 req->mask = lEvent;
3223 req->event = hEvent;
3224 req->window = 0;
3225 req->msg = 0;
3226 ret = wine_server_call( req );
3228 SERVER_END_REQ;
3229 if (!ret) return 0;
3230 SetLastError(WSAEINVAL);
3231 return SOCKET_ERROR;
3234 /**********************************************************************
3235 * WSAGetOverlappedResult (WS2_32.40)
3237 BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
3238 LPDWORD lpcbTransfer, BOOL fWait,
3239 LPDWORD lpdwFlags )
3241 DWORD r;
3243 TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
3244 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
3246 if ( !(lpOverlapped && lpOverlapped->hEvent) )
3248 ERR ( "Invalid pointer\n" );
3249 WSASetLastError (WSA_INVALID_PARAMETER);
3250 return FALSE;
3253 if ( fWait )
3255 while ( WaitForSingleObjectEx (lpOverlapped->hEvent, INFINITE, TRUE) == STATUS_USER_APC );
3257 else if ( lpOverlapped->Internal == STATUS_PENDING )
3259 /* Wait in order to give APCs a chance to run. */
3260 /* This is cheating, so we must set the event again in case of success -
3261 it may be a non-manual reset event. */
3262 while ( (r = WaitForSingleObjectEx (lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
3263 if ( r == WAIT_OBJECT_0 )
3264 NtSetEvent ( lpOverlapped->hEvent, NULL );
3267 if ( lpcbTransfer )
3268 *lpcbTransfer = lpOverlapped->InternalHigh;
3270 if ( lpdwFlags )
3271 *lpdwFlags = lpOverlapped->Offset;
3273 switch ( lpOverlapped->Internal )
3275 case STATUS_SUCCESS:
3276 return TRUE;
3277 case STATUS_PENDING:
3278 WSASetLastError ( WSA_IO_INCOMPLETE );
3279 if (fWait) ERR ("PENDING status after waiting!\n");
3280 return FALSE;
3281 default:
3282 WSASetLastError ( NtStatusToWSAError ( lpOverlapped->Internal ));
3283 return FALSE;
3288 /***********************************************************************
3289 * WSAAsyncSelect (WS2_32.101)
3291 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
3293 int ret;
3295 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3297 SERVER_START_REQ( set_socket_event )
3299 req->handle = SOCKET2HANDLE(s);
3300 req->mask = lEvent;
3301 req->event = 0;
3302 req->window = hWnd;
3303 req->msg = uMsg;
3304 ret = wine_server_call( req );
3306 SERVER_END_REQ;
3307 if (!ret) return 0;
3308 SetLastError(WSAEINVAL);
3309 return SOCKET_ERROR;
3312 /***********************************************************************
3313 * WSAAsyncSelect (WINSOCK.101)
3315 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
3317 return (INT16)WSAAsyncSelect( s, HWND_32(hWnd), wMsg, lEvent );
3320 /***********************************************************************
3321 * WSARecvEx (WINSOCK.1107)
3323 * See description for WSARecvEx()
3325 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags)
3327 FIXME("(WSARecvEx16) partial packet return value not set \n");
3329 return WINSOCK_recv16(s, buf, len, *flags);
3333 /***********************************************************************
3334 * WSACreateEvent (WS2_32.31)
3337 WSAEVENT WINAPI WSACreateEvent(void)
3339 /* Create a manual-reset event, with initial state: unsignealed */
3340 TRACE("\n");
3342 return CreateEventA(NULL, TRUE, FALSE, NULL);
3345 /***********************************************************************
3346 * WSACloseEvent (WS2_32.29)
3349 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3351 TRACE ("event=%p\n", event);
3353 return CloseHandle(event);
3356 /***********************************************************************
3357 * WSASocketA (WS2_32.78)
3360 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3361 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3362 GROUP g, DWORD dwFlags)
3364 SOCKET ret;
3367 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
3368 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3371 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3372 af, type, protocol, lpProtocolInfo, g, dwFlags );
3374 /* hack for WSADuplicateSocket */
3375 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3376 ret = lpProtocolInfo->dwCatalogEntryId;
3377 TRACE("\tgot duplicate %04x\n", ret);
3378 return ret;
3381 /* check the socket family */
3382 switch(af)
3384 #ifdef HAVE_IPX
3385 case WS_AF_IPX: af = AF_IPX;
3386 #endif
3387 case AF_INET:
3388 case AF_UNSPEC:
3389 break;
3390 default:
3391 SetLastError(WSAEAFNOSUPPORT);
3392 return INVALID_SOCKET;
3395 /* check the socket type */
3396 switch(type)
3398 case WS_SOCK_STREAM:
3399 type=SOCK_STREAM;
3400 break;
3401 case WS_SOCK_DGRAM:
3402 type=SOCK_DGRAM;
3403 break;
3404 case WS_SOCK_RAW:
3405 type=SOCK_RAW;
3406 break;
3407 default:
3408 SetLastError(WSAESOCKTNOSUPPORT);
3409 return INVALID_SOCKET;
3412 /* check the protocol type */
3413 if ( protocol < 0 ) /* don't support negative values */
3415 SetLastError(WSAEPROTONOSUPPORT);
3416 return INVALID_SOCKET;
3419 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3420 switch(protocol)
3422 case IPPROTO_TCP:
3423 if (type == SOCK_STREAM) { af = AF_INET; break; }
3424 case IPPROTO_UDP:
3425 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3426 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3429 SERVER_START_REQ( create_socket )
3431 req->family = af;
3432 req->type = type;
3433 req->protocol = protocol;
3434 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3435 req->flags = dwFlags;
3436 req->inherit = TRUE;
3437 set_error( wine_server_call( req ) );
3438 ret = HANDLE2SOCKET( reply->handle );
3440 SERVER_END_REQ;
3441 if (ret)
3443 TRACE("\tcreated %04x\n", ret );
3444 return ret;
3447 if (GetLastError() == WSAEACCES) /* raw socket denied */
3449 if (type == SOCK_RAW)
3450 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3451 else
3452 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3453 SetLastError(WSAESOCKTNOSUPPORT);
3456 WARN("\t\tfailed!\n");
3457 return INVALID_SOCKET;
3461 /***********************************************************************
3462 * __WSAFDIsSet (WINSOCK.151)
3464 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
3466 int i = set->fd_count;
3468 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3470 while (i--)
3471 if (set->fd_array[i] == s) return 1;
3472 return 0;
3475 /***********************************************************************
3476 * __WSAFDIsSet (WS2_32.151)
3478 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3480 int i = set->fd_count;
3482 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3484 while (i--)
3485 if (set->fd_array[i] == s) return 1;
3486 return 0;
3489 /***********************************************************************
3490 * WSAIsBlocking (WINSOCK.114)
3491 * WSAIsBlocking (WS2_32.114)
3493 BOOL WINAPI WSAIsBlocking(void)
3495 /* By default WinSock should set all its sockets to non-blocking mode
3496 * and poll in PeekMessage loop when processing "blocking" ones. This
3497 * function is supposed to tell if the program is in this loop. Our
3498 * blocking calls are truly blocking so we always return FALSE.
3500 * Note: It is allowed to call this function without prior WSAStartup().
3503 TRACE("\n");
3504 return FALSE;
3507 /***********************************************************************
3508 * WSACancelBlockingCall (WINSOCK.113)
3509 * WSACancelBlockingCall (WS2_32.113)
3511 INT WINAPI WSACancelBlockingCall(void)
3513 TRACE("\n");
3514 return 0;
3517 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
3519 FIXME("How was this called?\n");
3520 return x();
3524 /***********************************************************************
3525 * WSASetBlockingHook (WINSOCK.109)
3527 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
3529 FARPROC16 prev = (FARPROC16)blocking_hook;
3530 blocking_hook = (FARPROC)lpBlockFunc;
3531 TRACE("hook %p\n", lpBlockFunc);
3532 return prev;
3536 /***********************************************************************
3537 * WSASetBlockingHook (WS2_32.109)
3539 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3541 FARPROC prev = blocking_hook;
3542 blocking_hook = lpBlockFunc;
3543 TRACE("hook %p\n", lpBlockFunc);
3544 return prev;
3548 /***********************************************************************
3549 * WSAUnhookBlockingHook (WINSOCK.110)
3551 INT16 WINAPI WSAUnhookBlockingHook16(void)
3553 blocking_hook = WSA_DefaultBlockingHook;
3554 return 0;
3558 /***********************************************************************
3559 * WSAUnhookBlockingHook (WS2_32.110)
3561 INT WINAPI WSAUnhookBlockingHook(void)
3563 blocking_hook = WSA_DefaultBlockingHook;
3564 return 0;
3568 /* ----------------------------------- end of API stuff */
3570 /* ----------------------------------- helper functions -
3572 * TODO: Merge WS_dup_..() stuff into one function that
3573 * would operate with a generic structure containing internal
3574 * pointers (via a template of some kind).
3577 static int list_size(char** l, int item_size)
3579 int i,j = 0;
3580 if(l)
3581 { for(i=0;l[i];i++)
3582 j += (item_size) ? item_size : strlen(l[i]) + 1;
3583 j += (i + 1) * sizeof(char*); }
3584 return j;
3587 static int list_dup(char** l_src, char* ref, char* base, int item_size)
3589 /* base is either either equal to ref or 0 or SEGPTR */
3591 char* p = ref;
3592 char** l_to = (char**)ref;
3593 int i,j,k;
3595 for(j=0;l_src[j];j++) ;
3596 p += (j + 1) * sizeof(char*);
3597 for(i=0;i<j;i++)
3598 { l_to[i] = base + (p - ref);
3599 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3600 memcpy(p, l_src[i], k); p += k; }
3601 l_to[i] = NULL;
3602 return (p - ref);
3605 /* ----- hostent */
3607 static int hostent_size(struct hostent* p_he)
3609 int size = 0;
3610 if( p_he )
3611 { size = sizeof(struct hostent);
3612 size += strlen(p_he->h_name) + 1;
3613 size += list_size(p_he->h_aliases, 0);
3614 size += list_size(p_he->h_addr_list, p_he->h_length ); }
3615 return size;
3618 /* duplicate hostent entry
3619 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3620 * Dito for protoent and servent.
3622 static int WS_dup_he(struct hostent* p_he, int flag)
3624 /* Convert hostent structure into ws_hostent so that the data fits
3625 * into local_buffer. Internal pointers can be linear, SEGPTR, or
3626 * relative to local_buffer depending on "flag" value. Returns size
3627 * of the data copied.
3630 int size = hostent_size(p_he);
3631 if( size )
3633 char *p_name,*p_aliases,*p_addr,*p_base,*p;
3634 char *p_to;
3635 struct ws_hostent16 *p_to16;
3636 struct WS_hostent *p_to32;
3638 check_buffer_he(size);
3639 p_to = he_buffer;
3640 p_to16 = he_buffer;
3641 p_to32 = he_buffer;
3643 p = p_to;
3644 p_base = (flag & WS_DUP_SEGPTR) ? (char*)he_buffer_seg : he_buffer;
3645 p += (flag & WS_DUP_SEGPTR) ?
3646 sizeof(struct ws_hostent16) : sizeof(struct WS_hostent);
3647 p_name = p;
3648 strcpy(p, p_he->h_name); p += strlen(p) + 1;
3649 p_aliases = p;
3650 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3651 p_addr = p;
3652 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
3654 if (flag & WS_DUP_SEGPTR) /* Win16 */
3656 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
3657 p_to16->h_length = (INT16)p_he->h_length;
3658 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3659 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3660 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3661 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3663 else /* Win32 */
3665 p_to32->h_addrtype = p_he->h_addrtype;
3666 p_to32->h_length = p_he->h_length;
3667 p_to32->h_name = (p_base + (p_name - p_to));
3668 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3669 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3670 size += (sizeof(struct WS_hostent) - sizeof(struct hostent));
3673 return size;
3676 /* ----- protoent */
3678 static int protoent_size(struct protoent* p_pe)
3680 int size = 0;
3681 if( p_pe )
3682 { size = sizeof(struct protoent);
3683 size += strlen(p_pe->p_name) + 1;
3684 size += list_size(p_pe->p_aliases, 0); }
3685 return size;
3688 static int WS_dup_pe(struct protoent* p_pe, int flag)
3690 int size = protoent_size(p_pe);
3691 if( size )
3693 char *p_to;
3694 struct ws_protoent16 *p_to16;
3695 struct WS_protoent *p_to32;
3696 char *p_name,*p_aliases,*p_base,*p;
3698 check_buffer_pe(size);
3699 p_to = pe_buffer;
3700 p_to16 = pe_buffer;
3701 p_to32 = pe_buffer;
3702 p = p_to;
3703 p_base = (flag & WS_DUP_SEGPTR) ? (char*)pe_buffer_seg : pe_buffer;
3704 p += (flag & WS_DUP_SEGPTR) ?
3705 sizeof(struct ws_protoent16) : sizeof(struct WS_protoent);
3706 p_name = p;
3707 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3708 p_aliases = p;
3709 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3711 if (flag & WS_DUP_SEGPTR) /* Win16 */
3713 p_to16->p_proto = (INT16)p_pe->p_proto;
3714 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3715 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3716 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3718 else /* Win32 */
3720 p_to32->p_proto = p_pe->p_proto;
3721 p_to32->p_name = (p_base) + (p_name - p_to);
3722 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3723 size += (sizeof(struct WS_protoent) - sizeof(struct protoent));
3726 return size;
3729 /* ----- servent */
3731 static int servent_size(struct servent* p_se)
3733 int size = 0;
3734 if( p_se )
3735 { size += sizeof(struct servent);
3736 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3737 size += list_size(p_se->s_aliases, 0); }
3738 return size;
3741 static int WS_dup_se(struct servent* p_se, int flag)
3743 int size = servent_size(p_se);
3744 if( size )
3746 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3747 char *p_to;
3748 struct ws_servent16 *p_to16;
3749 struct WS_servent *p_to32;
3751 check_buffer_se(size);
3752 p_to = se_buffer;
3753 p_to16 = se_buffer;
3754 p_to32 = se_buffer;
3755 p = p_to;
3756 p_base = (flag & WS_DUP_SEGPTR) ? (char*)se_buffer_seg : se_buffer;
3757 p += (flag & WS_DUP_SEGPTR) ?
3758 sizeof(struct ws_servent16) : sizeof(struct WS_servent);
3759 p_name = p;
3760 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3761 p_proto = p;
3762 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3763 p_aliases = p;
3764 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3766 if (flag & WS_DUP_SEGPTR) /* Win16 */
3768 p_to16->s_port = (INT16)p_se->s_port;
3769 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3770 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3771 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3772 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3774 else /* Win32 */
3776 p_to32->s_port = p_se->s_port;
3777 p_to32->s_name = (p_base + (p_name - p_to));
3778 p_to32->s_proto = (p_base + (p_proto - p_to));
3779 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3780 size += (sizeof(struct WS_servent) - sizeof(struct servent));
3783 return size;
3786 /* ----------------------------------- error handling */
3788 UINT16 wsaErrno(void)
3790 int loc_errno = errno;
3791 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3793 switch(loc_errno)
3795 case EINTR: return WSAEINTR;
3796 case EBADF: return WSAEBADF;
3797 case EPERM:
3798 case EACCES: return WSAEACCES;
3799 case EFAULT: return WSAEFAULT;
3800 case EINVAL: return WSAEINVAL;
3801 case EMFILE: return WSAEMFILE;
3802 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3803 case EINPROGRESS: return WSAEINPROGRESS;
3804 case EALREADY: return WSAEALREADY;
3805 case ENOTSOCK: return WSAENOTSOCK;
3806 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3807 case EMSGSIZE: return WSAEMSGSIZE;
3808 case EPROTOTYPE: return WSAEPROTOTYPE;
3809 case ENOPROTOOPT: return WSAENOPROTOOPT;
3810 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3811 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3812 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3813 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3814 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3815 case EADDRINUSE: return WSAEADDRINUSE;
3816 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3817 case ENETDOWN: return WSAENETDOWN;
3818 case ENETUNREACH: return WSAENETUNREACH;
3819 case ENETRESET: return WSAENETRESET;
3820 case ECONNABORTED: return WSAECONNABORTED;
3821 case EPIPE:
3822 case ECONNRESET: return WSAECONNRESET;
3823 case ENOBUFS: return WSAENOBUFS;
3824 case EISCONN: return WSAEISCONN;
3825 case ENOTCONN: return WSAENOTCONN;
3826 case ESHUTDOWN: return WSAESHUTDOWN;
3827 case ETOOMANYREFS: return WSAETOOMANYREFS;
3828 case ETIMEDOUT: return WSAETIMEDOUT;
3829 case ECONNREFUSED: return WSAECONNREFUSED;
3830 case ELOOP: return WSAELOOP;
3831 case ENAMETOOLONG: return WSAENAMETOOLONG;
3832 case EHOSTDOWN: return WSAEHOSTDOWN;
3833 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3834 case ENOTEMPTY: return WSAENOTEMPTY;
3835 #ifdef EPROCLIM
3836 case EPROCLIM: return WSAEPROCLIM;
3837 #endif
3838 #ifdef EUSERS
3839 case EUSERS: return WSAEUSERS;
3840 #endif
3841 #ifdef EDQUOT
3842 case EDQUOT: return WSAEDQUOT;
3843 #endif
3844 #ifdef ESTALE
3845 case ESTALE: return WSAESTALE;
3846 #endif
3847 #ifdef EREMOTE
3848 case EREMOTE: return WSAEREMOTE;
3849 #endif
3851 /* just in case we ever get here and there are no problems */
3852 case 0: return 0;
3853 default:
3854 WARN("Unknown errno %d!\n", loc_errno);
3855 return WSAEOPNOTSUPP;
3859 UINT16 wsaHerrno(int loc_errno)
3862 WARN("h_errno %d.\n", loc_errno);
3864 switch(loc_errno)
3866 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3867 case TRY_AGAIN: return WSATRY_AGAIN;
3868 case NO_RECOVERY: return WSANO_RECOVERY;
3869 case NO_DATA: return WSANO_DATA;
3870 case ENOBUFS: return WSAENOBUFS;
3872 case 0: return 0;
3873 default:
3874 WARN("Unknown h_errno %d!\n", loc_errno);
3875 return WSAEOPNOTSUPP;
3880 /***********************************************************************
3881 * WSARecv (WS2_32.67)
3883 int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3884 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3885 LPWSAOVERLAPPED lpOverlapped,
3886 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3888 return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3889 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3892 /***********************************************************************
3893 * WSARecvFrom (WS2_32.69)
3895 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3896 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3897 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3898 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3901 int i, n, fd, err = WSAENOTSOCK, flags, ret;
3902 struct iovec* iovec;
3903 struct ws2_async *wsa;
3904 enum fd_type type;
3906 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3907 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3908 (lpFromlen ? *lpFromlen : -1L),
3909 lpOverlapped, lpCompletionRoutine);
3911 fd = _get_sock_fd_type( s, GENERIC_READ, &type, &flags );
3912 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
3914 if (fd == -1)
3916 err = WSAGetLastError ();
3917 goto error;
3920 iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3921 if ( !iovec )
3923 err = WSAEFAULT;
3924 goto err_close;
3927 for (i = 0; i < dwBufferCount; i++)
3929 iovec[i].iov_base = lpBuffers[i].buf;
3930 iovec[i].iov_len = lpBuffers[i].len;
3933 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3935 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
3936 lpFlags, lpFrom, lpFromlen,
3937 lpOverlapped, lpCompletionRoutine );
3939 if ( !wsa )
3941 err = WSAEFAULT;
3942 goto err_free;
3945 if ( ( ret = register_new_async ( &wsa->async )) )
3947 err = NtStatusToWSAError ( ret );
3949 if ( !lpOverlapped )
3950 HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
3951 HeapFree ( GetProcessHeap(), 0, wsa );
3952 goto err_free;
3955 /* Try immediate completion */
3956 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
3958 if ( WSAGetOverlappedResult ( s, lpOverlapped,
3959 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3960 return 0;
3962 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
3963 goto error;
3966 WSASetLastError ( WSA_IO_PENDING );
3967 return SOCKET_ERROR;
3970 if ( _is_blocking(s) )
3972 /* block here */
3973 /* FIXME: OOB and exceptfds? */
3974 do_block(fd, POLLIN);
3977 n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3978 if ( n == -1 )
3980 err = wsaErrno();
3981 goto err_free;
3984 TRACE(" -> %i bytes\n", n);
3985 *lpNumberOfBytesRecvd = n;
3987 HeapFree (GetProcessHeap(), 0, iovec);
3988 close(fd);
3989 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3991 return 0;
3993 err_free:
3994 HeapFree (GetProcessHeap(), 0, iovec);
3996 err_close:
3997 close (fd);
3999 error:
4000 WARN(" -> ERROR %d\n", err);
4001 WSASetLastError ( err );
4002 return SOCKET_ERROR;
4005 /***********************************************************************
4006 * WSCInstallProvider (WS2_32.88)
4008 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
4009 LPCWSTR lpszProviderDllPath,
4010 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
4011 DWORD dwNumberOfEntries,
4012 LPINT lpErrno )
4014 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
4015 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
4016 dwNumberOfEntries, lpErrno);
4017 *lpErrno = 0;
4018 return 0;
4022 /***********************************************************************
4023 * WSCDeinstallProvider (WS2_32.83)
4025 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
4027 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
4028 *lpErrno = 0;
4029 return 0;
4033 /***********************************************************************
4034 * WSAAccept (WS2_32.26)
4036 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
4037 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
4040 int ret = 0, size = 0;
4041 WSABUF CallerId, CallerData, CalleeId, CalleeData;
4042 /* QOS SQOS, GQOS; */
4043 GROUP g;
4044 SOCKET cs;
4045 SOCKADDR src_addr, dst_addr;
4047 TRACE("Socket %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
4048 s, addr, addrlen, lpfnCondition, dwCallbackData);
4051 size = sizeof(src_addr);
4052 cs = WS_accept(s, &src_addr, &size);
4054 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
4056 CallerId.buf = (char *)&src_addr;
4057 CallerId.len = sizeof(src_addr);
4059 CallerData.buf = NULL;
4060 CallerData.len = (ULONG)NULL;
4062 WS_getsockname(cs, &dst_addr, &size);
4064 CalleeId.buf = (char *)&dst_addr;
4065 CalleeId.len = sizeof(dst_addr);
4068 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
4069 &CalleeId, &CalleeData, &g, dwCallbackData);
4071 switch (ret)
4073 case CF_ACCEPT:
4074 if (addr && addrlen)
4075 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
4076 return cs;
4077 case CF_DEFER:
4078 SERVER_START_REQ ( set_socket_deferred )
4080 req->handle = SOCKET2HANDLE (s);
4081 req->deferred = SOCKET2HANDLE (cs);
4082 if ( !wine_server_call_err ( req ) )
4084 SetLastError ( WSATRY_AGAIN );
4085 WS_closesocket ( cs );
4088 SERVER_END_REQ;
4089 return SOCKET_ERROR;
4090 case CF_REJECT:
4091 WS_closesocket(cs);
4092 SetLastError(WSAECONNREFUSED);
4093 return SOCKET_ERROR;
4094 default:
4095 FIXME("Unknown return type from Condition function\n");
4096 SetLastError(WSAENOTSOCK);
4097 return SOCKET_ERROR;
4101 /***********************************************************************
4102 * WSAEnumProtocolsA (WS2_32.37)
4104 int WINAPI WSAEnumProtocolsA(LPINT lpiProtocols, LPWSAPROTOCOL_INFOA lpProtocolBuffer, LPDWORD lpdwBufferLength)
4106 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4107 return 0;
4110 /***********************************************************************
4111 * WSAEnumProtocolsW (WS2_32.38)
4113 int WINAPI WSAEnumProtocolsW(LPINT lpiProtocols, LPWSAPROTOCOL_INFOW lpProtocolBuffer, LPDWORD lpdwBufferLength)
4115 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4116 return 0;
4119 /***********************************************************************
4120 * WSADuplicateSocketA (WS2_32.32)
4122 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
4124 HANDLE hProcess;
4126 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
4127 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
4128 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
4129 /* I don't know what the real Windoze does next, this is a hack */
4130 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
4131 * the target use the global duplicate, or we could copy a reference to us to the structure
4132 * and let the target duplicate it from us, but let's do it as simple as possible */
4133 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
4134 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
4135 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
4136 0, FALSE, DUPLICATE_SAME_ACCESS);
4137 CloseHandle(hProcess);
4138 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
4139 return 0;
4142 /***********************************************************************
4143 * WSAInstallServiceClassA (WS2_32.48)
4145 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
4147 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
4148 WSASetLastError(WSAEACCES);
4149 return SOCKET_ERROR;
4152 /***********************************************************************
4153 * WSAInstallServiceClassW (WS2_32.49)
4155 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
4157 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
4158 WSASetLastError(WSAEACCES);
4159 return SOCKET_ERROR;
4162 /***********************************************************************
4163 * WSARemoveServiceClass (WS2_32.70)
4165 int WINAPI WSARemoveServiceClass(LPGUID info)
4167 FIXME("Request to remove service %p\n",info);
4168 WSASetLastError(WSATYPE_NOT_FOUND);
4169 return SOCKET_ERROR;