Store the thread entry point in the startup info passed to the new
[wine/gsoc_dplay.git] / dlls / winsock / socket.c
blobd3dce4640b84282d50b81b244528bd80d9b63644
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 #ifdef IP_HDRINCL
287 MAP_OPTION( IP_HDRINCL ),
288 #endif
289 MAP_OPTION( IP_TOS ),
290 MAP_OPTION( IP_TTL ),
291 { 0, 0 }
294 static DWORD opentype_tls_index = -1; /* TLS index for SO_OPENTYPE flag */
296 inline static DWORD NtStatusToWSAError ( const DWORD status )
298 /* We only need to cover the status codes set by server async request handling */
299 DWORD wserr;
300 switch ( status )
302 case STATUS_SUCCESS: wserr = 0; break;
303 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
304 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
305 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
306 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
307 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
308 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
309 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
310 default:
311 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
312 /* It is not a NT status code but a winsock error */
313 wserr = status;
314 else
316 wserr = RtlNtStatusToDosError( status );
317 FIXME ( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
320 return wserr;
323 /* set last error code from NT status without mapping WSA errors */
324 inline static unsigned int set_error( unsigned int err )
326 if (err)
328 err = NtStatusToWSAError ( err );
329 SetLastError( err );
331 return err;
334 static char* check_buffer(int size);
336 inline static int _get_sock_fd(SOCKET s)
338 int fd;
340 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), GENERIC_READ, &fd, NULL, NULL ) ))
341 return -1;
342 return fd;
345 inline static int _get_sock_fd_type( SOCKET s, DWORD access, enum fd_type *type, int *flags )
347 int fd;
348 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, type, flags ) )) return -1;
349 if ( ( (access & GENERIC_READ) && (*flags & FD_FLAG_RECV_SHUTDOWN ) ) ||
350 ( (access & GENERIC_WRITE) && (*flags & FD_FLAG_SEND_SHUTDOWN ) ) )
352 close (fd);
353 WSASetLastError ( WSAESHUTDOWN );
354 return -1;
356 return fd;
359 static void _enable_event( HANDLE s, unsigned int event,
360 unsigned int sstate, unsigned int cstate )
362 SERVER_START_REQ( enable_socket_event )
364 req->handle = s;
365 req->mask = event;
366 req->sstate = sstate;
367 req->cstate = cstate;
368 wine_server_call( req );
370 SERVER_END_REQ;
373 static int _is_blocking(SOCKET s)
375 int ret;
376 SERVER_START_REQ( get_socket_event )
378 req->handle = SOCKET2HANDLE(s);
379 req->service = FALSE;
380 req->c_event = 0;
381 wine_server_call( req );
382 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
384 SERVER_END_REQ;
385 return ret;
388 static unsigned int _get_sock_mask(SOCKET s)
390 unsigned int ret;
391 SERVER_START_REQ( get_socket_event )
393 req->handle = SOCKET2HANDLE(s);
394 req->service = FALSE;
395 req->c_event = 0;
396 wine_server_call( req );
397 ret = reply->mask;
399 SERVER_END_REQ;
400 return ret;
403 static void _sync_sock_state(SOCKET s)
405 /* do a dummy wineserver request in order to let
406 the wineserver run through its select loop once */
407 (void)_is_blocking(s);
410 static int _get_sock_error(SOCKET s, unsigned int bit)
412 int events[FD_MAX_EVENTS];
414 SERVER_START_REQ( get_socket_event )
416 req->handle = SOCKET2HANDLE(s);
417 req->service = FALSE;
418 req->c_event = 0;
419 wine_server_set_reply( req, events, sizeof(events) );
420 wine_server_call( req );
422 SERVER_END_REQ;
423 return events[bit];
426 static void WINSOCK_DeleteIData(void)
428 /* delete scratch buffers */
430 UnMapLS( he_buffer_seg );
431 UnMapLS( se_buffer_seg );
432 UnMapLS( pe_buffer_seg );
433 UnMapLS( dbuffer_seg );
434 if (he_buffer) HeapFree( GetProcessHeap(), 0, he_buffer );
435 if (se_buffer) HeapFree( GetProcessHeap(), 0, se_buffer );
436 if (pe_buffer) HeapFree( GetProcessHeap(), 0, pe_buffer );
437 if (local_buffer) HeapFree( GetProcessHeap(), 0, local_buffer );
438 he_buffer = NULL;
439 se_buffer = NULL;
440 pe_buffer = NULL;
441 local_buffer = NULL;
442 he_buffer_seg = 0;
443 se_buffer_seg = 0;
444 pe_buffer_seg = 0;
445 dbuffer_seg = 0;
446 num_startup = 0;
449 /***********************************************************************
450 * DllMain (WS2_32.init)
452 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
454 TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
455 switch (fdwReason) {
456 case DLL_PROCESS_ATTACH:
457 DisableThreadLibraryCalls(hInstDLL);
458 opentype_tls_index = TlsAlloc();
459 break;
460 case DLL_PROCESS_DETACH:
461 TlsFree( opentype_tls_index );
462 WINSOCK_DeleteIData();
463 break;
465 return TRUE;
468 /***********************************************************************
469 * convert_sockopt()
471 * Converts socket flags from Windows format.
472 * Return 1 if converted, 0 if not (error).
474 static int convert_sockopt(INT *level, INT *optname)
476 int i;
477 switch (*level)
479 case WS_SOL_SOCKET:
480 *level = SOL_SOCKET;
481 for(i=0; ws_sock_map[i][0]; i++)
483 if( ws_sock_map[i][0] == *optname )
485 *optname = ws_sock_map[i][1];
486 return 1;
489 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
490 break;
491 case WS_IPPROTO_TCP:
492 *level = IPPROTO_TCP;
493 for(i=0; ws_tcp_map[i][0]; i++)
495 if ( ws_tcp_map[i][0] == *optname )
497 *optname = ws_tcp_map[i][1];
498 return 1;
501 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
502 break;
503 case WS_IPPROTO_IP:
504 *level = IPPROTO_IP;
505 for(i=0; ws_ip_map[i][0]; i++)
507 if (ws_ip_map[i][0] == *optname )
509 *optname = ws_ip_map[i][1];
510 return 1;
513 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
514 break;
515 default: FIXME("Unimplemented or unknown socket level\n");
517 return 0;
520 /* ----------------------------------- Per-thread info (or per-process?) */
522 static int wsi_strtolo(const char* name, const char* opt)
524 /* Stuff a lowercase copy of the string into the local buffer */
526 int i = strlen(name) + 2;
527 char* p = check_buffer(i + ((opt)?strlen(opt):0));
529 if( p )
531 do *p++ = tolower(*name); while(*name++);
532 i = (p - local_buffer);
533 if( opt ) do *p++ = tolower(*opt); while(*opt++);
534 return i;
536 return 0;
539 static fd_set* fd_set_import( fd_set* fds, void* wsfds, int* highfd, int lfd[], BOOL b32 )
541 /* translate Winsock fd set into local fd set */
543 if( wsfds )
545 #define wsfds16 ((ws_fd_set16*)wsfds)
546 #define wsfds32 ((WS_fd_set*)wsfds)
547 int i, count;
549 FD_ZERO(fds);
550 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
552 for( i = 0; i < count; i++ )
554 int s = (b32) ? wsfds32->fd_array[i]
555 : wsfds16->fd_array[i];
556 int fd = _get_sock_fd(s);
557 if (fd != -1)
559 lfd[ i ] = fd;
560 if( fd > *highfd ) *highfd = fd;
561 FD_SET(fd, fds);
563 else lfd[ i ] = -1;
565 #undef wsfds32
566 #undef wsfds16
567 return fds;
569 return NULL;
572 inline static int sock_error_p(int s)
574 unsigned int optval, optlen;
576 optlen = sizeof(optval);
577 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
578 if (optval) WARN("\t[%i] error: %d\n", s, optval);
579 return optval != 0;
582 static int fd_set_export( fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
584 int num_err = 0;
586 /* translate local fd set into Winsock fd set, adding
587 * errors to exceptfds (only if app requested it) */
589 if( wsfds )
591 #define wsfds16 ((ws_fd_set16*)wsfds)
592 #define wsfds32 ((WS_fd_set*)wsfds)
593 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
595 for( i = 0, j = 0; i < count; i++ )
597 if( lfd[i] >= 0 )
599 int fd = lfd[i];
600 if( FD_ISSET(fd, fds) )
602 if ( exceptfds && sock_error_p(fd) )
604 FD_SET(fd, exceptfds);
605 num_err++;
607 else if( b32 )
608 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
609 else
610 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
612 close(fd);
613 lfd[i] = -1;
617 if( b32 ) wsfds32->fd_count = j;
618 else wsfds16->fd_count = j;
620 TRACE("\n");
621 #undef wsfds32
622 #undef wsfds16
624 return num_err;
627 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
629 if ( wsfds )
631 #define wsfds16 ((ws_fd_set16*)wsfds)
632 #define wsfds32 ((WS_fd_set*)wsfds)
633 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
635 for( i = 0; i < count; i++ )
636 if ( lfd[i] >= 0 )
637 close(lfd[i]);
639 TRACE("\n");
640 #undef wsfds32
641 #undef wsfds16
645 /* utility: given an fd, will block until one of the events occurs */
646 static inline int do_block( int fd, int events )
648 struct pollfd pfd;
650 pfd.fd = fd;
651 pfd.events = events;
652 poll(&pfd, 1, -1);
653 return pfd.revents;
656 void* __ws_memalloc( int size )
658 return WS_ALLOC(size);
661 void __ws_memfree(void* ptr)
663 WS_FREE(ptr);
667 /* ----------------------------------- API -----
669 * Init / cleanup / error checking.
672 /***********************************************************************
673 * WSAStartup (WINSOCK.115)
675 * Create socket control struct, attach it to the global list and
676 * update a pointer in the task struct.
678 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA16 lpWSAData)
680 static const WSADATA16 data =
682 0x0101, 0x0101,
683 "WINE Sockets 1.1",
684 #ifdef linux
685 "Linux/i386",
686 #elif defined(__NetBSD__)
687 "NetBSD/i386",
688 #elif defined(sunos)
689 "SunOS",
690 #elif defined(__FreeBSD__)
691 "FreeBSD",
692 #elif defined(__OpenBSD__)
693 "OpenBSD/i386",
694 #else
695 "Unknown",
696 #endif
697 WS_MAX_SOCKETS_PER_PROCESS,
698 WS_MAX_UDP_DATAGRAM,
702 TRACE("verReq=%x\n", wVersionRequested);
704 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
705 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
707 if (!lpWSAData) return WSAEINVAL;
709 /* initialize socket heap */
711 if( !_WSHeap )
713 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
714 if( !_WSHeap )
716 ERR("Fatal: failed to create WinSock heap\n");
717 return 0;
720 if( _WSHeap == 0 ) return WSASYSNOTREADY;
722 num_startup++;
724 /* return winsock information */
726 memcpy(lpWSAData, &data, sizeof(data));
728 TRACE("succeeded\n");
729 return 0;
732 /***********************************************************************
733 * WSAStartup (WS2_32.115)
735 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
737 TRACE("verReq=%x\n", wVersionRequested);
739 if (LOBYTE(wVersionRequested) < 1)
740 return WSAVERNOTSUPPORTED;
742 if (!lpWSAData) return WSAEINVAL;
744 /* initialize socket heap */
746 if( !_WSHeap )
748 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
749 if( !_WSHeap )
751 ERR("Fatal: failed to create WinSock heap\n");
752 return 0;
755 if( _WSHeap == 0 ) return WSASYSNOTREADY;
757 num_startup++;
759 /* that's the whole of the negotiation for now */
760 lpWSAData->wVersion = wVersionRequested;
761 /* return winsock information */
762 lpWSAData->wHighVersion = 0x0202;
763 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
764 strcpy(lpWSAData->szSystemStatus, "Running" );
765 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
766 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
767 /* don't do anything with lpWSAData->lpVendorInfo */
768 /* (some apps don't allocate the space for this field) */
770 TRACE("succeeded\n");
771 return 0;
775 /***********************************************************************
776 * WSACleanup (WINSOCK.116)
777 * WSACleanup (WS2_32.116)
779 INT WINAPI WSACleanup(void)
781 if (num_startup)
783 if (--num_startup > 0) return 0;
784 WINSOCK_DeleteIData();
785 return 0;
787 SetLastError(WSANOTINITIALISED);
788 return SOCKET_ERROR;
792 /***********************************************************************
793 * WSAGetLastError (WINSOCK.111)
794 * WSAGetLastError (WS2_32.111)
796 INT WINAPI WSAGetLastError(void)
798 return GetLastError();
801 /***********************************************************************
802 * WSASetLastError (WS2_32.112)
804 void WINAPI WSASetLastError(INT iError) {
805 SetLastError(iError);
808 /***********************************************************************
809 * WSASetLastError (WINSOCK.112)
811 void WINAPI WSASetLastError16(INT16 iError)
813 WSASetLastError(iError);
816 static char* check_buffer(int size)
818 static int local_buflen;
820 if (local_buffer)
822 if (local_buflen >= size ) return local_buffer;
823 HeapFree( GetProcessHeap(), 0, local_buffer );
825 local_buffer = HeapAlloc( GetProcessHeap(), 0, (local_buflen = size) );
826 return local_buffer;
829 static struct ws_hostent* check_buffer_he(int size)
831 static int he_len;
832 if (he_buffer)
834 if (he_len >= size ) return he_buffer;
835 UnMapLS( he_buffer_seg );
836 HeapFree( GetProcessHeap(), 0, he_buffer );
838 he_buffer = HeapAlloc( GetProcessHeap(), 0, (he_len = size) );
839 he_buffer_seg = MapLS( he_buffer );
840 return he_buffer;
843 static void* check_buffer_se(int size)
845 static int se_len;
846 if (se_buffer)
848 if (se_len >= size ) return se_buffer;
849 UnMapLS( se_buffer_seg );
850 HeapFree( GetProcessHeap(), 0, se_buffer );
852 se_buffer = HeapAlloc( GetProcessHeap(), 0, (se_len = size) );
853 se_buffer_seg = MapLS( se_buffer );
854 return se_buffer;
857 static struct ws_protoent* check_buffer_pe(int size)
859 static int pe_len;
860 if (pe_buffer)
862 if (pe_len >= size ) return pe_buffer;
863 UnMapLS( pe_buffer_seg );
864 HeapFree( GetProcessHeap(), 0, pe_buffer );
866 pe_buffer = HeapAlloc( GetProcessHeap(), 0, (pe_len = size) );
867 pe_buffer_seg = MapLS( he_buffer );
868 return pe_buffer;
871 /* ----------------------------------- i/o APIs */
873 #ifdef HAVE_IPX
874 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
875 #else
876 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
877 #endif
880 /**********************************************************************/
882 /* Returns the converted address if successful, NULL if it was too small to
883 * start with. Note that the returned pointer may be the original pointer
884 * if no conversion is necessary.
886 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
888 switch (wsaddr->sa_family)
890 #ifdef HAVE_IPX
891 case WS_AF_IPX:
893 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
894 struct sockaddr_ipx* uipx;
896 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
897 return NULL;
899 *uaddrlen=sizeof(struct sockaddr_ipx);
900 uipx=malloc(*uaddrlen);
901 uipx->sipx_family=AF_IPX;
902 uipx->sipx_port=wsipx->sa_socket;
903 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
904 * in one go
906 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
907 #ifdef IPX_FRAME_NONE
908 uipx->sipx_type=IPX_FRAME_NONE;
909 #endif
910 memset(&uipx->sipx_zero,0,sizeof(uipx->sipx_zero));
911 return (const struct sockaddr*)uipx;
913 #endif
915 default:
916 if (wsaddrlen<sizeof(struct WS_sockaddr))
917 return NULL;
919 /* No conversion needed, just return the original address */
920 *uaddrlen=wsaddrlen;
921 return (const struct sockaddr*)wsaddr;
923 return NULL;
926 /* Allocates a Unix sockaddr structure to receive the data */
927 inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
929 if (wsaddr==NULL)
931 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
933 /* This is not strictly the right thing to do. Hope it works however */
934 *uaddrlen=0;
936 return NULL;
939 if (*wsaddrlen==0)
940 *uaddrlen=0;
941 else
942 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
944 return malloc(*uaddrlen);
947 /* Returns 0 if successful, -1 if the buffer is too small */
948 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
950 int res;
952 switch(uaddr->sa_family)
954 #ifdef HAVE_IPX
955 case AF_IPX:
957 struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
958 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
960 res=-1;
961 switch (*wsaddrlen) /* how much can we copy? */
963 default:
964 res=0; /* enough */
965 *wsaddrlen=uaddrlen;
966 wsipx->sa_socket=uipx->sipx_port;
967 /* fall through */
968 case 13:
969 case 12:
970 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
971 /* fall through */
972 case 11:
973 case 10:
974 case 9:
975 case 8:
976 case 7:
977 case 6:
978 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
979 /* fall through */
980 case 5:
981 case 4:
982 case 3:
983 case 2:
984 wsipx->sa_family=WS_AF_IPX;
985 /* fall through */
986 case 1:
987 case 0:
988 /* way too small */
989 break;
992 break;
993 #endif
995 default:
996 /* No conversion needed */
997 memcpy(wsaddr,uaddr,*wsaddrlen);
998 if (*wsaddrlen<uaddrlen) {
999 res=-1;
1000 } else {
1001 *wsaddrlen=uaddrlen;
1002 res=0;
1005 return res;
1008 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
1009 * ws_sockaddr_alloc
1011 inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
1013 if (uaddr!=NULL && uaddr!=(const struct sockaddr*)wsaddr)
1014 free((void*)uaddr);
1017 /**************************************************************************
1018 * Functions for handling overlapped I/O
1019 **************************************************************************/
1021 static DWORD ws2_async_get_count (const struct async_private *ovp)
1023 return ovp->iosb->Information;
1026 static void ws2_async_cleanup ( struct async_private *ap )
1028 struct ws2_async *as = (struct ws2_async*) ap;
1030 TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->async.iosb );
1031 if ( !as->user_overlapped )
1033 #if 0
1034 /* FIXME: I don't think this is really used */
1035 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
1036 WSACloseEvent ( as->overlapped->hEvent );
1037 #endif
1038 HeapFree ( GetProcessHeap(), 0, as->async.iosb );
1041 if ( as->iovec )
1042 HeapFree ( GetProcessHeap(), 0, as->iovec );
1044 HeapFree ( GetProcessHeap(), 0, as );
1047 static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
1049 ws2_async* as = (ws2_async*) data;
1051 TRACE ("data: %p\n", as);
1053 as->completion_func ( NtStatusToWSAError (as->async.iosb->u.Status),
1054 as->async.iosb->Information,
1055 as->user_overlapped,
1056 as->flags );
1057 ws2_async_cleanup ( &as->async );
1060 /***********************************************************************
1061 * WS2_make_async (INTERNAL)
1064 static void WS2_async_recv (async_private *as);
1065 static void WS2_async_send (async_private *as);
1067 inline static struct ws2_async*
1068 WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferCount,
1069 LPDWORD lpFlags, struct WS_sockaddr *addr,
1070 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
1071 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1073 struct ws2_async *wsa = HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async ) );
1075 TRACE ( "wsa %p\n", wsa );
1077 if (!wsa)
1078 return NULL;
1080 wsa->async.ops = ( lpCompletionRoutine ? &ws2_async_ops : &ws2_nocomp_async_ops );
1081 wsa->async.handle = (HANDLE) s;
1082 wsa->async.fd = fd;
1083 wsa->async.type = type;
1084 switch (type)
1086 case ASYNC_TYPE_READ:
1087 wsa->flags = *lpFlags;
1088 wsa->async.func = WS2_async_recv;
1089 wsa->addrlen.ptr = addrlen;
1090 break;
1091 case ASYNC_TYPE_WRITE:
1092 wsa->flags = 0;
1093 wsa->async.func = WS2_async_send;
1094 wsa->addrlen.val = *addrlen;
1095 break;
1096 default:
1097 ERR ("Invalid async type: %d\n", type);
1099 wsa->user_overlapped = lpOverlapped;
1100 wsa->completion_func = lpCompletionRoutine;
1101 wsa->iovec = iovec;
1102 wsa->n_iovecs = dwBufferCount;
1103 wsa->addr = addr;
1105 if ( lpOverlapped )
1107 wsa->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
1108 wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
1110 else
1112 wsa->async.iosb = HeapAlloc ( GetProcessHeap(), 0,
1113 sizeof (IO_STATUS_BLOCK) );
1114 if ( !wsa->async.iosb )
1115 goto error;
1116 wsa->async.event = INVALID_HANDLE_VALUE;
1119 wsa->async.iosb->Information = 0;
1120 TRACE ( "wsa %p, ops %p, h %p, ev %p, fd %d, func %p, iosb %p, uov %p, cfunc %p\n",
1121 wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
1122 wsa->async.iosb, wsa->user_overlapped, wsa->completion_func );
1124 return wsa;
1126 error:
1127 TRACE ("Error\n");
1128 HeapFree ( GetProcessHeap(), 0, wsa );
1129 return NULL;
1132 /***********************************************************************
1133 * WS2_recv (INTERNAL)
1135 * Work horse for both synchronous and asynchronous recv() operations.
1137 static int WS2_recv ( int fd, struct iovec* iov, int count,
1138 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1139 LPDWORD lpFlags )
1141 struct msghdr hdr;
1142 int n;
1143 TRACE ( "fd %d, iovec %p, count %d addr %p, len %p, flags %lx\n",
1144 fd, iov, count, lpFrom, lpFromlen, *lpFlags);
1146 hdr.msg_name = NULL;
1148 if ( lpFrom )
1150 #if DEBUG_SOCKADDR
1151 dump_sockaddr (lpFrom);
1152 #endif
1154 hdr.msg_namelen = *lpFromlen;
1155 hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
1156 if ( !hdr.msg_name )
1158 WSASetLastError ( WSAEFAULT );
1159 n = -1;
1160 goto out;
1163 else
1164 hdr.msg_namelen = 0;
1166 hdr.msg_iov = iov;
1167 hdr.msg_iovlen = count;
1168 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1169 hdr.msg_accrights = NULL;
1170 hdr.msg_accrightslen = 0;
1171 #else
1172 hdr.msg_control = NULL;
1173 hdr.msg_controllen = 0;
1174 hdr.msg_flags = 0;
1175 #endif
1177 if ( (n = recvmsg (fd, &hdr, *lpFlags)) == -1 )
1179 TRACE ( "recvmsg error %d\n", errno);
1180 goto out;
1183 if ( lpFrom &&
1184 ws_sockaddr_u2ws ( hdr.msg_name, hdr.msg_namelen,
1185 lpFrom, lpFromlen ) != 0 )
1187 /* The from buffer was too small, but we read the data
1188 * anyway. Is that really bad?
1190 WSASetLastError ( WSAEFAULT );
1191 WARN ( "Address buffer too small\n" );
1194 out:
1196 ws_sockaddr_free ( hdr.msg_name, lpFrom );
1197 TRACE ("-> %d\n", n);
1198 return n;
1201 /***********************************************************************
1202 * WS2_async_recv (INTERNAL)
1204 * Handler for overlapped recv() operations.
1206 static void WS2_async_recv ( async_private *as )
1208 ws2_async* wsa = (ws2_async*) as;
1209 int result, err;
1211 TRACE ( "async %p\n", wsa );
1213 if ( wsa->async.iosb->u.Status != STATUS_PENDING )
1215 TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
1216 return;
1219 result = WS2_recv ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1220 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1222 if (result >= 0)
1224 wsa->async.iosb->u.Status = STATUS_SUCCESS;
1225 wsa->async.iosb->Information = result;
1226 TRACE ( "received %d bytes\n", result );
1227 _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
1228 return;
1231 err = wsaErrno ();
1232 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1234 wsa->async.iosb->u.Status = STATUS_PENDING;
1235 _enable_event ( wsa->async.handle, FD_READ, 0, 0 );
1236 TRACE ( "still pending\n" );
1238 else
1240 wsa->async.iosb->u.Status = err;
1241 TRACE ( "Error: %x\n", err );
1245 /***********************************************************************
1246 * WS2_send (INTERNAL)
1248 * Work horse for both synchronous and asynchronous send() operations.
1250 static int WS2_send ( int fd, struct iovec* iov, int count,
1251 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1253 struct msghdr hdr;
1254 int n = -1;
1255 TRACE ( "fd %d, iovec %p, count %d addr %p, len %d, flags %lx\n",
1256 fd, iov, count, to, tolen, dwFlags);
1258 hdr.msg_name = NULL;
1260 if ( to )
1262 #if DEBUG_SOCKADDR
1263 dump_sockaddr (to);
1264 #endif
1265 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
1266 if ( !hdr.msg_name )
1268 WSASetLastError ( WSAEFAULT );
1269 goto out;
1272 else
1273 hdr.msg_namelen = 0;
1275 hdr.msg_iov = iov;
1276 hdr.msg_iovlen = count;
1277 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1278 hdr.msg_accrights = NULL;
1279 hdr.msg_accrightslen = 0;
1280 #else
1281 hdr.msg_control = NULL;
1282 hdr.msg_controllen = 0;
1283 hdr.msg_flags = 0;
1284 #endif
1286 n = sendmsg (fd, &hdr, dwFlags);
1288 out:
1289 ws_sockaddr_free ( hdr.msg_name, to );
1290 return n;
1293 /***********************************************************************
1294 * WS2_async_send (INTERNAL)
1296 * Handler for overlapped send() operations.
1298 static void WS2_async_send ( async_private *as )
1300 ws2_async* wsa = (ws2_async*) as;
1301 int result, err;
1303 TRACE ( "async %p\n", wsa );
1305 if ( wsa->async.iosb->u.Status != STATUS_PENDING )
1307 TRACE ( "status: %ld\n", wsa->async.iosb->u.Status );
1308 return;
1311 result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1312 wsa->addr, wsa->addrlen.val, wsa->flags );
1314 if (result >= 0)
1316 wsa->async.iosb->u.Status = STATUS_SUCCESS;
1317 wsa->async.iosb->Information = result;
1318 TRACE ( "sent %d bytes\n", result );
1319 _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
1320 return;
1323 err = wsaErrno ();
1324 if ( err == WSAEINTR )
1326 wsa->async.iosb->u.Status = STATUS_PENDING;
1327 _enable_event ( wsa->async.handle, FD_WRITE, 0, 0 );
1328 TRACE ( "still pending\n" );
1330 else
1332 /* We set the status to a winsock error code and check for that
1333 later in NtStatusToWSAError () */
1334 wsa->async.iosb->u.Status = err;
1335 TRACE ( "Error: %x\n", err );
1339 /***********************************************************************
1340 * WS2_async_shutdown (INTERNAL)
1342 * Handler for shutdown() operations on overlapped sockets.
1344 static void WS2_async_shutdown ( async_private *as )
1346 ws2_async* wsa = (ws2_async*) as;
1347 int err = 1;
1349 TRACE ( "async %p %d\n", wsa, wsa->async.type );
1350 switch ( wsa->async.type )
1352 case ASYNC_TYPE_READ:
1353 err = shutdown ( wsa->async.fd, 0 );
1354 break;
1355 case ASYNC_TYPE_WRITE:
1356 err = shutdown ( wsa->async.fd, 1 );
1357 break;
1358 default:
1359 ERR ("invalid type: %d\n", wsa->async.type );
1362 if ( err )
1363 wsa->async.iosb->u.Status = wsaErrno ();
1364 else
1365 wsa->async.iosb->u.Status = STATUS_SUCCESS;
1368 /***********************************************************************
1369 * WS2_register_async_shutdown (INTERNAL)
1371 * Helper function for WS_shutdown() on overlapped sockets.
1373 static int WS2_register_async_shutdown ( SOCKET s, int fd, int type )
1375 struct ws2_async *wsa;
1376 int ret, err = WSAEFAULT;
1377 DWORD dwflags = 0;
1378 int len = 0;
1379 LPWSAOVERLAPPED ovl = HeapAlloc (GetProcessHeap(), 0, sizeof ( WSAOVERLAPPED ));
1381 TRACE ("s %d fd %d type %d\n", s, fd, type);
1382 if (!ovl)
1383 goto out;
1385 ovl->hEvent = WSACreateEvent ();
1386 if ( ovl->hEvent == WSA_INVALID_EVENT )
1387 goto out_free;
1389 wsa = WS2_make_async ( s, fd, type, NULL, 0,
1390 &dwflags, NULL, &len, ovl, NULL );
1391 if ( !wsa )
1392 goto out_close;
1394 /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
1395 wsa->user_overlapped = NULL;
1396 wsa->async.func = WS2_async_shutdown;
1397 if ( (ret = register_new_async ( &wsa->async )) )
1399 err = NtStatusToWSAError ( ret );
1400 goto out;
1402 /* Try immediate completion */
1403 while ( WaitForSingleObjectEx ( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1404 return 0;
1406 out_close:
1407 WSACloseEvent ( ovl->hEvent );
1408 out_free:
1409 HeapFree ( GetProcessHeap(), 0, ovl );
1410 out:
1411 return err;
1414 /***********************************************************************
1415 * accept (WS2_32.1)
1417 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1418 int *addrlen32)
1420 int fd = _get_sock_fd(s);
1422 TRACE("socket %04x\n", (UINT16)s );
1423 if (fd != -1)
1425 SOCKET as;
1426 if (_is_blocking(s))
1428 /* block here */
1429 do_block(fd, POLLIN);
1430 _sync_sock_state(s); /* let wineserver notice connection */
1431 /* retrieve any error codes from it */
1432 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1433 /* FIXME: care about the error? */
1435 close(fd);
1436 SERVER_START_REQ( accept_socket )
1438 req->lhandle = SOCKET2HANDLE(s);
1439 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1440 req->inherit = TRUE;
1441 set_error( wine_server_call( req ) );
1442 as = HANDLE2SOCKET( reply->handle );
1444 SERVER_END_REQ;
1445 if (as)
1447 if (addr)
1448 WS_getpeername(as, addr, addrlen32);
1449 return as;
1452 else
1454 SetLastError(WSAENOTSOCK);
1456 return INVALID_SOCKET;
1459 /***********************************************************************
1460 * accept (WINSOCK.1)
1462 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct WS_sockaddr* addr,
1463 INT16* addrlen16 )
1465 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
1466 SOCKET retSocket = WS_accept( s, addr, &addrlen32 );
1467 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
1468 return (SOCKET16)retSocket;
1471 /***********************************************************************
1472 * bind (WS2_32.2)
1474 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1476 int fd = _get_sock_fd(s);
1477 int res;
1479 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
1480 #if DEBUG_SOCKADDR
1481 dump_sockaddr(name);
1482 #endif
1484 res=SOCKET_ERROR;
1485 if (fd != -1)
1487 if (!name || !SUPPORTED_PF(name->sa_family))
1489 SetLastError(WSAEAFNOSUPPORT);
1491 else
1493 const struct sockaddr* uaddr;
1494 int uaddrlen;
1496 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1497 if (uaddr == NULL)
1499 SetLastError(WSAEFAULT);
1501 else
1503 int on = 1;
1504 /* The game GrandPrixLegends binds more than one time, but does
1505 * not do a SO_REUSEADDR - Stevens says this is ok */
1506 TRACE( "Setting WS_SO_REUSEADDR on socket before we bind it\n");
1507 WS_setsockopt( s, WS_SOL_SOCKET, WS_SO_REUSEADDR, (char*)&on, sizeof(on) );
1509 if (bind(fd, uaddr, uaddrlen) < 0)
1511 int loc_errno = errno;
1512 WARN("\tfailure - errno = %i\n", errno);
1513 errno = loc_errno;
1514 switch (errno)
1516 case EBADF:
1517 SetLastError(WSAENOTSOCK);
1518 break;
1519 case EADDRNOTAVAIL:
1520 SetLastError(WSAEINVAL);
1521 break;
1522 default:
1523 SetLastError(wsaErrno());
1524 break;
1527 else
1529 res=0; /* success */
1531 ws_sockaddr_free(uaddr,name);
1534 close(fd);
1536 else
1538 SetLastError(WSAENOTSOCK);
1540 return res;
1543 /***********************************************************************
1544 * bind (WINSOCK.2)
1546 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1548 return (INT16)WS_bind( s, name, namelen );
1551 /***********************************************************************
1552 * closesocket (WS2_32.3)
1554 int WINAPI WS_closesocket(SOCKET s)
1556 TRACE("socket %08x\n", s);
1557 if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1558 return SOCKET_ERROR;
1561 /***********************************************************************
1562 * closesocket (WINSOCK.3)
1564 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
1566 return (INT16)WS_closesocket(s);
1569 /***********************************************************************
1570 * connect (WS2_32.4)
1572 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1574 int fd = _get_sock_fd(s);
1576 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
1577 #if DEBUG_SOCKADDR
1578 dump_sockaddr(name);
1579 #endif
1581 if (fd != -1)
1583 const struct sockaddr* uaddr;
1584 int uaddrlen;
1586 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1587 if (uaddr == NULL)
1589 SetLastError(WSAEFAULT);
1591 else
1593 int rc;
1595 rc=connect(fd, uaddr, uaddrlen);
1596 ws_sockaddr_free(uaddr,name);
1597 if (rc == 0)
1598 goto connect_success;
1601 if (errno == EINPROGRESS)
1603 /* tell wineserver that a connection is in progress */
1604 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1605 FD_CONNECT|FD_READ|FD_WRITE,
1606 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1607 if (_is_blocking(s))
1609 int result;
1610 /* block here */
1611 do_block(fd, POLLIN | POLLOUT );
1612 _sync_sock_state(s); /* let wineserver notice connection */
1613 /* retrieve any error codes from it */
1614 result = _get_sock_error(s, FD_CONNECT_BIT);
1615 if (result)
1616 SetLastError(result);
1617 else
1619 goto connect_success;
1622 else
1624 SetLastError(WSAEWOULDBLOCK);
1627 else
1629 SetLastError(wsaErrno());
1631 close(fd);
1633 else
1635 SetLastError(WSAENOTSOCK);
1637 return SOCKET_ERROR;
1639 connect_success:
1640 close(fd);
1641 _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1642 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1643 FD_CONNECT|FD_WINE_LISTENING);
1644 return 0;
1647 /***********************************************************************
1648 * connect (WINSOCK.4)
1650 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1652 return (INT16)WS_connect( s, name, namelen );
1655 /***********************************************************************
1656 * WSAConnect (WS2_32.30)
1658 int WINAPI WSAConnect ( SOCKET s, const struct WS_sockaddr* name, int namelen,
1659 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1660 LPQOS lpSQOS, LPQOS lpGQOS )
1662 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1663 FIXME ("unsupported parameters!\n");
1664 return WS_connect ( s, name, namelen );
1668 /***********************************************************************
1669 * getpeername (WS2_32.5)
1671 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1673 int fd;
1674 int res;
1676 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1678 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1679 if( (name == NULL) || (namelen == NULL) )
1681 SetLastError( WSAEFAULT );
1682 return SOCKET_ERROR;
1685 fd = _get_sock_fd(s);
1686 res = SOCKET_ERROR;
1688 if (fd != -1)
1690 struct sockaddr* uaddr;
1691 int uaddrlen;
1693 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1694 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1696 SetLastError(wsaErrno());
1698 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1700 /* The buffer was too small */
1701 SetLastError(WSAEFAULT);
1703 else
1705 res=0;
1707 ws_sockaddr_free(uaddr,name);
1708 close(fd);
1710 else
1712 SetLastError(WSAENOTSOCK);
1714 return res;
1717 /***********************************************************************
1718 * getpeername (WINSOCK.5)
1720 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct WS_sockaddr *name,
1721 INT16 *namelen16)
1723 INT namelen32 = *namelen16;
1724 INT retVal = WS_getpeername( s, name, &namelen32 );
1726 #if DEBUG_SOCKADDR
1727 dump_sockaddr(name);
1728 #endif
1730 *namelen16 = namelen32;
1731 return (INT16)retVal;
1734 /***********************************************************************
1735 * getsockname (WS2_32.6)
1737 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1739 int fd;
1740 int res;
1742 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1744 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1745 if( (name == NULL) || (namelen == NULL) )
1747 SetLastError( WSAEFAULT );
1748 return SOCKET_ERROR;
1751 fd = _get_sock_fd(s);
1752 res = SOCKET_ERROR;
1754 if (fd != -1)
1756 struct sockaddr* uaddr;
1757 int uaddrlen;
1759 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1760 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1762 SetLastError(wsaErrno());
1764 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1766 /* The buffer was too small */
1767 SetLastError(WSAEFAULT);
1769 else
1771 res=0;
1773 close(fd);
1775 else
1777 SetLastError(WSAENOTSOCK);
1779 return res;
1782 /***********************************************************************
1783 * getsockname (WINSOCK.6)
1785 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct WS_sockaddr *name,
1786 INT16 *namelen16)
1788 INT retVal;
1790 if( namelen16 )
1792 INT namelen32 = *namelen16;
1793 retVal = WS_getsockname( s, name, &namelen32 );
1794 *namelen16 = namelen32;
1796 #if DEBUG_SOCKADDR
1797 dump_sockaddr(name);
1798 #endif
1801 else retVal = SOCKET_ERROR;
1802 return (INT16)retVal;
1806 /***********************************************************************
1807 * getsockopt (WS2_32.7)
1809 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1810 INT optname, char *optval, INT *optlen)
1812 int fd;
1814 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1815 (int) optname, (int) optval, (int) *optlen);
1816 /* SO_OPENTYPE does not require a valid socket handle. */
1817 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1819 if (!optlen || *optlen < sizeof(int) || !optval)
1821 SetLastError(WSAEFAULT);
1822 return SOCKET_ERROR;
1824 *(int *)optval = (int)TlsGetValue( opentype_tls_index );
1825 *optlen = sizeof(int);
1826 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1827 return 0;
1830 fd = _get_sock_fd(s);
1831 if (fd != -1)
1833 if (!convert_sockopt(&level, &optname)) {
1834 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1835 } else {
1836 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1838 close(fd);
1839 return 0;
1841 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1843 close(fd);
1845 return SOCKET_ERROR;
1849 /***********************************************************************
1850 * getsockopt (WINSOCK.7)
1852 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1853 INT16 optname, char *optval, INT16 *optlen)
1855 INT optlen32;
1856 INT *p = &optlen32;
1857 INT retVal;
1858 if( optlen ) optlen32 = *optlen; else p = NULL;
1859 retVal = WS_getsockopt( s, (UINT16)level, optname, optval, p );
1860 if( optlen ) *optlen = optlen32;
1861 return (INT16)retVal;
1865 /***********************************************************************
1866 * htonl (WINSOCK.8)
1867 * htonl (WS2_32.8)
1869 u_long WINAPI WS_htonl(u_long hostlong)
1871 return htonl(hostlong);
1875 /***********************************************************************
1876 * htons (WINSOCK.9)
1877 * htons (WS2_32.9)
1879 u_short WINAPI WS_htons(u_short hostshort)
1881 return htons(hostshort);
1885 /***********************************************************************
1886 * inet_addr (WINSOCK.10)
1887 * inet_addr (WS2_32.11)
1889 u_long WINAPI WS_inet_addr(const char *cp)
1891 return inet_addr(cp);
1895 /***********************************************************************
1896 * ntohl (WINSOCK.14)
1897 * ntohl (WS2_32.14)
1899 u_long WINAPI WS_ntohl(u_long netlong)
1901 return ntohl(netlong);
1905 /***********************************************************************
1906 * ntohs (WINSOCK.15)
1907 * ntohs (WS2_32.15)
1909 u_short WINAPI WS_ntohs(u_short netshort)
1911 return ntohs(netshort);
1915 /***********************************************************************
1916 * inet_ntoa (WS2_32.12)
1918 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1920 /* use "buffer for dummies" here because some applications have
1921 * propensity to decode addresses in ws_hostent structure without
1922 * saving them first...
1924 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1926 char* s = inet_ntoa(*((struct in_addr*)&in));
1927 if( s )
1929 strcpy(dbuffer, s);
1930 return dbuffer;
1932 SetLastError(wsaErrno());
1933 return NULL;
1936 /***********************************************************************
1937 * inet_ntoa (WINSOCK.11)
1939 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1941 char* retVal;
1942 if (!(retVal = WS_inet_ntoa(*((struct WS_in_addr*)&in)))) return 0;
1943 if (!dbuffer_seg) dbuffer_seg = MapLS( retVal );
1944 return dbuffer_seg;
1948 /**********************************************************************
1949 * WSAIoctl (WS2_32.50)
1952 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1954 INT WINAPI WSAIoctl (SOCKET s,
1955 DWORD dwIoControlCode,
1956 LPVOID lpvInBuffer,
1957 DWORD cbInBuffer,
1958 LPVOID lpbOutBuffer,
1959 DWORD cbOutBuffer,
1960 LPDWORD lpcbBytesReturned,
1961 LPWSAOVERLAPPED lpOverlapped,
1962 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1964 int fd = _get_sock_fd(s);
1966 if (fd != -1)
1968 switch( dwIoControlCode )
1970 case SIO_GET_INTERFACE_LIST:
1972 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1973 DWORD size, numInt, apiReturn;
1975 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1977 if (!lpbOutBuffer)
1979 close(fd);
1980 WSASetLastError(WSAEFAULT);
1981 return SOCKET_ERROR;
1983 if (!lpcbBytesReturned)
1985 close(fd);
1986 WSASetLastError(WSAEFAULT);
1987 return SOCKET_ERROR;
1990 apiReturn = GetAdaptersInfo(NULL, &size);
1991 if (apiReturn == ERROR_NO_DATA)
1993 numInt = 0;
1995 else if (apiReturn == ERROR_BUFFER_OVERFLOW)
1997 PIP_ADAPTER_INFO table = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(),0,size);
1999 if (table)
2001 if (GetAdaptersInfo(table, &size) == NO_ERROR)
2003 PIP_ADAPTER_INFO ptr;
2005 if (size > cbOutBuffer)
2007 HeapFree(GetProcessHeap(),0,table);
2008 close(fd);
2009 WSASetLastError(WSAEFAULT);
2010 return (SOCKET_ERROR);
2012 for (ptr = table, numInt = 0; ptr;
2013 ptr = ptr->Next, intArray++, numInt++)
2015 unsigned int addr, mask, bcast;
2016 struct ifreq ifInfo;
2018 /* Socket Status Flags */
2019 strncpy(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
2020 ifInfo.ifr_name[IFNAMSIZ-1] = '\0';
2021 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
2023 ERR ("Error obtaining status flags for socket!\n");
2024 HeapFree(GetProcessHeap(),0,table);
2025 close(fd);
2026 WSASetLastError(WSAEINVAL);
2027 return (SOCKET_ERROR);
2029 else
2031 /* set flags; the values of IFF_* are not the same
2032 under Linux and Windows, therefore must generate
2033 new flags */
2034 intArray->iiFlags = 0;
2035 if (ifInfo.ifr_flags & IFF_BROADCAST)
2036 intArray->iiFlags |= WS_IFF_BROADCAST;
2037 #ifdef IFF_POINTOPOINT
2038 if (ifInfo.ifr_flags & IFF_POINTOPOINT)
2039 intArray->iiFlags |= WS_IFF_POINTTOPOINT;
2040 #endif
2041 if (ifInfo.ifr_flags & IFF_LOOPBACK)
2042 intArray->iiFlags |= WS_IFF_LOOPBACK;
2043 if (ifInfo.ifr_flags & IFF_UP)
2044 intArray->iiFlags |= WS_IFF_UP;
2047 addr = inet_addr(ptr->IpAddressList.IpAddress.String);
2048 mask = inet_addr(ptr->IpAddressList.IpMask.String);
2049 bcast = addr | (addr & !mask);
2050 intArray->iiAddress.AddressIn.sin_family = AF_INET;
2051 intArray->iiAddress.AddressIn.sin_port = 0;
2052 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
2053 addr;
2054 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2055 intArray->iiNetmask.AddressIn.sin_port = 0;
2056 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
2057 mask;
2058 intArray->iiBroadcastAddress.AddressIn.sin_family =
2059 AF_INET;
2060 intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
2061 intArray->iiBroadcastAddress.AddressIn.sin_addr.
2062 WS_s_addr = bcast;
2065 else
2067 ERR ("Unable to get interface table!\n");
2068 close(fd);
2069 HeapFree(GetProcessHeap(),0,table);
2070 WSASetLastError(WSAEINVAL);
2071 return (SOCKET_ERROR);
2073 HeapFree(GetProcessHeap(),0,table);
2075 else
2077 close(fd);
2078 WSASetLastError(WSAEINVAL);
2079 return (SOCKET_ERROR);
2082 else
2084 ERR ("Unable to get interface table!\n");
2085 close(fd);
2086 WSASetLastError(WSAEINVAL);
2087 return (SOCKET_ERROR);
2089 /* Calculate the size of the array being returned */
2090 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2091 break;
2094 default:
2096 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2097 close(fd);
2098 WSASetLastError(WSAEOPNOTSUPP);
2099 return (SOCKET_ERROR);
2103 /* Function executed with no errors */
2104 close(fd);
2105 return (0);
2107 else
2109 WSASetLastError(WSAENOTSOCK);
2110 return (SOCKET_ERROR);
2115 /***********************************************************************
2116 * ioctlsocket (WS2_32.10)
2118 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2120 int fd = _get_sock_fd(s);
2122 TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
2123 if (fd != -1)
2125 long newcmd = cmd;
2127 switch( cmd )
2129 case WS_FIONREAD:
2130 newcmd=FIONREAD;
2131 break;
2133 case WS_FIONBIO:
2134 newcmd=FIONBIO;
2135 if( _get_sock_mask(s) )
2137 /* AsyncSelect()'ed sockets are always nonblocking */
2138 if (*argp) {
2139 close(fd);
2140 return 0;
2142 SetLastError(WSAEINVAL);
2143 close(fd);
2144 return SOCKET_ERROR;
2146 close(fd);
2147 if (*argp)
2148 _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2149 else
2150 _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2151 return 0;
2153 case WS_SIOCATMARK:
2154 newcmd=SIOCATMARK;
2155 break;
2157 case WS__IOW('f',125,u_long):
2158 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2159 SetLastError(WSAEINVAL);
2160 return SOCKET_ERROR;
2162 case SIOCGIFBRDADDR:
2163 case SIOCGIFNETMASK:
2164 case SIOCGIFADDR:
2165 /* These don't need any special handling. They are used by
2166 WsControl, and are here to suppress an unecessary warning. */
2167 break;
2170 default:
2171 /* Netscape tries hard to use bogus ioctl 0x667e */
2172 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2174 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2176 close(fd);
2177 return 0;
2179 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2180 close(fd);
2182 return SOCKET_ERROR;
2185 /***********************************************************************
2186 * ioctlsocket (WINSOCK.12)
2188 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
2190 return (INT16)WS_ioctlsocket( s, cmd, argp );
2194 /***********************************************************************
2195 * listen (WS2_32.13)
2197 int WINAPI WS_listen(SOCKET s, int backlog)
2199 int fd = _get_sock_fd(s);
2201 TRACE("socket %04x, backlog %d\n", s, backlog);
2202 if (fd != -1)
2204 if (listen(fd, backlog) == 0)
2206 close(fd);
2207 _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2208 FD_WINE_LISTENING,
2209 FD_CONNECT|FD_WINE_CONNECTED);
2210 return 0;
2212 SetLastError(wsaErrno());
2214 else SetLastError(WSAENOTSOCK);
2215 return SOCKET_ERROR;
2218 /***********************************************************************
2219 * listen (WINSOCK.13)
2221 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
2223 return (INT16)WS_listen( s, backlog );
2227 /***********************************************************************
2228 * recv (WS2_32.16)
2230 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2232 DWORD n, dwFlags = flags;
2233 WSABUF wsabuf;
2235 wsabuf.len = len;
2236 wsabuf.buf = buf;
2238 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2239 return SOCKET_ERROR;
2240 else
2241 return n;
2244 /***********************************************************************
2245 * recv (WINSOCK.16)
2247 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2249 return (INT16)WS_recv( s, buf, len, flags );
2253 /***********************************************************************
2254 * recvfrom (WS2_32.17)
2256 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2257 struct WS_sockaddr *from, int *fromlen)
2259 DWORD n, dwFlags = flags;
2260 WSABUF wsabuf;
2262 wsabuf.len = len;
2263 wsabuf.buf = buf;
2265 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2266 return SOCKET_ERROR;
2267 else
2268 return n;
2271 /***********************************************************************
2272 * recvfrom (WINSOCK.17)
2274 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2275 struct WS_sockaddr *from, INT16 *fromlen16)
2277 INT fromlen32;
2278 INT *p = &fromlen32;
2279 INT retVal;
2281 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
2282 retVal = WS_recvfrom( s, buf, len, flags, from, p );
2283 if( fromlen16 ) *fromlen16 = fromlen32;
2284 return (INT16)retVal;
2287 /***********************************************************************
2288 * __ws_select
2290 static int __ws_select(BOOL b32,
2291 void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
2292 const struct WS_timeval *ws_timeout)
2294 int highfd = 0;
2295 fd_set readfds, writefds, exceptfds;
2296 fd_set *p_read, *p_write, *p_except;
2297 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2298 struct timeval timeout, *timeoutaddr = NULL;
2300 TRACE("read %p, write %p, excp %p timeout %p\n",
2301 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2303 p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
2304 p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
2305 p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
2306 if (ws_timeout)
2308 timeoutaddr = &timeout;
2309 timeout.tv_sec=ws_timeout->tv_sec;
2310 timeout.tv_usec=ws_timeout->tv_usec;
2313 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2315 fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
2316 fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
2318 if (p_except && ws_exceptfds)
2320 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
2321 #define wsfds32 ((WS_fd_set*)ws_exceptfds)
2322 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
2324 for (i = j = 0; i < count; i++)
2326 int fd = exceptfd[i];
2327 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
2329 if( b32 )
2330 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
2331 else
2332 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
2334 if( fd >= 0 ) close(fd);
2335 exceptfd[i] = -1;
2337 if( b32 )
2338 wsfds32->fd_count = j;
2339 else
2340 wsfds16->fd_count = j;
2341 #undef wsfds32
2342 #undef wsfds16
2344 return highfd;
2346 fd_set_unimport(ws_readfds, readfd, b32);
2347 fd_set_unimport(ws_writefds, writefd, b32);
2348 fd_set_unimport(ws_exceptfds, exceptfd, b32);
2349 if( ws_readfds ) ((WS_fd_set*)ws_readfds)->fd_count = 0;
2350 if( ws_writefds ) ((WS_fd_set*)ws_writefds)->fd_count = 0;
2351 if( ws_exceptfds ) ((WS_fd_set*)ws_exceptfds)->fd_count = 0;
2353 if( highfd == 0 ) return 0;
2354 SetLastError(wsaErrno());
2355 return SOCKET_ERROR;
2358 /***********************************************************************
2359 * select (WINSOCK.18)
2361 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
2362 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
2363 struct WS_timeval* timeout)
2365 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2368 /***********************************************************************
2369 * select (WS2_32.18)
2371 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2372 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2373 const struct WS_timeval* timeout)
2375 /* struct timeval is the same for both 32- and 16-bit code */
2376 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2380 /***********************************************************************
2381 * send (WS2_32.19)
2383 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2385 DWORD n;
2386 WSABUF wsabuf;
2388 wsabuf.len = len;
2389 wsabuf.buf = (char*) buf;
2391 if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2392 return SOCKET_ERROR;
2393 else
2394 return n;
2397 /***********************************************************************
2398 * WSASend (WS2_32.72)
2400 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2401 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2402 LPWSAOVERLAPPED lpOverlapped,
2403 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2405 return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2406 NULL, 0, lpOverlapped, lpCompletionRoutine );
2409 /***********************************************************************
2410 * WSASendDisconnect (WS2_32.73)
2412 INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2414 return WS_shutdown ( s, SD_SEND );
2418 /***********************************************************************
2419 * WSASendTo (WS2_32.74)
2421 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2422 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2423 const struct WS_sockaddr *to, int tolen,
2424 LPWSAOVERLAPPED lpOverlapped,
2425 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2427 int i, n, fd, err = WSAENOTSOCK, flags, ret;
2428 struct iovec* iovec;
2429 struct ws2_async *wsa;
2430 enum fd_type type;
2432 TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2433 s, lpBuffers, dwBufferCount, dwFlags,
2434 to, tolen, lpOverlapped, lpCompletionRoutine);
2436 fd = _get_sock_fd_type( s, GENERIC_WRITE, &type, &flags );
2437 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
2439 if ( fd == -1 )
2441 err = WSAGetLastError ();
2442 goto error;
2445 if ( !lpNumberOfBytesSent )
2447 err = WSAEFAULT;
2448 goto error;
2451 iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
2453 if ( !iovec )
2455 err = WSAEFAULT;
2456 goto err_close;
2459 for ( i = 0; i < dwBufferCount; i++ )
2461 iovec[i].iov_base = lpBuffers[i].buf;
2462 iovec[i].iov_len = lpBuffers[i].len;
2465 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2467 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
2468 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2469 lpOverlapped, lpCompletionRoutine );
2470 if ( !wsa )
2472 err = WSAEFAULT;
2473 goto err_free;
2476 if ( ( ret = register_new_async ( &wsa->async )) )
2478 err = NtStatusToWSAError ( ret );
2480 if ( !lpOverlapped )
2481 HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
2482 HeapFree ( GetProcessHeap(), 0, wsa );
2483 goto err_free;
2486 /* Try immediate completion */
2487 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
2489 if ( WSAGetOverlappedResult ( s, lpOverlapped,
2490 lpNumberOfBytesSent, FALSE, &dwFlags) )
2491 return 0;
2493 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
2494 goto error;
2497 WSASetLastError ( WSA_IO_PENDING );
2498 return SOCKET_ERROR;
2501 if (_is_blocking(s))
2503 /* FIXME: exceptfds? */
2504 do_block(fd, POLLOUT);
2507 n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2508 if ( n == -1 )
2510 err = wsaErrno();
2511 if ( err == WSAEWOULDBLOCK )
2512 _enable_event (SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2513 goto err_free;
2516 TRACE(" -> %i bytes\n", n);
2517 *lpNumberOfBytesSent = n;
2519 HeapFree ( GetProcessHeap(), 0, iovec );
2520 close ( fd );
2521 return 0;
2523 err_free:
2524 HeapFree ( GetProcessHeap(), 0, iovec );
2526 err_close:
2527 close ( fd );
2529 error:
2530 WARN (" -> ERROR %d\n", err);
2531 WSASetLastError (err);
2532 return SOCKET_ERROR;
2535 /***********************************************************************
2536 * send (WINSOCK.19)
2538 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2540 return WS_send( s, buf, len, flags );
2543 /***********************************************************************
2544 * sendto (WS2_32.20)
2546 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2547 const struct WS_sockaddr *to, int tolen)
2549 DWORD n;
2550 WSABUF wsabuf;
2552 wsabuf.len = len;
2553 wsabuf.buf = (char*) buf;
2555 if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2556 return SOCKET_ERROR;
2557 else
2558 return n;
2561 /***********************************************************************
2562 * sendto (WINSOCK.20)
2564 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2565 struct WS_sockaddr *to, INT16 tolen)
2567 return (INT16)WS_sendto( s, buf, len, flags, to, tolen );
2570 /***********************************************************************
2571 * setsockopt (WS2_32.21)
2573 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2574 const char *optval, int optlen)
2576 int fd;
2578 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
2579 (int) optname, (int) optval, optlen);
2580 /* SO_OPENTYPE does not require a valid socket handle. */
2581 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2583 if (optlen < sizeof(int) || !optval)
2585 SetLastError(WSAEFAULT);
2586 return SOCKET_ERROR;
2588 TlsSetValue( opentype_tls_index, (LPVOID)*(int *)optval );
2589 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2590 return 0;
2593 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2594 * socket. This will either not happen under windows or it is ignored in
2595 * windows (but it works in linux and therefor prevents the game to find
2596 * games outsite the current network) */
2597 if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE )
2599 FIXME("Does windows ignore SO_DONTROUTE?\n");
2600 return 0;
2604 fd = _get_sock_fd(s);
2605 if (fd != -1)
2607 struct linger linger;
2608 int woptval;
2609 struct timeval tval;
2611 /* Is a privileged and useless operation, so we don't. */
2612 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
2613 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2614 return 0;
2617 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2618 /* This is unique to WinSock and takes special conversion */
2619 linger.l_onoff = *((int*)optval) ? 0: 1;
2620 linger.l_linger = 0;
2621 optname=SO_LINGER;
2622 optval = (char*)&linger;
2623 optlen = sizeof(struct linger);
2624 level = SOL_SOCKET;
2625 }else{
2626 if (!convert_sockopt(&level, &optname)) {
2627 ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2628 SetLastError(WSAENOPROTOOPT);
2629 close(fd);
2630 return SOCKET_ERROR;
2632 if (optname == SO_LINGER && optval) {
2633 /* yes, uses unsigned short in both win16/win32 */
2634 linger.l_onoff = ((UINT16*)optval)[0];
2635 linger.l_linger = ((UINT16*)optval)[1];
2636 /* FIXME: what is documented behavior if SO_LINGER optval
2637 is null?? */
2638 optval = (char*)&linger;
2639 optlen = sizeof(struct linger);
2640 } else if (optval && optlen < sizeof(int)){
2641 woptval= *((INT16 *) optval);
2642 optval= (char*) &woptval;
2643 optlen=sizeof(int);
2645 #ifdef SO_RCVTIMEO
2646 if (level == SOL_SOCKET && optname == SO_RCVTIMEO) {
2647 if (optlen == sizeof(UINT32)) {
2648 /* WinSock passes miliseconds instead of struct timeval */
2649 tval.tv_usec = *(PUINT32)optval % 1000;
2650 tval.tv_sec = *(PUINT32)optval / 1000;
2651 /* min of 500 milisec */
2652 if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2653 optlen = sizeof(struct timeval);
2654 optval = (char*)&tval;
2655 } else if (optlen == sizeof(struct timeval)) {
2656 WARN("SO_RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2657 } else {
2658 WARN("SO_RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2659 close(fd);
2660 return 0;
2663 #endif
2664 #ifdef SO_SNDTIMEO
2665 if (level == SOL_SOCKET && optname == SO_SNDTIMEO) {
2666 if (optlen == sizeof(UINT32)) {
2667 /* WinSock passes miliseconds instead of struct timeval */
2668 tval.tv_usec = *(PUINT32)optval % 1000;
2669 tval.tv_sec = *(PUINT32)optval / 1000;
2670 /* min of 500 milisec */
2671 if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2672 optlen = sizeof(struct timeval);
2673 optval = (char*)&tval;
2674 } else if (optlen == sizeof(struct timeval)) {
2675 WARN("SO_SNDTIMEO for %d bytes: assuming unixism\n", optlen);
2676 } else {
2677 WARN("SO_SNDTIMEO for %d bytes is weird: ignored\n", optlen);
2678 close(fd);
2679 return 0;
2682 #endif
2684 if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2685 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2686 close( fd);
2687 return 0;
2690 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2692 close(fd);
2693 return 0;
2695 TRACE("Setting socket error, %d\n", wsaErrno());
2696 SetLastError(wsaErrno());
2697 close(fd);
2699 else SetLastError(WSAENOTSOCK);
2700 return SOCKET_ERROR;
2703 /***********************************************************************
2704 * setsockopt (WINSOCK.21)
2706 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2707 char *optval, INT16 optlen)
2709 if( !optval ) return SOCKET_ERROR;
2710 return (INT16)WS_setsockopt( s, (UINT16)level, optname, optval, optlen );
2714 /***********************************************************************
2715 * shutdown (WS2_32.22)
2717 int WINAPI WS_shutdown(SOCKET s, int how)
2719 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2720 enum fd_type type;
2721 unsigned int clear_flags = 0;
2723 fd = _get_sock_fd_type ( s, 0, &type, &flags );
2724 TRACE("socket %04x, how %i %d %d \n", s, how, type, flags );
2726 if (fd == -1)
2727 return SOCKET_ERROR;
2729 switch( how )
2731 case 0: /* drop receives */
2732 clear_flags |= FD_READ;
2733 break;
2734 case 1: /* drop sends */
2735 clear_flags |= FD_WRITE;
2736 break;
2737 case 2: /* drop all */
2738 clear_flags |= FD_READ|FD_WRITE;
2739 default:
2740 clear_flags |= FD_WINE_LISTENING;
2743 if ( flags & FD_FLAG_OVERLAPPED ) {
2745 switch ( how )
2747 case SD_RECEIVE:
2748 fd0 = fd;
2749 break;
2750 case SD_SEND:
2751 fd1 = fd;
2752 break;
2753 case SD_BOTH:
2754 default:
2755 fd0 = fd;
2756 fd1 = _get_sock_fd ( s );
2759 if ( fd0 != -1 )
2761 err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
2762 if ( err )
2764 close ( fd0 );
2765 goto error;
2768 if ( fd1 != -1 )
2770 err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
2771 if ( err )
2773 close ( fd1 );
2774 goto error;
2778 else /* non-overlapped mode */
2780 if ( shutdown( fd, how ) )
2782 err = wsaErrno ();
2783 close ( fd );
2784 goto error;
2786 close(fd);
2789 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2790 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2791 return 0;
2793 error:
2794 _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2795 WSASetLastError ( err );
2796 return SOCKET_ERROR;
2799 /***********************************************************************
2800 * shutdown (WINSOCK.22)
2802 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2804 return (INT16)WS_shutdown( s, how );
2808 /***********************************************************************
2809 * socket (WS2_32.23)
2811 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2813 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2815 return WSASocketA ( af, type, protocol, NULL, 0,
2816 (TlsGetValue(opentype_tls_index) ? 0 : WSA_FLAG_OVERLAPPED) );
2819 /***********************************************************************
2820 * socket (WINSOCK.23)
2822 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2824 return (SOCKET16)WS_socket( af, type, protocol );
2828 /* ----------------------------------- DNS services
2830 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2831 * Also, we have to use wsock32 stubs to convert structures and
2832 * error codes from Unix to WSA, hence there is no direct mapping in
2833 * the relay32/wsock32.spec.
2837 /***********************************************************************
2838 * __ws_gethostbyaddr
2840 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2842 WIN_hostent *retval = NULL;
2844 struct hostent* host;
2845 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2846 char *extrabuf;
2847 int ebufsize=1024;
2848 struct hostent hostentry;
2849 int locerr=ENOBUFS;
2850 host = NULL;
2851 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2852 while(extrabuf) {
2853 int res = gethostbyaddr_r(addr, len, type,
2854 &hostentry, extrabuf, ebufsize, &host, &locerr);
2855 if( res != ERANGE) break;
2856 ebufsize *=2;
2857 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2859 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2860 #else
2861 EnterCriticalSection( &csWSgetXXXbyYYY );
2862 host = gethostbyaddr(addr, len, type);
2863 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2864 #endif
2865 if( host != NULL )
2867 if( WS_dup_he(host, dup_flag) )
2868 retval = he_buffer;
2869 else
2870 SetLastError(WSAENOBUFS);
2872 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2873 HeapFree(GetProcessHeap(),0,extrabuf);
2874 #else
2875 LeaveCriticalSection( &csWSgetXXXbyYYY );
2876 #endif
2877 return retval;
2880 /***********************************************************************
2881 * gethostbyaddr (WINSOCK.51)
2883 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2885 TRACE("ptr %p, len %d, type %d\n", addr, len, type);
2886 if (!__ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR )) return 0;
2887 return he_buffer_seg;
2890 /***********************************************************************
2891 * gethostbyaddr (WS2_32.51)
2893 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len,
2894 int type)
2896 TRACE("ptr %08x, len %d, type %d\n",
2897 (unsigned) addr, len, type);
2898 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2901 /***********************************************************************
2902 * __ws_gethostbyname
2904 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2906 WIN_hostent *retval = NULL;
2907 struct hostent* host;
2908 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2909 char *extrabuf;
2910 int ebufsize=1024;
2911 struct hostent hostentry;
2912 int locerr = ENOBUFS;
2913 #endif
2914 char buf[100];
2915 if( !name) {
2916 name = buf;
2917 if( gethostname( buf, 100) == -1) {
2918 SetLastError( WSAENOBUFS); /* appropriate ? */
2919 return retval;
2922 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2923 host = NULL;
2924 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2925 while(extrabuf) {
2926 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2927 if( res != ERANGE) break;
2928 ebufsize *=2;
2929 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2931 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2932 #else
2933 EnterCriticalSection( &csWSgetXXXbyYYY );
2934 host = gethostbyname(name);
2935 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2936 #endif
2937 if( host != NULL )
2939 if( WS_dup_he(host, dup_flag) )
2940 retval = he_buffer;
2941 else SetLastError(WSAENOBUFS);
2943 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2944 HeapFree(GetProcessHeap(),0,extrabuf);
2945 #else
2946 LeaveCriticalSection( &csWSgetXXXbyYYY );
2947 #endif
2948 return retval;
2951 /***********************************************************************
2952 * gethostbyname (WINSOCK.52)
2954 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2956 TRACE( "%s\n", debugstr_a(name) );
2957 if (!__ws_gethostbyname( name, WS_DUP_SEGPTR )) return 0;
2958 return he_buffer_seg;
2961 /***********************************************************************
2962 * gethostbyname (WS2_32.52)
2964 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2966 TRACE( "%s\n", debugstr_a(name) );
2967 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2971 /***********************************************************************
2972 * __ws_getprotobyname
2974 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2976 WIN_protoent* retval = NULL;
2977 #ifdef HAVE_GETPROTOBYNAME
2978 struct protoent* proto;
2979 EnterCriticalSection( &csWSgetXXXbyYYY );
2980 if( (proto = getprotobyname(name)) != NULL )
2982 if( WS_dup_pe(proto, dup_flag) )
2983 retval = pe_buffer;
2984 else SetLastError(WSAENOBUFS);
2986 else {
2987 MESSAGE("protocol %s not found; You might want to add "
2988 "this to /etc/protocols\n", debugstr_a(name) );
2989 SetLastError(WSANO_DATA);
2991 LeaveCriticalSection( &csWSgetXXXbyYYY );
2992 #endif
2993 return retval;
2996 /***********************************************************************
2997 * getprotobyname (WINSOCK.53)
2999 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
3001 TRACE( "%s\n", debugstr_a(name) );
3002 if (!__ws_getprotobyname(name, WS_DUP_SEGPTR)) return 0;
3003 return pe_buffer_seg;
3006 /***********************************************************************
3007 * getprotobyname (WS2_32.53)
3009 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
3011 TRACE( "%s\n", debugstr_a(name) );
3012 return __ws_getprotobyname(name, WS_DUP_LINEAR);
3016 /***********************************************************************
3017 * __ws_getprotobynumber
3019 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
3021 WIN_protoent* retval = NULL;
3022 #ifdef HAVE_GETPROTOBYNUMBER
3023 struct protoent* proto;
3024 EnterCriticalSection( &csWSgetXXXbyYYY );
3025 if( (proto = getprotobynumber(number)) != NULL )
3027 if( WS_dup_pe(proto, dup_flag) )
3028 retval = pe_buffer;
3029 else SetLastError(WSAENOBUFS);
3031 else {
3032 MESSAGE("protocol number %d not found; You might want to add "
3033 "this to /etc/protocols\n", number );
3034 SetLastError(WSANO_DATA);
3036 LeaveCriticalSection( &csWSgetXXXbyYYY );
3037 #endif
3038 return retval;
3041 /***********************************************************************
3042 * getprotobynumber (WINSOCK.54)
3044 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
3046 TRACE("%i\n", number);
3047 if (!__ws_getprotobynumber(number, WS_DUP_SEGPTR)) return 0;
3048 return pe_buffer_seg;
3051 /***********************************************************************
3052 * getprotobynumber (WS2_32.54)
3054 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
3056 TRACE("%i\n", number);
3057 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
3061 /***********************************************************************
3062 * __ws_getservbyname
3064 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
3066 WIN_servent* retval = NULL;
3067 struct servent* serv;
3068 int i = wsi_strtolo( name, proto );
3070 if( i ) {
3071 EnterCriticalSection( &csWSgetXXXbyYYY );
3072 serv = getservbyname(local_buffer,
3073 proto && *proto ? (local_buffer + i) : NULL);
3074 if( serv != NULL )
3076 if( WS_dup_se(serv, dup_flag) )
3077 retval = se_buffer;
3078 else SetLastError(WSAENOBUFS);
3080 else {
3081 MESSAGE("service %s protocol %s not found; You might want to add "
3082 "this to /etc/services\n", debugstr_a(local_buffer),
3083 proto ? debugstr_a(local_buffer+i):"*");
3084 SetLastError(WSANO_DATA);
3086 LeaveCriticalSection( &csWSgetXXXbyYYY );
3088 else SetLastError(WSAENOBUFS);
3089 return retval;
3092 /***********************************************************************
3093 * getservbyname (WINSOCK.55)
3095 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
3097 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3098 if (!__ws_getservbyname(name, proto, WS_DUP_SEGPTR)) return 0;
3099 return se_buffer_seg;
3102 /***********************************************************************
3103 * getservbyname (WS2_32.55)
3105 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
3107 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3108 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
3112 /***********************************************************************
3113 * __ws_getservbyport
3115 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
3117 WIN_servent* retval = NULL;
3118 #ifdef HAVE_GETSERVBYPORT
3119 struct servent* serv;
3120 if (!proto || wsi_strtolo( proto, NULL )) {
3121 EnterCriticalSection( &csWSgetXXXbyYYY );
3122 if( (serv = getservbyport(port, proto && *proto ? local_buffer :
3123 NULL)) != NULL ) {
3124 if( WS_dup_se(serv, dup_flag) )
3125 retval = se_buffer;
3126 else SetLastError(WSAENOBUFS);
3128 else {
3129 MESSAGE("service on port %lu protocol %s not found; You might want to add "
3130 "this to /etc/services\n", (unsigned long)ntohl(port),
3131 proto ? debugstr_a(local_buffer) : "*");
3132 SetLastError(WSANO_DATA);
3134 LeaveCriticalSection( &csWSgetXXXbyYYY );
3136 else SetLastError(WSAENOBUFS);
3137 #endif
3138 return retval;
3141 /***********************************************************************
3142 * getservbyport (WINSOCK.56)
3144 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
3146 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3147 if (!__ws_getservbyport(port, proto, WS_DUP_SEGPTR)) return 0;
3148 return se_buffer_seg;
3151 /***********************************************************************
3152 * getservbyport (WS2_32.56)
3154 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
3156 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3157 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
3161 /***********************************************************************
3162 * gethostname (WS2_32.57)
3164 int WINAPI WS_gethostname(char *name, int namelen)
3166 TRACE("name %p, len %d\n", name, namelen);
3168 if (gethostname(name, namelen) == 0)
3170 TRACE("<- '%s'\n", name);
3171 return 0;
3173 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
3174 TRACE("<- ERROR !\n");
3175 return SOCKET_ERROR;
3178 /***********************************************************************
3179 * gethostname (WINSOCK.57)
3181 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
3183 return (INT16)WS_gethostname(name, namelen);
3187 /* ------------------------------------- Windows sockets extensions -- *
3189 * ------------------------------------------------------------------- */
3191 /***********************************************************************
3192 * WSAEnumNetworkEvents (WS2_32.36)
3194 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
3196 int ret;
3198 TRACE("%08x, hEvent %p, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
3200 SERVER_START_REQ( get_socket_event )
3202 req->handle = SOCKET2HANDLE(s);
3203 req->service = TRUE;
3204 req->c_event = hEvent;
3205 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
3206 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
3208 SERVER_END_REQ;
3209 if (!ret) return 0;
3210 SetLastError(WSAEINVAL);
3211 return SOCKET_ERROR;
3214 /***********************************************************************
3215 * WSAEventSelect (WS2_32.39)
3217 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
3219 int ret;
3221 TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
3223 SERVER_START_REQ( set_socket_event )
3225 req->handle = SOCKET2HANDLE(s);
3226 req->mask = lEvent;
3227 req->event = hEvent;
3228 req->window = 0;
3229 req->msg = 0;
3230 ret = wine_server_call( req );
3232 SERVER_END_REQ;
3233 if (!ret) return 0;
3234 SetLastError(WSAEINVAL);
3235 return SOCKET_ERROR;
3238 /**********************************************************************
3239 * WSAGetOverlappedResult (WS2_32.40)
3241 BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
3242 LPDWORD lpcbTransfer, BOOL fWait,
3243 LPDWORD lpdwFlags )
3245 DWORD r;
3247 TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
3248 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
3250 if ( !(lpOverlapped && lpOverlapped->hEvent) )
3252 ERR ( "Invalid pointer\n" );
3253 WSASetLastError (WSA_INVALID_PARAMETER);
3254 return FALSE;
3257 if ( fWait )
3259 while ( WaitForSingleObjectEx (lpOverlapped->hEvent, INFINITE, TRUE) == STATUS_USER_APC );
3261 else if ( lpOverlapped->Internal == STATUS_PENDING )
3263 /* Wait in order to give APCs a chance to run. */
3264 /* This is cheating, so we must set the event again in case of success -
3265 it may be a non-manual reset event. */
3266 while ( (r = WaitForSingleObjectEx (lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
3267 if ( r == WAIT_OBJECT_0 )
3268 NtSetEvent ( lpOverlapped->hEvent, NULL );
3271 if ( lpcbTransfer )
3272 *lpcbTransfer = lpOverlapped->InternalHigh;
3274 if ( lpdwFlags )
3275 *lpdwFlags = lpOverlapped->Offset;
3277 switch ( lpOverlapped->Internal )
3279 case STATUS_SUCCESS:
3280 return TRUE;
3281 case STATUS_PENDING:
3282 WSASetLastError ( WSA_IO_INCOMPLETE );
3283 if (fWait) ERR ("PENDING status after waiting!\n");
3284 return FALSE;
3285 default:
3286 WSASetLastError ( NtStatusToWSAError ( lpOverlapped->Internal ));
3287 return FALSE;
3292 /***********************************************************************
3293 * WSAAsyncSelect (WS2_32.101)
3295 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
3297 int ret;
3299 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3301 SERVER_START_REQ( set_socket_event )
3303 req->handle = SOCKET2HANDLE(s);
3304 req->mask = lEvent;
3305 req->event = 0;
3306 req->window = hWnd;
3307 req->msg = uMsg;
3308 ret = wine_server_call( req );
3310 SERVER_END_REQ;
3311 if (!ret) return 0;
3312 SetLastError(WSAEINVAL);
3313 return SOCKET_ERROR;
3316 /***********************************************************************
3317 * WSAAsyncSelect (WINSOCK.101)
3319 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
3321 return (INT16)WSAAsyncSelect( s, HWND_32(hWnd), wMsg, lEvent );
3324 /***********************************************************************
3325 * WSARecvEx (WINSOCK.1107)
3327 * See description for WSARecvEx()
3329 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags)
3331 FIXME("(WSARecvEx16) partial packet return value not set \n");
3333 return WINSOCK_recv16(s, buf, len, *flags);
3337 /***********************************************************************
3338 * WSACreateEvent (WS2_32.31)
3341 WSAEVENT WINAPI WSACreateEvent(void)
3343 /* Create a manual-reset event, with initial state: unsignealed */
3344 TRACE("\n");
3346 return CreateEventA(NULL, TRUE, FALSE, NULL);
3349 /***********************************************************************
3350 * WSACloseEvent (WS2_32.29)
3353 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3355 TRACE ("event=%p\n", event);
3357 return CloseHandle(event);
3360 /***********************************************************************
3361 * WSASocketA (WS2_32.78)
3364 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3365 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3366 GROUP g, DWORD dwFlags)
3368 SOCKET ret;
3371 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
3372 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3375 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3376 af, type, protocol, lpProtocolInfo, g, dwFlags );
3378 /* hack for WSADuplicateSocket */
3379 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3380 ret = lpProtocolInfo->dwCatalogEntryId;
3381 TRACE("\tgot duplicate %04x\n", ret);
3382 return ret;
3385 /* check the socket family */
3386 switch(af)
3388 #ifdef HAVE_IPX
3389 case WS_AF_IPX: af = AF_IPX;
3390 #endif
3391 case AF_INET:
3392 case AF_UNSPEC:
3393 break;
3394 default:
3395 SetLastError(WSAEAFNOSUPPORT);
3396 return INVALID_SOCKET;
3399 /* check the socket type */
3400 switch(type)
3402 case WS_SOCK_STREAM:
3403 type=SOCK_STREAM;
3404 break;
3405 case WS_SOCK_DGRAM:
3406 type=SOCK_DGRAM;
3407 break;
3408 case WS_SOCK_RAW:
3409 type=SOCK_RAW;
3410 break;
3411 default:
3412 SetLastError(WSAESOCKTNOSUPPORT);
3413 return INVALID_SOCKET;
3416 /* check the protocol type */
3417 if ( protocol < 0 ) /* don't support negative values */
3419 SetLastError(WSAEPROTONOSUPPORT);
3420 return INVALID_SOCKET;
3423 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3424 switch(protocol)
3426 case IPPROTO_TCP:
3427 if (type == SOCK_STREAM) { af = AF_INET; break; }
3428 case IPPROTO_UDP:
3429 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3430 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3433 SERVER_START_REQ( create_socket )
3435 req->family = af;
3436 req->type = type;
3437 req->protocol = protocol;
3438 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3439 req->flags = dwFlags;
3440 req->inherit = TRUE;
3441 set_error( wine_server_call( req ) );
3442 ret = HANDLE2SOCKET( reply->handle );
3444 SERVER_END_REQ;
3445 if (ret)
3447 TRACE("\tcreated %04x\n", ret );
3448 return ret;
3451 if (GetLastError() == WSAEACCES) /* raw socket denied */
3453 if (type == SOCK_RAW)
3454 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3455 else
3456 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3457 SetLastError(WSAESOCKTNOSUPPORT);
3460 WARN("\t\tfailed!\n");
3461 return INVALID_SOCKET;
3465 /***********************************************************************
3466 * __WSAFDIsSet (WINSOCK.151)
3468 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
3470 int i = set->fd_count;
3472 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3474 while (i--)
3475 if (set->fd_array[i] == s) return 1;
3476 return 0;
3479 /***********************************************************************
3480 * __WSAFDIsSet (WS2_32.151)
3482 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3484 int i = set->fd_count;
3486 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3488 while (i--)
3489 if (set->fd_array[i] == s) return 1;
3490 return 0;
3493 /***********************************************************************
3494 * WSAIsBlocking (WINSOCK.114)
3495 * WSAIsBlocking (WS2_32.114)
3497 BOOL WINAPI WSAIsBlocking(void)
3499 /* By default WinSock should set all its sockets to non-blocking mode
3500 * and poll in PeekMessage loop when processing "blocking" ones. This
3501 * function is supposed to tell if the program is in this loop. Our
3502 * blocking calls are truly blocking so we always return FALSE.
3504 * Note: It is allowed to call this function without prior WSAStartup().
3507 TRACE("\n");
3508 return FALSE;
3511 /***********************************************************************
3512 * WSACancelBlockingCall (WINSOCK.113)
3513 * WSACancelBlockingCall (WS2_32.113)
3515 INT WINAPI WSACancelBlockingCall(void)
3517 TRACE("\n");
3518 return 0;
3521 static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
3523 FIXME("How was this called?\n");
3524 return x();
3528 /***********************************************************************
3529 * WSASetBlockingHook (WINSOCK.109)
3531 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
3533 FARPROC16 prev = (FARPROC16)blocking_hook;
3534 blocking_hook = (FARPROC)lpBlockFunc;
3535 TRACE("hook %p\n", lpBlockFunc);
3536 return prev;
3540 /***********************************************************************
3541 * WSASetBlockingHook (WS2_32.109)
3543 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3545 FARPROC prev = blocking_hook;
3546 blocking_hook = lpBlockFunc;
3547 TRACE("hook %p\n", lpBlockFunc);
3548 return prev;
3552 /***********************************************************************
3553 * WSAUnhookBlockingHook (WINSOCK.110)
3555 INT16 WINAPI WSAUnhookBlockingHook16(void)
3557 blocking_hook = WSA_DefaultBlockingHook;
3558 return 0;
3562 /***********************************************************************
3563 * WSAUnhookBlockingHook (WS2_32.110)
3565 INT WINAPI WSAUnhookBlockingHook(void)
3567 blocking_hook = WSA_DefaultBlockingHook;
3568 return 0;
3572 /* ----------------------------------- end of API stuff */
3574 /* ----------------------------------- helper functions -
3576 * TODO: Merge WS_dup_..() stuff into one function that
3577 * would operate with a generic structure containing internal
3578 * pointers (via a template of some kind).
3581 static int list_size(char** l, int item_size)
3583 int i,j = 0;
3584 if(l)
3585 { for(i=0;l[i];i++)
3586 j += (item_size) ? item_size : strlen(l[i]) + 1;
3587 j += (i + 1) * sizeof(char*); }
3588 return j;
3591 static int list_dup(char** l_src, char* ref, char* base, int item_size)
3593 /* base is either either equal to ref or 0 or SEGPTR */
3595 char* p = ref;
3596 char** l_to = (char**)ref;
3597 int i,j,k;
3599 for(j=0;l_src[j];j++) ;
3600 p += (j + 1) * sizeof(char*);
3601 for(i=0;i<j;i++)
3602 { l_to[i] = base + (p - ref);
3603 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3604 memcpy(p, l_src[i], k); p += k; }
3605 l_to[i] = NULL;
3606 return (p - ref);
3609 /* ----- hostent */
3611 static int hostent_size(struct hostent* p_he)
3613 int size = 0;
3614 if( p_he )
3615 { size = sizeof(struct hostent);
3616 size += strlen(p_he->h_name) + 1;
3617 size += list_size(p_he->h_aliases, 0);
3618 size += list_size(p_he->h_addr_list, p_he->h_length ); }
3619 return size;
3622 /* duplicate hostent entry
3623 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3624 * Dito for protoent and servent.
3626 static int WS_dup_he(struct hostent* p_he, int flag)
3628 /* Convert hostent structure into ws_hostent so that the data fits
3629 * into local_buffer. Internal pointers can be linear, SEGPTR, or
3630 * relative to local_buffer depending on "flag" value. Returns size
3631 * of the data copied.
3634 int size = hostent_size(p_he);
3635 if( size )
3637 char *p_name,*p_aliases,*p_addr,*p_base,*p;
3638 char *p_to;
3639 struct ws_hostent16 *p_to16;
3640 struct WS_hostent *p_to32;
3642 check_buffer_he(size);
3643 p_to = he_buffer;
3644 p_to16 = he_buffer;
3645 p_to32 = he_buffer;
3647 p = p_to;
3648 p_base = (flag & WS_DUP_SEGPTR) ? (char*)he_buffer_seg : he_buffer;
3649 p += (flag & WS_DUP_SEGPTR) ?
3650 sizeof(struct ws_hostent16) : sizeof(struct WS_hostent);
3651 p_name = p;
3652 strcpy(p, p_he->h_name); p += strlen(p) + 1;
3653 p_aliases = p;
3654 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3655 p_addr = p;
3656 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
3658 if (flag & WS_DUP_SEGPTR) /* Win16 */
3660 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
3661 p_to16->h_length = (INT16)p_he->h_length;
3662 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3663 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3664 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3665 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3667 else /* Win32 */
3669 p_to32->h_addrtype = p_he->h_addrtype;
3670 p_to32->h_length = p_he->h_length;
3671 p_to32->h_name = (p_base + (p_name - p_to));
3672 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3673 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3674 size += (sizeof(struct WS_hostent) - sizeof(struct hostent));
3677 return size;
3680 /* ----- protoent */
3682 static int protoent_size(struct protoent* p_pe)
3684 int size = 0;
3685 if( p_pe )
3686 { size = sizeof(struct protoent);
3687 size += strlen(p_pe->p_name) + 1;
3688 size += list_size(p_pe->p_aliases, 0); }
3689 return size;
3692 static int WS_dup_pe(struct protoent* p_pe, int flag)
3694 int size = protoent_size(p_pe);
3695 if( size )
3697 char *p_to;
3698 struct ws_protoent16 *p_to16;
3699 struct WS_protoent *p_to32;
3700 char *p_name,*p_aliases,*p_base,*p;
3702 check_buffer_pe(size);
3703 p_to = pe_buffer;
3704 p_to16 = pe_buffer;
3705 p_to32 = pe_buffer;
3706 p = p_to;
3707 p_base = (flag & WS_DUP_SEGPTR) ? (char*)pe_buffer_seg : pe_buffer;
3708 p += (flag & WS_DUP_SEGPTR) ?
3709 sizeof(struct ws_protoent16) : sizeof(struct WS_protoent);
3710 p_name = p;
3711 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3712 p_aliases = p;
3713 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3715 if (flag & WS_DUP_SEGPTR) /* Win16 */
3717 p_to16->p_proto = (INT16)p_pe->p_proto;
3718 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3719 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3720 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3722 else /* Win32 */
3724 p_to32->p_proto = p_pe->p_proto;
3725 p_to32->p_name = (p_base) + (p_name - p_to);
3726 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3727 size += (sizeof(struct WS_protoent) - sizeof(struct protoent));
3730 return size;
3733 /* ----- servent */
3735 static int servent_size(struct servent* p_se)
3737 int size = 0;
3738 if( p_se )
3739 { size += sizeof(struct servent);
3740 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3741 size += list_size(p_se->s_aliases, 0); }
3742 return size;
3745 static int WS_dup_se(struct servent* p_se, int flag)
3747 int size = servent_size(p_se);
3748 if( size )
3750 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3751 char *p_to;
3752 struct ws_servent16 *p_to16;
3753 struct WS_servent *p_to32;
3755 check_buffer_se(size);
3756 p_to = se_buffer;
3757 p_to16 = se_buffer;
3758 p_to32 = se_buffer;
3759 p = p_to;
3760 p_base = (flag & WS_DUP_SEGPTR) ? (char*)se_buffer_seg : se_buffer;
3761 p += (flag & WS_DUP_SEGPTR) ?
3762 sizeof(struct ws_servent16) : sizeof(struct WS_servent);
3763 p_name = p;
3764 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3765 p_proto = p;
3766 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3767 p_aliases = p;
3768 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3770 if (flag & WS_DUP_SEGPTR) /* Win16 */
3772 p_to16->s_port = (INT16)p_se->s_port;
3773 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3774 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3775 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3776 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3778 else /* Win32 */
3780 p_to32->s_port = p_se->s_port;
3781 p_to32->s_name = (p_base + (p_name - p_to));
3782 p_to32->s_proto = (p_base + (p_proto - p_to));
3783 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3784 size += (sizeof(struct WS_servent) - sizeof(struct servent));
3787 return size;
3790 /* ----------------------------------- error handling */
3792 UINT16 wsaErrno(void)
3794 int loc_errno = errno;
3795 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3797 switch(loc_errno)
3799 case EINTR: return WSAEINTR;
3800 case EBADF: return WSAEBADF;
3801 case EPERM:
3802 case EACCES: return WSAEACCES;
3803 case EFAULT: return WSAEFAULT;
3804 case EINVAL: return WSAEINVAL;
3805 case EMFILE: return WSAEMFILE;
3806 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3807 case EINPROGRESS: return WSAEINPROGRESS;
3808 case EALREADY: return WSAEALREADY;
3809 case ENOTSOCK: return WSAENOTSOCK;
3810 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3811 case EMSGSIZE: return WSAEMSGSIZE;
3812 case EPROTOTYPE: return WSAEPROTOTYPE;
3813 case ENOPROTOOPT: return WSAENOPROTOOPT;
3814 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3815 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3816 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3817 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3818 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3819 case EADDRINUSE: return WSAEADDRINUSE;
3820 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3821 case ENETDOWN: return WSAENETDOWN;
3822 case ENETUNREACH: return WSAENETUNREACH;
3823 case ENETRESET: return WSAENETRESET;
3824 case ECONNABORTED: return WSAECONNABORTED;
3825 case EPIPE:
3826 case ECONNRESET: return WSAECONNRESET;
3827 case ENOBUFS: return WSAENOBUFS;
3828 case EISCONN: return WSAEISCONN;
3829 case ENOTCONN: return WSAENOTCONN;
3830 case ESHUTDOWN: return WSAESHUTDOWN;
3831 case ETOOMANYREFS: return WSAETOOMANYREFS;
3832 case ETIMEDOUT: return WSAETIMEDOUT;
3833 case ECONNREFUSED: return WSAECONNREFUSED;
3834 case ELOOP: return WSAELOOP;
3835 case ENAMETOOLONG: return WSAENAMETOOLONG;
3836 case EHOSTDOWN: return WSAEHOSTDOWN;
3837 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3838 case ENOTEMPTY: return WSAENOTEMPTY;
3839 #ifdef EPROCLIM
3840 case EPROCLIM: return WSAEPROCLIM;
3841 #endif
3842 #ifdef EUSERS
3843 case EUSERS: return WSAEUSERS;
3844 #endif
3845 #ifdef EDQUOT
3846 case EDQUOT: return WSAEDQUOT;
3847 #endif
3848 #ifdef ESTALE
3849 case ESTALE: return WSAESTALE;
3850 #endif
3851 #ifdef EREMOTE
3852 case EREMOTE: return WSAEREMOTE;
3853 #endif
3855 /* just in case we ever get here and there are no problems */
3856 case 0: return 0;
3857 default:
3858 WARN("Unknown errno %d!\n", loc_errno);
3859 return WSAEOPNOTSUPP;
3863 UINT16 wsaHerrno(int loc_errno)
3866 WARN("h_errno %d.\n", loc_errno);
3868 switch(loc_errno)
3870 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3871 case TRY_AGAIN: return WSATRY_AGAIN;
3872 case NO_RECOVERY: return WSANO_RECOVERY;
3873 case NO_DATA: return WSANO_DATA;
3874 case ENOBUFS: return WSAENOBUFS;
3876 case 0: return 0;
3877 default:
3878 WARN("Unknown h_errno %d!\n", loc_errno);
3879 return WSAEOPNOTSUPP;
3884 /***********************************************************************
3885 * WSARecv (WS2_32.67)
3887 int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3888 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3889 LPWSAOVERLAPPED lpOverlapped,
3890 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3892 return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3893 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3896 /***********************************************************************
3897 * WSARecvFrom (WS2_32.69)
3899 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3900 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3901 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3902 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3905 int i, n, fd, err = WSAENOTSOCK, flags, ret;
3906 struct iovec* iovec;
3907 struct ws2_async *wsa;
3908 enum fd_type type;
3910 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3911 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3912 (lpFromlen ? *lpFromlen : -1L),
3913 lpOverlapped, lpCompletionRoutine);
3915 fd = _get_sock_fd_type( s, GENERIC_READ, &type, &flags );
3916 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
3918 if (fd == -1)
3920 err = WSAGetLastError ();
3921 goto error;
3924 iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3925 if ( !iovec )
3927 err = WSAEFAULT;
3928 goto err_close;
3931 for (i = 0; i < dwBufferCount; i++)
3933 iovec[i].iov_base = lpBuffers[i].buf;
3934 iovec[i].iov_len = lpBuffers[i].len;
3937 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3939 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
3940 lpFlags, lpFrom, lpFromlen,
3941 lpOverlapped, lpCompletionRoutine );
3943 if ( !wsa )
3945 err = WSAEFAULT;
3946 goto err_free;
3949 if ( ( ret = register_new_async ( &wsa->async )) )
3951 err = NtStatusToWSAError ( ret );
3953 if ( !lpOverlapped )
3954 HeapFree ( GetProcessHeap(), 0, wsa->async.iosb );
3955 HeapFree ( GetProcessHeap(), 0, wsa );
3956 goto err_free;
3959 /* Try immediate completion */
3960 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
3962 if ( WSAGetOverlappedResult ( s, lpOverlapped,
3963 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3964 return 0;
3966 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
3967 goto error;
3970 WSASetLastError ( WSA_IO_PENDING );
3971 return SOCKET_ERROR;
3974 if ( _is_blocking(s) )
3976 /* block here */
3977 /* FIXME: OOB and exceptfds? */
3978 do_block(fd, POLLIN);
3981 n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3982 if ( n == -1 )
3984 err = wsaErrno();
3985 goto err_free;
3988 TRACE(" -> %i bytes\n", n);
3989 *lpNumberOfBytesRecvd = n;
3991 HeapFree (GetProcessHeap(), 0, iovec);
3992 close(fd);
3993 _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3995 return 0;
3997 err_free:
3998 HeapFree (GetProcessHeap(), 0, iovec);
4000 err_close:
4001 close (fd);
4003 error:
4004 WARN(" -> ERROR %d\n", err);
4005 WSASetLastError ( err );
4006 return SOCKET_ERROR;
4009 /***********************************************************************
4010 * WSCInstallProvider (WS2_32.88)
4012 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
4013 LPCWSTR lpszProviderDllPath,
4014 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
4015 DWORD dwNumberOfEntries,
4016 LPINT lpErrno )
4018 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
4019 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
4020 dwNumberOfEntries, lpErrno);
4021 *lpErrno = 0;
4022 return 0;
4026 /***********************************************************************
4027 * WSCDeinstallProvider (WS2_32.83)
4029 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
4031 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
4032 *lpErrno = 0;
4033 return 0;
4037 /***********************************************************************
4038 * WSAAccept (WS2_32.26)
4040 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
4041 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
4044 int ret = 0, size = 0;
4045 WSABUF CallerId, CallerData, CalleeId, CalleeData;
4046 /* QOS SQOS, GQOS; */
4047 GROUP g;
4048 SOCKET cs;
4049 SOCKADDR src_addr, dst_addr;
4051 TRACE("Socket %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
4052 s, addr, addrlen, lpfnCondition, dwCallbackData);
4055 size = sizeof(src_addr);
4056 cs = WS_accept(s, &src_addr, &size);
4058 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
4060 CallerId.buf = (char *)&src_addr;
4061 CallerId.len = sizeof(src_addr);
4063 CallerData.buf = NULL;
4064 CallerData.len = (ULONG)NULL;
4066 WS_getsockname(cs, &dst_addr, &size);
4068 CalleeId.buf = (char *)&dst_addr;
4069 CalleeId.len = sizeof(dst_addr);
4072 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
4073 &CalleeId, &CalleeData, &g, dwCallbackData);
4075 switch (ret)
4077 case CF_ACCEPT:
4078 if (addr && addrlen)
4079 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
4080 return cs;
4081 case CF_DEFER:
4082 SERVER_START_REQ ( set_socket_deferred )
4084 req->handle = SOCKET2HANDLE (s);
4085 req->deferred = SOCKET2HANDLE (cs);
4086 if ( !wine_server_call_err ( req ) )
4088 SetLastError ( WSATRY_AGAIN );
4089 WS_closesocket ( cs );
4092 SERVER_END_REQ;
4093 return SOCKET_ERROR;
4094 case CF_REJECT:
4095 WS_closesocket(cs);
4096 SetLastError(WSAECONNREFUSED);
4097 return SOCKET_ERROR;
4098 default:
4099 FIXME("Unknown return type from Condition function\n");
4100 SetLastError(WSAENOTSOCK);
4101 return SOCKET_ERROR;
4105 /***********************************************************************
4106 * WSAEnumProtocolsA (WS2_32.37)
4108 int WINAPI WSAEnumProtocolsA(LPINT lpiProtocols, LPWSAPROTOCOL_INFOA lpProtocolBuffer, LPDWORD lpdwBufferLength)
4110 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4111 return 0;
4114 /***********************************************************************
4115 * WSAEnumProtocolsW (WS2_32.38)
4117 int WINAPI WSAEnumProtocolsW(LPINT lpiProtocols, LPWSAPROTOCOL_INFOW lpProtocolBuffer, LPDWORD lpdwBufferLength)
4119 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4120 return 0;
4123 /***********************************************************************
4124 * WSADuplicateSocketA (WS2_32.32)
4126 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
4128 HANDLE hProcess;
4130 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
4131 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
4132 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
4133 /* I don't know what the real Windoze does next, this is a hack */
4134 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
4135 * the target use the global duplicate, or we could copy a reference to us to the structure
4136 * and let the target duplicate it from us, but let's do it as simple as possible */
4137 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
4138 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
4139 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
4140 0, FALSE, DUPLICATE_SAME_ACCESS);
4141 CloseHandle(hProcess);
4142 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
4143 return 0;
4146 /***********************************************************************
4147 * WSAInstallServiceClassA (WS2_32.48)
4149 int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
4151 FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
4152 WSASetLastError(WSAEACCES);
4153 return SOCKET_ERROR;
4156 /***********************************************************************
4157 * WSAInstallServiceClassW (WS2_32.49)
4159 int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
4161 FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
4162 WSASetLastError(WSAEACCES);
4163 return SOCKET_ERROR;
4166 /***********************************************************************
4167 * WSARemoveServiceClass (WS2_32.70)
4169 int WINAPI WSARemoveServiceClass(LPGUID info)
4171 FIXME("Request to remove service %p\n",info);
4172 WSASetLastError(WSATYPE_NOT_FOUND);
4173 return SOCKET_ERROR;