Moved mode setting out of .spec file into Makefile.
[wine/gsoc_dplay.git] / dlls / winsock / socket.c
blob81e8d002324fefd436f68b4fcceca6b169864ce7
1 /*
2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
5 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * NOTE: If you make any changes to fix a particular app, make sure
22 * they don't break something else like Netscape or telnet and ftp
23 * clients and servers (www.winsite.com got a lot of those).
26 #include "config.h"
27 #include "wine/port.h"
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #ifdef HAVE_SYS_IPC_H
33 # include <sys/ipc.h>
34 #endif
35 #ifdef HAVE_SYS_IOCTL_H
36 # include <sys/ioctl.h>
37 #endif
38 #ifdef HAVE_SYS_FILIO_H
39 # include <sys/filio.h>
40 #endif
41 #ifdef HAVE_SYS_SOCKIO_H
42 # include <sys/sockio.h>
43 #endif
45 #if defined(__EMX__)
46 # include <sys/so_ioctl.h>
47 #endif
49 #ifdef HAVE_SYS_PARAM_H
50 # include <sys/param.h>
51 #endif
53 #ifdef HAVE_SYS_MSG_H
54 # include <sys/msg.h>
55 #endif
56 #ifdef HAVE_SYS_WAIT_H
57 # include <sys/wait.h>
58 #endif
59 #include <sys/uio.h>
60 #ifdef HAVE_SYS_SOCKET_H
61 #include <sys/socket.h>
62 #endif
63 #ifdef HAVE_NETINET_IN_H
64 # include <netinet/in.h>
65 #endif
66 #ifdef HAVE_NETINET_TCP_H
67 # include <netinet/tcp.h>
68 #endif
69 #ifdef HAVE_ARPA_INET_H
70 # include <arpa/inet.h>
71 #endif
72 #include <ctype.h>
73 #include <fcntl.h>
74 #include <errno.h>
75 #ifdef HAVE_SYS_ERRNO_H
76 #include <sys/errno.h>
77 #endif
78 #ifdef HAVE_NETDB_H
79 #include <netdb.h>
80 #endif
81 #ifdef HAVE_UNISTD_H
82 # include <unistd.h>
83 #endif
84 #include <stdlib.h>
85 #ifdef HAVE_ARPA_NAMESER_H
86 # include <arpa/nameser.h>
87 #endif
88 #ifdef HAVE_RESOLV_H
89 # include <resolv.h>
90 #endif
91 #ifdef HAVE_NET_IF_H
92 # include <net/if.h>
93 #endif
94 #ifdef HAVE_IPX_GNU
95 # include <netipx/ipx.h>
96 # define HAVE_IPX
97 #endif
98 #ifdef HAVE_IPX_LINUX
99 # include <asm/types.h>
100 # include <linux/ipx.h>
101 # define HAVE_IPX
102 #endif
104 #ifdef HAVE_SYS_TIME_H
105 # include <sys/time.h>
106 #endif
108 #include "wine/winbase16.h"
109 #include "wingdi.h"
110 #include "winuser.h"
111 #include "winerror.h"
112 #include "winsock2.h"
113 #include "ws2tcpip.h"
114 #include "wsipx.h"
115 #include "wine/winsock16.h"
116 #include "winnt.h"
117 #include "wine/server.h"
118 #include "wine/debug.h"
121 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
123 /* critical section to protect some non-rentrant net function */
124 extern CRITICAL_SECTION csWSgetXXXbyYYY;
126 #define DEBUG_SOCKADDR 0
127 #define dump_sockaddr(a) \
128 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
129 ((struct sockaddr_in *)a)->sin_family, \
130 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
131 ntohs(((struct sockaddr_in *)a)->sin_port))
133 /****************************************************************
134 * Async IO declarations
135 ****************************************************************/
136 #include "async.h"
138 static DWORD ws2_async_get_status (const struct async_private *ovp);
139 static DWORD ws2_async_get_count (const struct async_private *ovp);
140 static void ws2_async_set_status (struct async_private *ovp, const DWORD status);
141 static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
142 static void ws2_async_cleanup ( struct async_private *ovp );
144 static struct async_ops ws2_async_ops =
146 ws2_async_get_status,
147 ws2_async_set_status,
148 ws2_async_get_count,
149 ws2_async_call_completion,
150 ws2_async_cleanup
153 static struct async_ops ws2_nocomp_async_ops =
155 ws2_async_get_status,
156 ws2_async_set_status,
157 ws2_async_get_count,
158 NULL, /* call_completion */
159 ws2_async_cleanup
162 typedef struct ws2_async
164 async_private async;
165 LPWSAOVERLAPPED overlapped;
166 LPWSAOVERLAPPED user_overlapped;
167 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
168 struct iovec *iovec;
169 int n_iovecs;
170 struct WS_sockaddr *addr;
171 union {
172 int val; /* for send operations */
173 int *ptr; /* for recv operations */
174 } addrlen;
175 DWORD flags;
176 } ws2_async;
178 /****************************************************************/
180 /* ----------------------------------- internal data */
182 /* ws_... struct conversion flags */
184 #define WS_DUP_LINEAR 0x0001
185 #define WS_DUP_SEGPTR 0x0002 /* internal pointers are SEGPTRs */
186 /* by default, internal pointers are linear */
187 typedef struct /* WSAAsyncSelect() control struct */
189 HANDLE service, event, sock;
190 HWND hWnd;
191 UINT uMsg;
192 LONG lEvent;
193 } ws_select_info;
195 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
196 #define WS_MAX_UDP_DATAGRAM 1024
198 #define PROCFS_NETDEV_FILE "/proc/net/dev" /* Points to the file in the /proc fs
199 that lists the network devices.
200 Do we need an #ifdef LINUX for this? */
202 static void *he_buffer; /* typecast for Win16/32 ws_hostent */
203 static SEGPTR he_buffer_seg;
204 static void *se_buffer; /* typecast for Win16/32 ws_servent */
205 static SEGPTR se_buffer_seg;
206 static void *pe_buffer; /* typecast for Win16/32 ws_protoent */
207 static SEGPTR pe_buffer_seg;
208 static char* local_buffer;
209 static SEGPTR dbuffer_seg;
210 static INT num_startup; /* reference counter */
211 static FARPROC blocking_hook;
213 /* function prototypes */
214 static int WS_dup_he(struct hostent* p_he, int flag);
215 static int WS_dup_pe(struct protoent* p_pe, int flag);
216 static int WS_dup_se(struct servent* p_se, int flag);
218 typedef void WIN_hostent;
219 typedef void WIN_protoent;
220 typedef void WIN_servent;
222 int WSAIOCTL_GetInterfaceCount(void);
223 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
225 UINT16 wsaErrno(void);
226 UINT16 wsaHerrno(int errnr);
228 static HANDLE _WSHeap = 0;
230 #define WS_ALLOC(size) \
231 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
232 #define WS_FREE(ptr) \
233 HeapFree(_WSHeap, 0, (ptr) )
235 static INT _ws_sock_ops[] =
236 { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
237 WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
238 WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE,
239 #ifdef SO_RCVTIMEO
240 WS_SO_RCVTIMEO,
241 #endif
242 #ifdef SO_SNDTIMEO
243 WS_SO_SNDTIMEO,
244 #endif
245 0 };
246 static int _px_sock_ops[] =
247 { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
248 SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
249 #ifdef SO_RCVTIMEO
250 SO_RCVTIMEO,
251 #endif
252 #ifdef SO_SNDTIMEO
253 SO_SNDTIMEO,
254 #endif
257 static INT _ws_tcp_ops[] = {
258 #ifdef TCP_NODELAY
259 WS_TCP_NODELAY,
260 #endif
263 static int _px_tcp_ops[] = {
264 #ifdef TCP_NODELAY
265 TCP_NODELAY,
266 #endif
270 static DWORD opentype_tls_index = -1; /* TLS index for SO_OPENTYPE flag */
272 inline static DWORD NtStatusToWSAError ( const DWORD status )
274 /* We only need to cover the status codes set by server async request handling */
275 DWORD wserr;
276 switch ( status )
278 case STATUS_SUCCESS: wserr = 0; break;
279 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
280 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
281 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
282 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
283 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
284 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
285 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
286 default:
287 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
288 /* It is not a NT status code but a winsock error */
289 wserr = status;
290 else
292 wserr = RtlNtStatusToDosError( status );
293 FIXME ( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
296 return wserr;
299 /* set last error code from NT status without mapping WSA errors */
300 inline static unsigned int set_error( unsigned int err )
302 if (err)
304 err = NtStatusToWSAError ( err );
305 SetLastError( err );
307 return err;
310 static char* check_buffer(int size);
312 inline static int _get_sock_fd(SOCKET s)
314 int fd;
316 if (set_error( wine_server_handle_to_fd( s, GENERIC_READ, &fd, NULL, NULL ) )) return -1;
317 return fd;
320 inline static int _get_sock_fd_type( SOCKET s, DWORD access, enum fd_type *type, int *flags )
322 int fd;
323 if (set_error( wine_server_handle_to_fd( s, access, &fd, type, flags ) )) return -1;
324 if ( ( (access & GENERIC_READ) && (*flags & FD_FLAG_RECV_SHUTDOWN ) ) ||
325 ( (access & GENERIC_WRITE) && (*flags & FD_FLAG_SEND_SHUTDOWN ) ) )
327 close (fd);
328 WSASetLastError ( WSAESHUTDOWN );
329 return -1;
331 return fd;
334 static void _enable_event(SOCKET s, unsigned int event,
335 unsigned int sstate, unsigned int cstate)
337 SERVER_START_REQ( enable_socket_event )
339 req->handle = s;
340 req->mask = event;
341 req->sstate = sstate;
342 req->cstate = cstate;
343 wine_server_call( req );
345 SERVER_END_REQ;
348 static int _is_blocking(SOCKET s)
350 int ret;
351 SERVER_START_REQ( get_socket_event )
353 req->handle = s;
354 req->service = FALSE;
355 req->c_event = 0;
356 wine_server_call( req );
357 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
359 SERVER_END_REQ;
360 return ret;
363 static unsigned int _get_sock_mask(SOCKET s)
365 unsigned int ret;
366 SERVER_START_REQ( get_socket_event )
368 req->handle = s;
369 req->service = FALSE;
370 req->c_event = 0;
371 wine_server_call( req );
372 ret = reply->mask;
374 SERVER_END_REQ;
375 return ret;
378 static void _sync_sock_state(SOCKET s)
380 /* do a dummy wineserver request in order to let
381 the wineserver run through its select loop once */
382 (void)_is_blocking(s);
385 static int _get_sock_error(SOCKET s, unsigned int bit)
387 int events[FD_MAX_EVENTS];
389 SERVER_START_REQ( get_socket_event )
391 req->handle = s;
392 req->service = FALSE;
393 req->c_event = 0;
394 wine_server_set_reply( req, events, sizeof(events) );
395 wine_server_call( req );
397 SERVER_END_REQ;
398 return events[bit];
401 static void WINSOCK_DeleteIData(void)
403 /* delete scratch buffers */
405 UnMapLS( he_buffer_seg );
406 UnMapLS( se_buffer_seg );
407 UnMapLS( pe_buffer_seg );
408 UnMapLS( dbuffer_seg );
409 if (he_buffer) HeapFree( GetProcessHeap(), 0, he_buffer );
410 if (se_buffer) HeapFree( GetProcessHeap(), 0, se_buffer );
411 if (pe_buffer) HeapFree( GetProcessHeap(), 0, pe_buffer );
412 if (local_buffer) HeapFree( GetProcessHeap(), 0, local_buffer );
413 he_buffer = NULL;
414 se_buffer = NULL;
415 pe_buffer = NULL;
416 local_buffer = NULL;
417 he_buffer_seg = 0;
418 se_buffer_seg = 0;
419 pe_buffer_seg = 0;
420 dbuffer_seg = 0;
421 num_startup = 0;
424 /***********************************************************************
425 * WS_LibMain (WS2_32.init)
427 BOOL WINAPI WS_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
429 TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
430 switch (fdwReason) {
431 case DLL_PROCESS_ATTACH:
432 opentype_tls_index = TlsAlloc();
433 break;
434 case DLL_PROCESS_DETACH:
435 TlsFree( opentype_tls_index );
436 WINSOCK_DeleteIData();
437 break;
439 return TRUE;
442 /***********************************************************************
443 * convert_sockopt()
445 * Converts socket flags from Windows format.
446 * Return 1 if converted, 0 if not (error).
448 static int convert_sockopt(INT *level, INT *optname)
450 int i;
451 switch (*level)
453 case WS_SOL_SOCKET:
454 *level = SOL_SOCKET;
455 for(i=0; _ws_sock_ops[i]; i++)
456 if( _ws_sock_ops[i] == *optname ) break;
457 if( _ws_sock_ops[i] ) {
458 *optname = _px_sock_ops[i];
459 return 1;
461 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
462 break;
463 case WS_IPPROTO_TCP:
464 *level = IPPROTO_TCP;
465 for(i=0; _ws_tcp_ops[i]; i++)
466 if ( _ws_tcp_ops[i] == *optname ) break;
467 if( _ws_tcp_ops[i] ) {
468 *optname = _px_tcp_ops[i];
469 return 1;
471 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
472 break;
474 return 0;
477 /* ----------------------------------- Per-thread info (or per-process?) */
479 static int wsi_strtolo(const char* name, const char* opt)
481 /* Stuff a lowercase copy of the string into the local buffer */
483 int i = strlen(name) + 2;
484 char* p = check_buffer(i + ((opt)?strlen(opt):0));
486 if( p )
488 do *p++ = tolower(*name); while(*name++);
489 i = (p - local_buffer);
490 if( opt ) do *p++ = tolower(*opt); while(*opt++);
491 return i;
493 return 0;
496 static fd_set* fd_set_import( fd_set* fds, void* wsfds, int* highfd, int lfd[], BOOL b32 )
498 /* translate Winsock fd set into local fd set */
500 if( wsfds )
502 #define wsfds16 ((ws_fd_set16*)wsfds)
503 #define wsfds32 ((WS_fd_set*)wsfds)
504 int i, count;
506 FD_ZERO(fds);
507 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
509 for( i = 0; i < count; i++ )
511 int s = (b32) ? wsfds32->fd_array[i]
512 : wsfds16->fd_array[i];
513 int fd = _get_sock_fd(s);
514 if (fd != -1)
516 lfd[ i ] = fd;
517 if( fd > *highfd ) *highfd = fd;
518 FD_SET(fd, fds);
520 else lfd[ i ] = -1;
522 #undef wsfds32
523 #undef wsfds16
524 return fds;
526 return NULL;
529 inline static int sock_error_p(int s)
531 unsigned int optval, optlen;
533 optlen = sizeof(optval);
534 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
535 if (optval) WARN("\t[%i] error: %d\n", s, optval);
536 return optval != 0;
539 static int fd_set_export( fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
541 int num_err = 0;
543 /* translate local fd set into Winsock fd set, adding
544 * errors to exceptfds (only if app requested it) */
546 if( wsfds )
548 #define wsfds16 ((ws_fd_set16*)wsfds)
549 #define wsfds32 ((WS_fd_set*)wsfds)
550 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
552 for( i = 0, j = 0; i < count; i++ )
554 if( lfd[i] >= 0 )
556 int fd = lfd[i];
557 if( FD_ISSET(fd, fds) )
559 if ( exceptfds && sock_error_p(fd) )
561 FD_SET(fd, exceptfds);
562 num_err++;
564 else if( b32 )
565 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
566 else
567 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
569 close(fd);
570 lfd[i] = -1;
574 if( b32 ) wsfds32->fd_count = j;
575 else wsfds16->fd_count = j;
577 TRACE("\n");
578 #undef wsfds32
579 #undef wsfds16
581 return num_err;
584 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
586 if ( wsfds )
588 #define wsfds16 ((ws_fd_set16*)wsfds)
589 #define wsfds32 ((WS_fd_set*)wsfds)
590 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
592 for( i = 0; i < count; i++ )
593 if ( lfd[i] >= 0 )
594 close(lfd[i]);
596 TRACE("\n");
597 #undef wsfds32
598 #undef wsfds16
602 static int do_block( int fd, int mask )
604 fd_set fds[3];
605 int i, r;
607 FD_ZERO(&fds[0]);
608 FD_ZERO(&fds[1]);
609 FD_ZERO(&fds[2]);
610 for (i=0; i<3; i++)
611 if (mask & (1<<i))
612 FD_SET(fd, &fds[i]);
613 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
614 if (i <= 0) return -1;
615 r = 0;
616 for (i=0; i<3; i++)
617 if (FD_ISSET(fd, &fds[i]))
618 r |= 1<<i;
619 return r;
622 void* __ws_memalloc( int size )
624 return WS_ALLOC(size);
627 void __ws_memfree(void* ptr)
629 WS_FREE(ptr);
633 /* ----------------------------------- API -----
635 * Init / cleanup / error checking.
638 /***********************************************************************
639 * WSAStartup (WINSOCK.115)
641 * Create socket control struct, attach it to the global list and
642 * update a pointer in the task struct.
644 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA16 lpWSAData)
646 static const WSADATA16 data =
648 0x0101, 0x0101,
649 "WINE Sockets 1.1",
650 #ifdef linux
651 "Linux/i386",
652 #elif defined(__NetBSD__)
653 "NetBSD/i386",
654 #elif defined(sunos)
655 "SunOS",
656 #elif defined(__FreeBSD__)
657 "FreeBSD",
658 #elif defined(__OpenBSD__)
659 "OpenBSD/i386",
660 #else
661 "Unknown",
662 #endif
663 WS_MAX_SOCKETS_PER_PROCESS,
664 WS_MAX_UDP_DATAGRAM,
668 TRACE("verReq=%x\n", wVersionRequested);
670 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
671 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
673 if (!lpWSAData) return WSAEINVAL;
675 /* initialize socket heap */
677 if( !_WSHeap )
679 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
680 if( !_WSHeap )
682 ERR("Fatal: failed to create WinSock heap\n");
683 return 0;
686 if( _WSHeap == 0 ) return WSASYSNOTREADY;
688 num_startup++;
690 /* return winsock information */
692 memcpy(lpWSAData, &data, sizeof(data));
694 TRACE("succeeded\n");
695 return 0;
698 /***********************************************************************
699 * WSAStartup (WS2_32.115)
701 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
703 TRACE("verReq=%x\n", wVersionRequested);
705 if (LOBYTE(wVersionRequested) < 1)
706 return WSAVERNOTSUPPORTED;
708 if (!lpWSAData) return WSAEINVAL;
710 /* initialize socket heap */
712 if( !_WSHeap )
714 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
715 if( !_WSHeap )
717 ERR("Fatal: failed to create WinSock heap\n");
718 return 0;
721 if( _WSHeap == 0 ) return WSASYSNOTREADY;
723 num_startup++;
725 /* that's the whole of the negotiation for now */
726 lpWSAData->wVersion = wVersionRequested;
727 /* return winsock information */
728 lpWSAData->wHighVersion = 0x0202;
729 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
730 strcpy(lpWSAData->szSystemStatus, "Running" );
731 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
732 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
733 /* don't do anything with lpWSAData->lpVendorInfo */
734 /* (some apps don't allocate the space for this field) */
736 TRACE("succeeded\n");
737 return 0;
741 /***********************************************************************
742 * WSACleanup (WINSOCK.116)
743 * WSACleanup (WS2_32.116)
745 INT WINAPI WSACleanup(void)
747 if (num_startup)
749 if (--num_startup > 0) return 0;
750 WINSOCK_DeleteIData();
751 return 0;
753 SetLastError(WSANOTINITIALISED);
754 return SOCKET_ERROR;
758 /***********************************************************************
759 * WSAGetLastError (WINSOCK.111)
760 * WSAGetLastError (WS2_32.111)
762 INT WINAPI WSAGetLastError(void)
764 return GetLastError();
767 /***********************************************************************
768 * WSASetLastError (WS2_32.112)
770 void WINAPI WSASetLastError(INT iError) {
771 SetLastError(iError);
774 /***********************************************************************
775 * WSASetLastError (WINSOCK.112)
777 void WINAPI WSASetLastError16(INT16 iError)
779 WSASetLastError(iError);
782 static char* check_buffer(int size)
784 static int local_buflen;
786 if (local_buffer)
788 if (local_buflen >= size ) return local_buffer;
789 HeapFree( GetProcessHeap(), 0, local_buffer );
791 local_buffer = HeapAlloc( GetProcessHeap(), 0, (local_buflen = size) );
792 return local_buffer;
795 static struct ws_hostent* check_buffer_he(int size)
797 static int he_len;
798 if (he_buffer)
800 if (he_len >= size ) return he_buffer;
801 UnMapLS( he_buffer_seg );
802 HeapFree( GetProcessHeap(), 0, he_buffer );
804 he_buffer = HeapAlloc( GetProcessHeap(), 0, (he_len = size) );
805 he_buffer_seg = MapLS( he_buffer );
806 return he_buffer;
809 static void* check_buffer_se(int size)
811 static int se_len;
812 if (se_buffer)
814 if (se_len >= size ) return se_buffer;
815 UnMapLS( se_buffer_seg );
816 HeapFree( GetProcessHeap(), 0, se_buffer );
818 se_buffer = HeapAlloc( GetProcessHeap(), 0, (se_len = size) );
819 se_buffer_seg = MapLS( se_buffer );
820 return se_buffer;
823 static struct ws_protoent* check_buffer_pe(int size)
825 static int pe_len;
826 if (pe_buffer)
828 if (pe_len >= size ) return pe_buffer;
829 UnMapLS( pe_buffer_seg );
830 HeapFree( GetProcessHeap(), 0, pe_buffer );
832 pe_buffer = HeapAlloc( GetProcessHeap(), 0, (pe_len = size) );
833 pe_buffer_seg = MapLS( he_buffer );
834 return pe_buffer;
837 /* ----------------------------------- i/o APIs */
839 #ifdef HAVE_IPX
840 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
841 #else
842 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
843 #endif
846 /**********************************************************************/
848 /* Returns the converted address if successful, NULL if it was too small to
849 * start with. Note that the returned pointer may be the original pointer
850 * if no conversion is necessary.
852 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
854 switch (wsaddr->sa_family)
856 #ifdef HAVE_IPX
857 case WS_AF_IPX:
859 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
860 struct sockaddr_ipx* uipx;
862 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
863 return NULL;
865 *uaddrlen=sizeof(struct sockaddr_ipx);
866 uipx=malloc(*uaddrlen);
867 uipx->sipx_family=AF_IPX;
868 uipx->sipx_port=wsipx->sa_socket;
869 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
870 * in one go
872 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
873 uipx->sipx_type=IPX_FRAME_NONE;
874 uipx->sipx_zero=0;
875 return (const struct sockaddr*)uipx;
877 #endif
879 default:
880 if (wsaddrlen<sizeof(struct WS_sockaddr))
881 return NULL;
883 /* No conversion needed, just return the original address */
884 *uaddrlen=wsaddrlen;
885 return (const struct sockaddr*)wsaddr;
887 return NULL;
890 /* Allocates a Unix sockaddr structure to receive the data */
891 inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
893 if (wsaddr==NULL)
895 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
897 /* This is not strictly the right thing to do. Hope it works however */
898 *uaddrlen=0;
900 return NULL;
903 if (*wsaddrlen==0)
904 *uaddrlen=0;
905 else
906 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
908 return malloc(*uaddrlen);
911 /* Returns 0 if successful, -1 if the buffer is too small */
912 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
914 int res;
916 switch(uaddr->sa_family)
918 #ifdef HAVE_IPX
919 case AF_IPX:
921 struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
922 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
924 res=-1;
925 switch (*wsaddrlen) /* how much can we copy? */
927 default:
928 res=0; /* enough */
929 *wsaddrlen=uaddrlen;
930 wsipx->sa_socket=uipx->sipx_port;
931 /* fall through */
932 case 13:
933 case 12:
934 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
935 /* fall through */
936 case 11:
937 case 10:
938 case 9:
939 case 8:
940 case 7:
941 case 6:
942 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
943 /* fall through */
944 case 5:
945 case 4:
946 case 3:
947 case 2:
948 wsipx->sa_family=WS_AF_IPX;
949 /* fall through */
950 case 1:
951 case 0:
952 /* way too small */
953 break;
956 break;
957 #endif
959 default:
960 /* No conversion needed */
961 memcpy(wsaddr,uaddr,*wsaddrlen);
962 if (*wsaddrlen<uaddrlen) {
963 res=-1;
964 } else {
965 *wsaddrlen=uaddrlen;
966 res=0;
969 return res;
972 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
973 * ws_sockaddr_alloc
975 inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
977 if (uaddr!=NULL && uaddr!=(const struct sockaddr*)wsaddr)
978 free((void*)uaddr);
981 /**************************************************************************
982 * Functions for handling overlapped I/O
983 **************************************************************************/
985 static DWORD ws2_async_get_status (const struct async_private *ovp)
987 return ((ws2_async*) ovp)->overlapped->Internal;
990 static VOID ws2_async_set_status (struct async_private *ovp, const DWORD status)
992 ((ws2_async*) ovp)->overlapped->Internal = status;
995 static DWORD ws2_async_get_count (const struct async_private *ovp)
997 return ((ws2_async*) ovp)->overlapped->InternalHigh;
1000 static void ws2_async_cleanup ( struct async_private *ap )
1002 struct ws2_async *as = (struct ws2_async*) ap;
1004 TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->overlapped );
1005 if ( !as->user_overlapped )
1007 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
1008 WSACloseEvent ( as->overlapped->hEvent );
1009 HeapFree ( GetProcessHeap(), 0, as->overlapped );
1012 if ( as->iovec )
1013 HeapFree ( GetProcessHeap(), 0, as->iovec );
1015 HeapFree ( GetProcessHeap(), 0, as );
1018 static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
1020 ws2_async* as = (ws2_async*) data;
1022 TRACE ("data: %p\n", as);
1024 as->completion_func ( NtStatusToWSAError (as->overlapped->Internal),
1025 as->overlapped->InternalHigh,
1026 as->user_overlapped,
1027 as->flags );
1028 ws2_async_cleanup ( &as->async );
1031 /***********************************************************************
1032 * WS2_make_async (INTERNAL)
1035 static void WS2_async_recv (async_private *as);
1036 static void WS2_async_send (async_private *as);
1038 inline static struct ws2_async*
1039 WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferCount,
1040 LPDWORD lpFlags, struct WS_sockaddr *addr,
1041 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
1042 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1044 struct ws2_async *wsa = HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async ) );
1046 TRACE ( "wsa %p\n", wsa );
1048 if (!wsa)
1049 return NULL;
1051 wsa->async.ops = ( lpCompletionRoutine ? &ws2_async_ops : &ws2_nocomp_async_ops );
1052 wsa->async.handle = (HANDLE) s;
1053 wsa->async.fd = fd;
1054 wsa->async.type = type;
1055 switch (type)
1057 case ASYNC_TYPE_READ:
1058 wsa->flags = *lpFlags;
1059 wsa->async.func = WS2_async_recv;
1060 wsa->addrlen.ptr = addrlen;
1061 break;
1062 case ASYNC_TYPE_WRITE:
1063 wsa->flags = 0;
1064 wsa->async.func = WS2_async_send;
1065 wsa->addrlen.val = *addrlen;
1066 break;
1067 default:
1068 ERR ("Invalid async type: %d\n", type);
1070 wsa->user_overlapped = lpOverlapped;
1071 wsa->completion_func = lpCompletionRoutine;
1072 wsa->iovec = iovec;
1073 wsa->n_iovecs = dwBufferCount;
1074 wsa->addr = addr;
1076 if ( lpOverlapped )
1078 wsa->overlapped = lpOverlapped;
1079 wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
1081 else
1083 wsa->overlapped = HeapAlloc ( GetProcessHeap(), 0,
1084 sizeof (WSAOVERLAPPED) );
1085 if ( !wsa->overlapped )
1086 goto error;
1087 wsa->async.event = wsa->overlapped->hEvent = INVALID_HANDLE_VALUE;
1090 wsa->overlapped->InternalHigh = 0;
1091 TRACE ( "wsa %p, ops %p, h %d, ev %d, fd %d, func %p, ov %p, uov %p, cfunc %p\n",
1092 wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
1093 wsa->overlapped, wsa->user_overlapped, wsa->completion_func );
1095 return wsa;
1097 error:
1098 TRACE ("Error\n");
1099 HeapFree ( GetProcessHeap(), 0, wsa );
1100 return NULL;
1103 /***********************************************************************
1104 * WS2_recv (INTERNAL)
1106 * Work horse for both synchronous and asynchronous recv() operations.
1108 static int WS2_recv ( int fd, struct iovec* iov, int count,
1109 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1110 LPDWORD lpFlags )
1112 struct msghdr hdr;
1113 int n;
1114 TRACE ( "fd %d, iovec %p, count %d addr %p, len %p, flags %lx\n",
1115 fd, iov, count, lpFrom, lpFromlen, *lpFlags);
1117 hdr.msg_name = NULL;
1119 if ( lpFrom )
1121 #if DEBUG_SOCKADDR
1122 dump_sockaddr (lpFrom);
1123 #endif
1125 hdr.msg_namelen = *lpFromlen;
1126 hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
1127 if ( !hdr.msg_name )
1129 WSASetLastError ( WSAEFAULT );
1130 n = -1;
1131 goto out;
1134 else
1135 hdr.msg_namelen = 0;
1137 hdr.msg_iov = iov;
1138 hdr.msg_iovlen = count;
1139 #ifdef HAVE_MSGHDR_ACCRIGHTS
1140 hdr.msg_accrights = NULL;
1141 hdr.msg_accrightslen = 0;
1142 #else
1143 hdr.msg_control = NULL;
1144 hdr.msg_controllen = 0;
1145 hdr.msg_flags = 0;
1146 #endif
1148 if ( (n = recvmsg (fd, &hdr, *lpFlags)) == -1 )
1150 TRACE ( "recvmsg error %d\n", errno);
1151 goto out;
1154 if ( lpFrom &&
1155 ws_sockaddr_u2ws ( hdr.msg_name, hdr.msg_namelen,
1156 lpFrom, lpFromlen ) != 0 )
1158 /* The from buffer was too small, but we read the data
1159 * anyway. Is that really bad?
1161 WSASetLastError ( WSAEFAULT );
1162 WARN ( "Address buffer too small\n" );
1165 out:
1167 ws_sockaddr_free ( hdr.msg_name, lpFrom );
1168 TRACE ("-> %d\n", n);
1169 return n;
1172 /***********************************************************************
1173 * WS2_async_recv (INTERNAL)
1175 * Handler for overlapped recv() operations.
1177 static void WS2_async_recv ( async_private *as )
1179 ws2_async* wsa = (ws2_async*) as;
1180 int result, err;
1182 TRACE ( "async %p\n", wsa );
1184 if ( wsa->overlapped->Internal != STATUS_PENDING )
1186 TRACE ( "status: %ld\n", wsa->overlapped->Internal );
1187 return;
1190 result = WS2_recv ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1191 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1193 if (result >= 0)
1195 wsa->overlapped->Internal = STATUS_SUCCESS;
1196 wsa->overlapped->InternalHigh = result;
1197 TRACE ( "received %d bytes\n", result );
1198 _enable_event ( (SOCKET) wsa->async.handle, FD_READ, 0, 0 );
1199 return;
1202 err = wsaErrno ();
1203 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1205 wsa->overlapped->Internal = STATUS_PENDING;
1206 _enable_event ( (SOCKET) wsa->async.handle, FD_READ, 0, 0 );
1207 TRACE ( "still pending\n" );
1209 else
1211 wsa->overlapped->Internal = err;
1212 TRACE ( "Error: %x\n", err );
1216 /***********************************************************************
1217 * WS2_send (INTERNAL)
1219 * Work horse for both synchronous and asynchronous send() operations.
1221 static int WS2_send ( int fd, struct iovec* iov, int count,
1222 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1224 struct msghdr hdr;
1225 int n = -1;
1226 TRACE ( "fd %d, iovec %p, count %d addr %p, len %d, flags %lx\n",
1227 fd, iov, count, to, tolen, dwFlags);
1229 hdr.msg_name = NULL;
1231 if ( to )
1233 #if DEBUG_SOCKADDR
1234 dump_sockaddr (to);
1235 #endif
1236 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
1237 if ( !hdr.msg_name )
1239 WSASetLastError ( WSAEFAULT );
1240 goto out;
1243 else
1244 hdr.msg_namelen = 0;
1246 hdr.msg_iov = iov;
1247 hdr.msg_iovlen = count;
1248 #ifdef HAVE_MSGHDR_ACCRIGHTS
1249 hdr.msg_accrights = NULL;
1250 hdr.msg_accrightslen = 0;
1251 #else
1252 hdr.msg_control = NULL;
1253 hdr.msg_controllen = 0;
1254 hdr.msg_flags = 0;
1255 #endif
1257 n = sendmsg (fd, &hdr, dwFlags);
1259 out:
1260 ws_sockaddr_free ( hdr.msg_name, to );
1261 return n;
1264 /***********************************************************************
1265 * WS2_async_send (INTERNAL)
1267 * Handler for overlapped send() operations.
1269 static void WS2_async_send ( async_private *as )
1271 ws2_async* wsa = (ws2_async*) as;
1272 int result, err;
1274 TRACE ( "async %p\n", wsa );
1276 if ( wsa->overlapped->Internal != STATUS_PENDING )
1278 TRACE ( "status: %ld\n", wsa->overlapped->Internal );
1279 return;
1282 result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1283 wsa->addr, wsa->addrlen.val, wsa->flags );
1285 if (result >= 0)
1287 wsa->overlapped->Internal = STATUS_SUCCESS;
1288 wsa->overlapped->InternalHigh = result;
1289 TRACE ( "sent %d bytes\n", result );
1290 _enable_event ( (SOCKET) wsa->async.handle, FD_WRITE, 0, 0 );
1291 return;
1294 err = wsaErrno ();
1295 if ( err == WSAEINTR )
1297 wsa->overlapped->Internal = STATUS_PENDING;
1298 _enable_event ( (SOCKET) wsa->async.handle, FD_WRITE, 0, 0 );
1299 TRACE ( "still pending\n" );
1301 else
1303 /* We set the status to a winsock error code and check for that
1304 later in NtStatusToWSAError () */
1305 wsa->overlapped->Internal = err;
1306 TRACE ( "Error: %x\n", err );
1310 /***********************************************************************
1311 * WS2_async_shutdown (INTERNAL)
1313 * Handler for shutdown() operations on overlapped sockets.
1315 static void WS2_async_shutdown ( async_private *as )
1317 ws2_async* wsa = (ws2_async*) as;
1318 int err = 1;
1320 TRACE ( "async %p %d\n", wsa, wsa->async.type );
1321 switch ( wsa->async.type )
1323 case ASYNC_TYPE_READ:
1324 err = shutdown ( wsa->async.fd, 0 );
1325 break;
1326 case ASYNC_TYPE_WRITE:
1327 err = shutdown ( wsa->async.fd, 1 );
1328 break;
1329 default:
1330 ERR ("invalid type: %d\n", wsa->async.type );
1333 if ( err )
1334 wsa->overlapped->Internal = wsaErrno ();
1335 else
1336 wsa->overlapped->Internal = STATUS_SUCCESS;
1339 /***********************************************************************
1340 * WS2_register_async_shutdown (INTERNAL)
1342 * Helper function for WS_shutdown() on overlapped sockets.
1344 static int WS2_register_async_shutdown ( SOCKET s, int fd, int type )
1346 struct ws2_async *wsa;
1347 int ret, err = WSAEFAULT;
1348 DWORD dwflags = 0;
1349 int len = 0;
1350 LPWSAOVERLAPPED ovl = HeapAlloc (GetProcessHeap(), 0, sizeof ( WSAOVERLAPPED ));
1352 TRACE ("s %d fd %d type %d\n", s, fd, type);
1353 if (!ovl)
1354 goto out;
1356 ovl->hEvent = WSACreateEvent ();
1357 if ( ovl->hEvent == WSA_INVALID_EVENT )
1358 goto out_free;
1360 wsa = WS2_make_async ( s, fd, type, NULL, 0,
1361 &dwflags, NULL, &len, ovl, NULL );
1362 if ( !wsa )
1363 goto out_close;
1365 /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
1366 wsa->user_overlapped = NULL;
1367 wsa->async.func = WS2_async_shutdown;
1368 if ( (ret = register_new_async ( &wsa->async )) )
1370 err = NtStatusToWSAError ( ret );
1371 ws2_async_cleanup ( &wsa->async );
1372 goto out;
1374 /* Try immediate completion */
1375 if ( WSAGetOverlappedResult ( (HANDLE) s, ovl, NULL, FALSE, NULL ) )
1376 return 0;
1377 if ( (err = WSAGetLastError ()) == WSA_IO_INCOMPLETE )
1378 return 0;
1379 return WSAEINVAL;
1381 out_close:
1382 WSACloseEvent ( ovl->hEvent );
1383 out_free:
1384 HeapFree ( GetProcessHeap(), 0, ovl );
1385 out:
1386 return err;
1389 /***********************************************************************
1390 * accept (WS2_32.1)
1392 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1393 int *addrlen32)
1395 int fd = _get_sock_fd(s);
1397 TRACE("socket %04x\n", (UINT16)s );
1398 if (fd != -1)
1400 SOCKET as;
1401 if (_is_blocking(s))
1403 /* block here */
1404 do_block(fd, 5);
1405 _sync_sock_state(s); /* let wineserver notice connection */
1406 /* retrieve any error codes from it */
1407 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1408 /* FIXME: care about the error? */
1410 close(fd);
1411 SERVER_START_REQ( accept_socket )
1413 req->lhandle = s;
1414 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1415 req->inherit = TRUE;
1416 set_error( wine_server_call( req ) );
1417 as = (SOCKET)reply->handle;
1419 SERVER_END_REQ;
1420 if (as)
1422 if (addr)
1423 WS_getpeername(as, addr, addrlen32);
1424 return as;
1427 else
1429 SetLastError(WSAENOTSOCK);
1431 return INVALID_SOCKET;
1434 /***********************************************************************
1435 * accept (WINSOCK.1)
1437 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct WS_sockaddr* addr,
1438 INT16* addrlen16 )
1440 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
1441 SOCKET retSocket = WS_accept( s, addr, &addrlen32 );
1442 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
1443 return (SOCKET16)retSocket;
1446 /***********************************************************************
1447 * bind (WS2_32.2)
1449 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1451 int fd = _get_sock_fd(s);
1452 int res;
1454 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
1455 #if DEBUG_SOCKADDR
1456 dump_sockaddr(name);
1457 #endif
1459 res=SOCKET_ERROR;
1460 if (fd != -1)
1462 if (!name || !SUPPORTED_PF(name->sa_family))
1464 SetLastError(WSAEAFNOSUPPORT);
1466 else
1468 const struct sockaddr* uaddr;
1469 int uaddrlen;
1471 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1472 if (uaddr == NULL)
1474 SetLastError(WSAEFAULT);
1476 else
1478 if (bind(fd, uaddr, uaddrlen) < 0)
1480 int loc_errno = errno;
1481 WARN("\tfailure - errno = %i\n", errno);
1482 errno = loc_errno;
1483 switch (errno)
1485 case EBADF:
1486 SetLastError(WSAENOTSOCK);
1487 break;
1488 case EADDRNOTAVAIL:
1489 SetLastError(WSAEINVAL);
1490 break;
1491 default:
1492 SetLastError(wsaErrno());
1493 break;
1496 else
1498 res=0; /* success */
1500 ws_sockaddr_free(uaddr,name);
1503 close(fd);
1505 else
1507 SetLastError(WSAENOTSOCK);
1509 return res;
1512 /***********************************************************************
1513 * bind (WINSOCK.2)
1515 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1517 return (INT16)WS_bind( s, name, namelen );
1520 /***********************************************************************
1521 * closesocket (WS2_32.3)
1523 int WINAPI WS_closesocket(SOCKET s)
1525 TRACE("socket %08x\n", s);
1526 if (CloseHandle(s)) return 0;
1527 return SOCKET_ERROR;
1530 /***********************************************************************
1531 * closesocket (WINSOCK.3)
1533 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
1535 return (INT16)WS_closesocket(s);
1538 /***********************************************************************
1539 * connect (WS2_32.4)
1541 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1543 int fd = _get_sock_fd(s);
1545 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
1546 #if DEBUG_SOCKADDR
1547 dump_sockaddr(name);
1548 #endif
1550 if (fd != -1)
1552 const struct sockaddr* uaddr;
1553 int uaddrlen;
1555 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1556 if (uaddr == NULL)
1558 SetLastError(WSAEFAULT);
1560 else
1562 int rc;
1564 rc=connect(fd, uaddr, uaddrlen);
1565 ws_sockaddr_free(uaddr,name);
1566 if (rc == 0)
1567 goto connect_success;
1570 if (errno == EINPROGRESS)
1572 /* tell wineserver that a connection is in progress */
1573 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1574 FD_CONNECT|FD_READ|FD_WRITE,
1575 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1576 if (_is_blocking(s))
1578 int result;
1579 /* block here */
1580 do_block(fd, 7);
1581 _sync_sock_state(s); /* let wineserver notice connection */
1582 /* retrieve any error codes from it */
1583 result = _get_sock_error(s, FD_CONNECT_BIT);
1584 if (result)
1585 SetLastError(result);
1586 else
1588 goto connect_success;
1591 else
1593 SetLastError(WSAEWOULDBLOCK);
1596 else
1598 SetLastError(wsaErrno());
1600 close(fd);
1602 else
1604 SetLastError(WSAENOTSOCK);
1606 return SOCKET_ERROR;
1608 connect_success:
1609 close(fd);
1610 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1611 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1612 FD_CONNECT|FD_WINE_LISTENING);
1613 return 0;
1616 /***********************************************************************
1617 * connect (WINSOCK.4)
1619 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1621 return (INT16)WS_connect( s, name, namelen );
1624 /***********************************************************************
1625 * WSAConnect (WS2_32.30)
1627 int WINAPI WSAConnect ( SOCKET s, const struct WS_sockaddr* name, int namelen,
1628 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1629 LPQOS lpSQOS, LPQOS lpGQOS )
1631 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1632 FIXME ("unsupported parameters!\n");
1633 return WS_connect ( s, name, namelen );
1637 /***********************************************************************
1638 * getpeername (WS2_32.5)
1640 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1642 int fd;
1643 int res;
1645 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1647 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1648 if( (name == NULL) || (namelen == NULL) )
1650 SetLastError( WSAEFAULT );
1651 return SOCKET_ERROR;
1654 fd = _get_sock_fd(s);
1655 res = SOCKET_ERROR;
1657 if (fd != -1)
1659 struct sockaddr* uaddr;
1660 int uaddrlen;
1662 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1663 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1665 SetLastError(wsaErrno());
1667 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1669 /* The buffer was too small */
1670 SetLastError(WSAEFAULT);
1672 else
1674 res=0;
1676 ws_sockaddr_free(uaddr,name);
1677 close(fd);
1679 else
1681 SetLastError(WSAENOTSOCK);
1683 return res;
1686 /***********************************************************************
1687 * getpeername (WINSOCK.5)
1689 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct WS_sockaddr *name,
1690 INT16 *namelen16)
1692 INT namelen32 = *namelen16;
1693 INT retVal = WS_getpeername( s, name, &namelen32 );
1695 #if DEBUG_SOCKADDR
1696 dump_sockaddr(name);
1697 #endif
1699 *namelen16 = namelen32;
1700 return (INT16)retVal;
1703 /***********************************************************************
1704 * getsockname (WS2_32.6)
1706 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1708 int fd;
1709 int res;
1711 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1713 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1714 if( (name == NULL) || (namelen == NULL) )
1716 SetLastError( WSAEFAULT );
1717 return SOCKET_ERROR;
1720 fd = _get_sock_fd(s);
1721 res = SOCKET_ERROR;
1723 if (fd != -1)
1725 struct sockaddr* uaddr;
1726 int uaddrlen;
1728 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1729 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1731 SetLastError(wsaErrno());
1733 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1735 /* The buffer was too small */
1736 SetLastError(WSAEFAULT);
1738 else
1740 res=0;
1742 close(fd);
1744 else
1746 SetLastError(WSAENOTSOCK);
1748 return res;
1751 /***********************************************************************
1752 * getsockname (WINSOCK.6)
1754 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct WS_sockaddr *name,
1755 INT16 *namelen16)
1757 INT retVal;
1759 if( namelen16 )
1761 INT namelen32 = *namelen16;
1762 retVal = WS_getsockname( s, name, &namelen32 );
1763 *namelen16 = namelen32;
1765 #if DEBUG_SOCKADDR
1766 dump_sockaddr(name);
1767 #endif
1770 else retVal = SOCKET_ERROR;
1771 return (INT16)retVal;
1775 /***********************************************************************
1776 * getsockopt (WS2_32.7)
1778 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1779 INT optname, char *optval, INT *optlen)
1781 int fd;
1783 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1784 (int) optname, (int) optval, (int) *optlen);
1785 /* SO_OPENTYPE does not require a valid socket handle. */
1786 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1788 if (!optlen || *optlen < sizeof(int) || !optval)
1790 SetLastError(WSAEFAULT);
1791 return SOCKET_ERROR;
1793 *(int *)optval = (int)TlsGetValue( opentype_tls_index );
1794 *optlen = sizeof(int);
1795 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1796 return 0;
1799 fd = _get_sock_fd(s);
1800 if (fd != -1)
1802 if (!convert_sockopt(&level, &optname)) {
1803 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1804 } else {
1805 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1807 close(fd);
1808 return 0;
1810 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1812 close(fd);
1814 return SOCKET_ERROR;
1818 /***********************************************************************
1819 * getsockopt (WINSOCK.7)
1821 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1822 INT16 optname, char *optval, INT16 *optlen)
1824 INT optlen32;
1825 INT *p = &optlen32;
1826 INT retVal;
1827 if( optlen ) optlen32 = *optlen; else p = NULL;
1828 retVal = WS_getsockopt( s, (UINT16)level, optname, optval, p );
1829 if( optlen ) *optlen = optlen32;
1830 return (INT16)retVal;
1834 /***********************************************************************
1835 * htonl (WINSOCK.8)
1836 * htonl (WS2_32.8)
1838 u_long WINAPI WS_htonl(u_long hostlong)
1840 return htonl(hostlong);
1844 /***********************************************************************
1845 * htons (WINSOCK.9)
1846 * htons (WS2_32.9)
1848 u_short WINAPI WS_htons(u_short hostshort)
1850 return htons(hostshort);
1854 /***********************************************************************
1855 * inet_addr (WINSOCK.10)
1856 * inet_addr (WS2_32.11)
1858 u_long WINAPI WS_inet_addr(const char *cp)
1860 return inet_addr(cp);
1864 /***********************************************************************
1865 * ntohl (WINSOCK.14)
1866 * ntohl (WS2_32.14)
1868 u_long WINAPI WS_ntohl(u_long netlong)
1870 return ntohl(netlong);
1874 /***********************************************************************
1875 * ntohs (WINSOCK.15)
1876 * ntohs (WS2_32.15)
1878 u_short WINAPI WS_ntohs(u_short netshort)
1880 return ntohs(netshort);
1884 /***********************************************************************
1885 * inet_ntoa (WS2_32.12)
1887 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1889 /* use "buffer for dummies" here because some applications have
1890 * propensity to decode addresses in ws_hostent structure without
1891 * saving them first...
1893 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1895 char* s = inet_ntoa(*((struct in_addr*)&in));
1896 if( s )
1898 strcpy(dbuffer, s);
1899 return dbuffer;
1901 SetLastError(wsaErrno());
1902 return NULL;
1905 /***********************************************************************
1906 * inet_ntoa (WINSOCK.11)
1908 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1910 char* retVal;
1911 if (!(retVal = WS_inet_ntoa(*((struct WS_in_addr*)&in)))) return 0;
1912 if (!dbuffer_seg) dbuffer_seg = MapLS( retVal );
1913 return dbuffer_seg;
1917 /**********************************************************************
1918 * WSAIoctl (WS2_32.50)
1921 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1923 INT WINAPI WSAIoctl (SOCKET s,
1924 DWORD dwIoControlCode,
1925 LPVOID lpvInBuffer,
1926 DWORD cbInBuffer,
1927 LPVOID lpbOutBuffer,
1928 DWORD cbOutBuffer,
1929 LPDWORD lpcbBytesReturned,
1930 LPWSAOVERLAPPED lpOverlapped,
1931 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1933 int fd = _get_sock_fd(s);
1935 if (fd != -1)
1937 switch( dwIoControlCode )
1939 case SIO_GET_INTERFACE_LIST:
1941 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1942 int i, numInt;
1943 struct ifreq ifInfo;
1944 char ifName[512];
1947 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1949 numInt = WSAIOCTL_GetInterfaceCount();
1950 if (numInt < 0)
1952 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1953 close(fd);
1954 WSASetLastError(WSAEINVAL);
1955 return (SOCKET_ERROR);
1958 for (i=0; i<numInt; i++)
1960 if (!WSAIOCTL_GetInterfaceName(i, ifName))
1962 ERR ("Error parsing /proc filesystem!\n");
1963 close(fd);
1964 WSASetLastError(WSAEINVAL);
1965 return (SOCKET_ERROR);
1968 ifInfo.ifr_addr.sa_family = AF_INET;
1970 /* IP Address */
1971 strcpy (ifInfo.ifr_name, ifName);
1972 if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
1974 ERR ("Error obtaining IP address\n");
1975 close(fd);
1976 WSASetLastError(WSAEINVAL);
1977 return (SOCKET_ERROR);
1979 else
1981 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_addr;
1983 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1984 intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1985 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
1988 /* Broadcast Address */
1989 strcpy (ifInfo.ifr_name, ifName);
1990 if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1992 ERR ("Error obtaining Broadcast IP address\n");
1993 close(fd);
1994 WSASetLastError(WSAEINVAL);
1995 return (SOCKET_ERROR);
1997 else
1999 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_broadaddr;
2001 intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
2002 intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
2003 intArray->iiBroadcastAddress.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
2006 /* Subnet Mask */
2007 strcpy (ifInfo.ifr_name, ifName);
2008 if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
2010 ERR ("Error obtaining Subnet IP address\n");
2011 close(fd);
2012 WSASetLastError(WSAEINVAL);
2013 return (SOCKET_ERROR);
2015 else
2017 /* Trying to avoid some compile problems across platforms.
2018 (Linux, FreeBSD, Solaris...) */
2019 #ifndef ifr_netmask
2020 #ifndef ifr_addr
2021 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2022 intArray->iiNetmask.AddressIn.sin_port = 0;
2023 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = 0;
2024 ERR ("Unable to determine Netmask on your platform!\n");
2025 #else
2026 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_addr;
2028 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2029 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
2030 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
2031 #endif
2032 #else
2033 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_netmask;
2035 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2036 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
2037 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
2038 #endif
2041 /* Socket Status Flags */
2042 strcpy(ifInfo.ifr_name, ifName);
2043 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
2045 ERR ("Error obtaining status flags for socket!\n");
2046 close(fd);
2047 WSASetLastError(WSAEINVAL);
2048 return (SOCKET_ERROR);
2050 else
2052 /* FIXME - Is this the right flag to use? */
2053 intArray->iiFlags = ifInfo.ifr_flags;
2055 intArray++; /* Prepare for another interface */
2058 /* Calculate the size of the array being returned */
2059 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2060 break;
2063 default:
2065 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2066 close(fd);
2067 WSASetLastError(WSAEOPNOTSUPP);
2068 return (SOCKET_ERROR);
2072 /* Function executed with no errors */
2073 close(fd);
2074 return (0);
2076 else
2078 WSASetLastError(WSAENOTSOCK);
2079 return (SOCKET_ERROR);
2085 Helper function for WSAIoctl - Get count of the number of interfaces
2086 by parsing /proc filesystem.
2088 int WSAIOCTL_GetInterfaceCount(void)
2090 FILE *procfs;
2091 char buf[512]; /* Size doesn't matter, something big */
2092 int intcnt=0;
2095 /* Open /proc filesystem file for network devices */
2096 procfs = fopen(PROCFS_NETDEV_FILE, "r");
2097 if (!procfs)
2099 /* If we can't open the file, return an error */
2100 return (-1);
2103 /* Omit first two lines, they are only headers */
2104 fgets(buf, sizeof buf, procfs);
2105 fgets(buf, sizeof buf, procfs);
2107 while (fgets(buf, sizeof buf, procfs))
2109 /* Each line in the file represents a network interface */
2110 intcnt++;
2113 fclose(procfs);
2114 return(intcnt);
2119 Helper function for WSAIoctl - Get name of device from interface number
2120 by parsing /proc filesystem.
2122 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
2124 FILE *procfs;
2125 char buf[512]; /* Size doesn't matter, something big */
2126 int i;
2128 /* Open /proc filesystem file for network devices */
2129 procfs = fopen(PROCFS_NETDEV_FILE, "r");
2130 if (!procfs)
2132 /* If we can't open the file, return an error */
2133 return (-1);
2136 /* Omit first two lines, they are only headers */
2137 fgets(buf, sizeof(buf), procfs);
2138 fgets(buf, sizeof(buf), procfs);
2140 for (i=0; i<intNumber; i++)
2142 /* Skip the lines that don't interest us. */
2143 fgets(buf, sizeof(buf), procfs);
2145 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
2148 /* Parse out the line, grabbing only the name of the device
2149 to the intName variable
2151 The Line comes in like this: (we only care about the device name)
2152 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
2154 i=0;
2155 while (isspace(buf[i])) /* Skip initial space(s) */
2157 i++;
2160 while (buf[i])
2162 if (isspace(buf[i]))
2164 break;
2167 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
2169 /* This interface could be an alias... */
2170 int hold = i;
2171 char *dotname = intName;
2172 *intName++ = buf[i++];
2174 while (isdigit(buf[i]))
2176 *intName++ = buf[i++];
2179 if (buf[i] != ':')
2181 /* ... It wasn't, so back up */
2182 i = hold;
2183 intName = dotname;
2186 if (buf[i] == '\0')
2188 fclose(procfs);
2189 return(FALSE);
2192 i++;
2193 break;
2196 *intName++ = buf[i++];
2198 *intName++ = '\0';
2200 fclose(procfs);
2201 return(TRUE);
2205 /***********************************************************************
2206 * ioctlsocket (WS2_32.10)
2208 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2210 int fd = _get_sock_fd(s);
2212 TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
2213 if (fd != -1)
2215 long newcmd = cmd;
2217 switch( cmd )
2219 case WS_FIONREAD:
2220 newcmd=FIONREAD;
2221 break;
2223 case WS_FIONBIO:
2224 newcmd=FIONBIO;
2225 if( _get_sock_mask(s) )
2227 /* AsyncSelect()'ed sockets are always nonblocking */
2228 if (*argp) {
2229 close(fd);
2230 return 0;
2232 SetLastError(WSAEINVAL);
2233 close(fd);
2234 return SOCKET_ERROR;
2236 close(fd);
2237 if (*argp)
2238 _enable_event(s, 0, FD_WINE_NONBLOCKING, 0);
2239 else
2240 _enable_event(s, 0, 0, FD_WINE_NONBLOCKING);
2241 return 0;
2243 case WS_SIOCATMARK:
2244 newcmd=SIOCATMARK;
2245 break;
2247 case WS__IOW('f',125,u_long):
2248 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2249 SetLastError(WSAEINVAL);
2250 return SOCKET_ERROR;
2252 case SIOCGIFBRDADDR:
2253 case SIOCGIFNETMASK:
2254 case SIOCGIFADDR:
2255 /* These don't need any special handling. They are used by
2256 WsControl, and are here to suppress an unecessary warning. */
2257 break;
2260 default:
2261 /* Netscape tries hard to use bogus ioctl 0x667e */
2262 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2264 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2266 close(fd);
2267 return 0;
2269 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2270 close(fd);
2272 return SOCKET_ERROR;
2275 /***********************************************************************
2276 * ioctlsocket (WINSOCK.12)
2278 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
2280 return (INT16)WS_ioctlsocket( s, cmd, argp );
2284 /***********************************************************************
2285 * listen (WS2_32.13)
2287 int WINAPI WS_listen(SOCKET s, int backlog)
2289 int fd = _get_sock_fd(s);
2291 TRACE("socket %04x, backlog %d\n", s, backlog);
2292 if (fd != -1)
2294 if (listen(fd, backlog) == 0)
2296 close(fd);
2297 _enable_event(s, FD_ACCEPT,
2298 FD_WINE_LISTENING,
2299 FD_CONNECT|FD_WINE_CONNECTED);
2300 return 0;
2302 SetLastError(wsaErrno());
2304 else SetLastError(WSAENOTSOCK);
2305 return SOCKET_ERROR;
2308 /***********************************************************************
2309 * listen (WINSOCK.13)
2311 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
2313 return (INT16)WS_listen( s, backlog );
2317 /***********************************************************************
2318 * recv (WS2_32.16)
2320 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2322 DWORD n, dwFlags = flags;
2323 WSABUF wsabuf;
2325 wsabuf.len = len;
2326 wsabuf.buf = buf;
2328 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2329 return SOCKET_ERROR;
2330 else
2331 return n;
2334 /***********************************************************************
2335 * recv (WINSOCK.16)
2337 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2339 return (INT16)WS_recv( s, buf, len, flags );
2343 /***********************************************************************
2344 * recvfrom (WS2_32.17)
2346 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2347 struct WS_sockaddr *from, int *fromlen)
2349 DWORD n, dwFlags = flags;
2350 WSABUF wsabuf;
2352 wsabuf.len = len;
2353 wsabuf.buf = buf;
2355 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2356 return SOCKET_ERROR;
2357 else
2358 return n;
2361 /***********************************************************************
2362 * recvfrom (WINSOCK.17)
2364 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2365 struct WS_sockaddr *from, INT16 *fromlen16)
2367 INT fromlen32;
2368 INT *p = &fromlen32;
2369 INT retVal;
2371 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
2372 retVal = WS_recvfrom( s, buf, len, flags, from, p );
2373 if( fromlen16 ) *fromlen16 = fromlen32;
2374 return (INT16)retVal;
2377 /***********************************************************************
2378 * __ws_select
2380 static int __ws_select(BOOL b32,
2381 void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
2382 const struct WS_timeval *ws_timeout)
2384 int highfd = 0;
2385 fd_set readfds, writefds, exceptfds;
2386 fd_set *p_read, *p_write, *p_except;
2387 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2388 struct timeval timeout, *timeoutaddr = NULL;
2390 TRACE("read %p, write %p, excp %p timeout %p\n",
2391 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2393 p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
2394 p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
2395 p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
2396 if (ws_timeout)
2398 timeoutaddr = &timeout;
2399 timeout.tv_sec=ws_timeout->tv_sec;
2400 timeout.tv_usec=ws_timeout->tv_usec;
2403 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2405 fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
2406 fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
2408 if (p_except && ws_exceptfds)
2410 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
2411 #define wsfds32 ((WS_fd_set*)ws_exceptfds)
2412 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
2414 for (i = j = 0; i < count; i++)
2416 int fd = exceptfd[i];
2417 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
2419 if( b32 )
2420 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
2421 else
2422 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
2424 if( fd >= 0 ) close(fd);
2425 exceptfd[i] = -1;
2427 if( b32 )
2428 wsfds32->fd_count = j;
2429 else
2430 wsfds16->fd_count = j;
2431 #undef wsfds32
2432 #undef wsfds16
2434 return highfd;
2436 fd_set_unimport(ws_readfds, readfd, b32);
2437 fd_set_unimport(ws_writefds, writefd, b32);
2438 fd_set_unimport(ws_exceptfds, exceptfd, b32);
2439 if( ws_readfds ) ((WS_fd_set*)ws_readfds)->fd_count = 0;
2440 if( ws_writefds ) ((WS_fd_set*)ws_writefds)->fd_count = 0;
2441 if( ws_exceptfds ) ((WS_fd_set*)ws_exceptfds)->fd_count = 0;
2443 if( highfd == 0 ) return 0;
2444 SetLastError(wsaErrno());
2445 return SOCKET_ERROR;
2448 /***********************************************************************
2449 * select (WINSOCK.18)
2451 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
2452 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
2453 struct WS_timeval* timeout)
2455 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2458 /***********************************************************************
2459 * select (WS2_32.18)
2461 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2462 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2463 const struct WS_timeval* timeout)
2465 /* struct timeval is the same for both 32- and 16-bit code */
2466 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2470 /***********************************************************************
2471 * send (WS2_32.19)
2473 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2475 DWORD n;
2476 WSABUF wsabuf;
2478 wsabuf.len = len;
2479 wsabuf.buf = (char*) buf;
2481 if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2482 return SOCKET_ERROR;
2483 else
2484 return n;
2487 /***********************************************************************
2488 * WSASend (WS2_32.72)
2490 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2491 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2492 LPWSAOVERLAPPED lpOverlapped,
2493 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2495 return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2496 NULL, 0, lpOverlapped, lpCompletionRoutine );
2499 /***********************************************************************
2500 * WSASendTo (WS2_32.74)
2502 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2503 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2504 const struct WS_sockaddr *to, int tolen,
2505 LPWSAOVERLAPPED lpOverlapped,
2506 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2508 int i, n, fd, err = WSAENOTSOCK, flags, ret;
2509 struct iovec* iovec;
2510 struct ws2_async *wsa;
2511 enum fd_type type;
2513 TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2514 s, lpBuffers, dwBufferCount, dwFlags,
2515 to, tolen, lpOverlapped, lpCompletionRoutine);
2517 fd = _get_sock_fd_type( s, GENERIC_WRITE, &type, &flags );
2518 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
2520 if ( fd == -1 )
2522 err = WSAGetLastError ();
2523 goto error;
2526 iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
2528 if ( !iovec )
2530 err = WSAEFAULT;
2531 goto err_close;
2534 for ( i = 0; i < dwBufferCount; i++ )
2536 iovec[i].iov_base = lpBuffers[i].buf;
2537 iovec[i].iov_len = lpBuffers[i].len;
2540 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2542 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
2543 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2544 lpOverlapped, lpCompletionRoutine );
2545 if ( !wsa )
2547 err = WSAEFAULT;
2548 goto err_free;
2551 if ( ( ret = register_new_async ( &wsa->async )) )
2553 err = NtStatusToWSAError ( ret );
2555 if ( !lpOverlapped )
2556 HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
2557 HeapFree ( GetProcessHeap(), 0, wsa );
2558 goto err_free;
2561 /* Try immediate completion */
2562 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
2564 if ( WSAGetOverlappedResult ( (HANDLE) s, lpOverlapped,
2565 lpNumberOfBytesSent, FALSE, &dwFlags) )
2566 return 0;
2568 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
2569 goto error;
2572 WSASetLastError ( WSA_IO_PENDING );
2573 return SOCKET_ERROR;
2576 if (_is_blocking(s))
2578 /* FIXME: exceptfds? */
2579 do_block(fd, 2);
2582 n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2583 if ( n == -1 )
2585 err = wsaErrno();
2586 if ( err == WSAEWOULDBLOCK )
2587 _enable_event (s, FD_WRITE, 0, 0);
2588 goto err_free;
2591 TRACE(" -> %i bytes\n", n);
2592 *lpNumberOfBytesSent = n;
2594 HeapFree ( GetProcessHeap(), 0, iovec );
2595 close ( fd );
2596 return 0;
2598 err_free:
2599 HeapFree ( GetProcessHeap(), 0, iovec );
2601 err_close:
2602 close ( fd );
2604 error:
2605 WARN (" -> ERROR %d\n", err);
2606 WSASetLastError (err);
2607 return SOCKET_ERROR;
2610 /***********************************************************************
2611 * send (WINSOCK.19)
2613 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2615 return WS_send( s, buf, len, flags );
2618 /***********************************************************************
2619 * sendto (WS2_32.20)
2621 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2622 const struct WS_sockaddr *to, int tolen)
2624 DWORD n;
2625 WSABUF wsabuf;
2627 wsabuf.len = len;
2628 wsabuf.buf = (char*) buf;
2630 if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2631 return SOCKET_ERROR;
2632 else
2633 return n;
2636 /***********************************************************************
2637 * sendto (WINSOCK.20)
2639 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2640 struct WS_sockaddr *to, INT16 tolen)
2642 return (INT16)WS_sendto( s, buf, len, flags, to, tolen );
2645 /***********************************************************************
2646 * setsockopt (WS2_32.21)
2648 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2649 const char *optval, int optlen)
2651 int fd;
2653 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
2654 (int) optname, (int) optval, optlen);
2655 /* SO_OPENTYPE does not require a valid socket handle. */
2656 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2658 if (optlen < sizeof(int) || !optval)
2660 SetLastError(WSAEFAULT);
2661 return SOCKET_ERROR;
2663 TlsSetValue( opentype_tls_index, (LPVOID)*(int *)optval );
2664 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2665 return 0;
2668 fd = _get_sock_fd(s);
2669 if (fd != -1)
2671 struct linger linger;
2672 int woptval;
2674 /* Is a privileged and useless operation, so we don't. */
2675 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
2676 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2677 return 0;
2680 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2681 /* This is unique to WinSock and takes special conversion */
2682 linger.l_onoff = *((int*)optval) ? 0: 1;
2683 linger.l_linger = 0;
2684 optname=SO_LINGER;
2685 optval = (char*)&linger;
2686 optlen = sizeof(struct linger);
2687 level = SOL_SOCKET;
2688 }else{
2689 if (!convert_sockopt(&level, &optname)) {
2690 SetLastError(WSAENOPROTOOPT);
2691 close(fd);
2692 return SOCKET_ERROR;
2694 if (optname == SO_LINGER && optval) {
2695 /* yes, uses unsigned short in both win16/win32 */
2696 linger.l_onoff = ((UINT16*)optval)[0];
2697 linger.l_linger = ((UINT16*)optval)[1];
2698 /* FIXME: what is documented behavior if SO_LINGER optval
2699 is null?? */
2700 optval = (char*)&linger;
2701 optlen = sizeof(struct linger);
2702 } else if (optlen < sizeof(int)){
2703 woptval= *((INT16 *) optval);
2704 optval= (char*) &woptval;
2705 optlen=sizeof(int);
2708 if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2709 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2710 close( fd);
2711 return 0;
2714 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2716 close(fd);
2717 return 0;
2719 SetLastError(wsaErrno());
2720 close(fd);
2722 else SetLastError(WSAENOTSOCK);
2723 return SOCKET_ERROR;
2726 /***********************************************************************
2727 * setsockopt (WINSOCK.21)
2729 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2730 char *optval, INT16 optlen)
2732 if( !optval ) return SOCKET_ERROR;
2733 return (INT16)WS_setsockopt( s, (UINT16)level, optname, optval, optlen );
2737 /***********************************************************************
2738 * shutdown (WS2_32.22)
2740 int WINAPI WS_shutdown(SOCKET s, int how)
2742 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2743 enum fd_type type;
2744 unsigned int clear_flags = 0;
2746 fd = _get_sock_fd_type ( s, 0, &type, &flags );
2747 TRACE("socket %04x, how %i %d %d \n", s, how, type, flags );
2749 if (fd == -1)
2750 return SOCKET_ERROR;
2752 switch( how )
2754 case 0: /* drop receives */
2755 clear_flags |= FD_READ;
2756 break;
2757 case 1: /* drop sends */
2758 clear_flags |= FD_WRITE;
2759 break;
2760 case 2: /* drop all */
2761 clear_flags |= FD_READ|FD_WRITE;
2762 default:
2763 clear_flags |= FD_WINE_CONNECTED|FD_WINE_LISTENING;
2766 if ( flags & FD_FLAG_OVERLAPPED ) {
2768 switch ( how )
2770 case SD_RECEIVE:
2771 fd0 = fd;
2772 break;
2773 case SD_SEND:
2774 fd1 = fd;
2775 break;
2776 case SD_BOTH:
2777 default:
2778 fd0 = fd;
2779 fd1 = _get_sock_fd ( s );
2782 if ( fd0 != -1 )
2784 err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
2785 if ( err )
2787 close ( fd0 );
2788 goto error;
2791 if ( fd1 != -1 )
2793 err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
2794 if ( err )
2796 close ( fd1 );
2797 goto error;
2801 else /* non-overlapped mode */
2803 if ( shutdown( fd, how ) )
2805 err = wsaErrno ();
2806 close ( fd );
2807 goto error;
2809 close(fd);
2812 _enable_event( s, 0, 0, clear_flags );
2813 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2814 return 0;
2816 error:
2817 _enable_event( s, 0, 0, clear_flags );
2818 WSASetLastError ( err );
2819 return SOCKET_ERROR;
2822 /***********************************************************************
2823 * shutdown (WINSOCK.22)
2825 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2827 return (INT16)WS_shutdown( s, how );
2831 /***********************************************************************
2832 * socket (WS2_32.23)
2834 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2836 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2838 return WSASocketA ( af, type, protocol, NULL, 0,
2839 (TlsGetValue(opentype_tls_index) ? 0 : WSA_FLAG_OVERLAPPED) );
2842 /***********************************************************************
2843 * socket (WINSOCK.23)
2845 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2847 return (SOCKET16)WS_socket( af, type, protocol );
2851 /* ----------------------------------- DNS services
2853 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2854 * Also, we have to use wsock32 stubs to convert structures and
2855 * error codes from Unix to WSA, hence there is no direct mapping in
2856 * the relay32/wsock32.spec.
2860 /***********************************************************************
2861 * __ws_gethostbyaddr
2863 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2865 WIN_hostent *retval = NULL;
2867 struct hostent* host;
2868 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2869 char *extrabuf;
2870 int ebufsize=1024;
2871 struct hostent hostentry;
2872 int locerr=ENOBUFS;
2873 host = NULL;
2874 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2875 while(extrabuf) {
2876 int res = gethostbyaddr_r(addr, len, type,
2877 &hostentry, extrabuf, ebufsize, &host, &locerr);
2878 if( res != ERANGE) break;
2879 ebufsize *=2;
2880 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2882 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2883 #else
2884 EnterCriticalSection( &csWSgetXXXbyYYY );
2885 host = gethostbyaddr(addr, len, type);
2886 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2887 #endif
2888 if( host != NULL )
2890 if( WS_dup_he(host, dup_flag) )
2891 retval = he_buffer;
2892 else
2893 SetLastError(WSAENOBUFS);
2895 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2896 HeapFree(GetProcessHeap(),0,extrabuf);
2897 #else
2898 LeaveCriticalSection( &csWSgetXXXbyYYY );
2899 #endif
2900 return retval;
2903 /***********************************************************************
2904 * gethostbyaddr (WINSOCK.51)
2906 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2908 TRACE("ptr %p, len %d, type %d\n", addr, len, type);
2909 if (!__ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR )) return 0;
2910 return he_buffer_seg;
2913 /***********************************************************************
2914 * gethostbyaddr (WS2_32.51)
2916 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len,
2917 int type)
2919 TRACE("ptr %08x, len %d, type %d\n",
2920 (unsigned) addr, len, type);
2921 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2924 /***********************************************************************
2925 * __ws_gethostbyname
2927 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2929 WIN_hostent *retval = NULL;
2930 struct hostent* host;
2931 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2932 char *extrabuf;
2933 int ebufsize=1024;
2934 struct hostent hostentry;
2935 int locerr = ENOBUFS;
2936 host = NULL;
2937 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2938 while(extrabuf) {
2939 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2940 if( res != ERANGE) break;
2941 ebufsize *=2;
2942 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2944 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2945 #else
2946 EnterCriticalSection( &csWSgetXXXbyYYY );
2947 host = gethostbyname(name);
2948 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2949 #endif
2950 if( host != NULL )
2952 if( WS_dup_he(host, dup_flag) )
2953 retval = he_buffer;
2954 else SetLastError(WSAENOBUFS);
2956 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2957 HeapFree(GetProcessHeap(),0,extrabuf);
2958 #else
2959 LeaveCriticalSection( &csWSgetXXXbyYYY );
2960 #endif
2961 return retval;
2964 /***********************************************************************
2965 * gethostbyname (WINSOCK.52)
2967 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2969 TRACE( "%s\n", debugstr_a(name) );
2970 if (!__ws_gethostbyname( name, WS_DUP_SEGPTR )) return 0;
2971 return he_buffer_seg;
2974 /***********************************************************************
2975 * gethostbyname (WS2_32.52)
2977 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2979 TRACE( "%s\n", debugstr_a(name) );
2980 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2984 /***********************************************************************
2985 * __ws_getprotobyname
2987 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2989 WIN_protoent* retval = NULL;
2990 #ifdef HAVE_GETPROTOBYNAME
2991 struct protoent* proto;
2992 EnterCriticalSection( &csWSgetXXXbyYYY );
2993 if( (proto = getprotobyname(name)) != NULL )
2995 if( WS_dup_pe(proto, dup_flag) )
2996 retval = pe_buffer;
2997 else SetLastError(WSAENOBUFS);
2999 else {
3000 MESSAGE("protocol %s not found; You might want to add "
3001 "this to /etc/protocols\n", debugstr_a(name) );
3002 SetLastError(WSANO_DATA);
3004 LeaveCriticalSection( &csWSgetXXXbyYYY );
3005 #endif
3006 return retval;
3009 /***********************************************************************
3010 * getprotobyname (WINSOCK.53)
3012 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
3014 TRACE( "%s\n", debugstr_a(name) );
3015 if (!__ws_getprotobyname(name, WS_DUP_SEGPTR)) return 0;
3016 return pe_buffer_seg;
3019 /***********************************************************************
3020 * getprotobyname (WS2_32.53)
3022 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
3024 TRACE( "%s\n", debugstr_a(name) );
3025 return __ws_getprotobyname(name, WS_DUP_LINEAR);
3029 /***********************************************************************
3030 * __ws_getprotobynumber
3032 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
3034 WIN_protoent* retval = NULL;
3035 #ifdef HAVE_GETPROTOBYNUMBER
3036 struct protoent* proto;
3037 EnterCriticalSection( &csWSgetXXXbyYYY );
3038 if( (proto = getprotobynumber(number)) != NULL )
3040 if( WS_dup_pe(proto, dup_flag) )
3041 retval = pe_buffer;
3042 else SetLastError(WSAENOBUFS);
3044 else {
3045 MESSAGE("protocol number %d not found; You might want to add "
3046 "this to /etc/protocols\n", number );
3047 SetLastError(WSANO_DATA);
3049 LeaveCriticalSection( &csWSgetXXXbyYYY );
3050 #endif
3051 return retval;
3054 /***********************************************************************
3055 * getprotobynumber (WINSOCK.54)
3057 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
3059 TRACE("%i\n", number);
3060 if (!__ws_getprotobynumber(number, WS_DUP_SEGPTR)) return 0;
3061 return pe_buffer_seg;
3064 /***********************************************************************
3065 * getprotobynumber (WS2_32.54)
3067 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
3069 TRACE("%i\n", number);
3070 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
3074 /***********************************************************************
3075 * __ws_getservbyname
3077 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
3079 WIN_servent* retval = NULL;
3080 struct servent* serv;
3081 int i = wsi_strtolo( name, proto );
3083 if( i ) {
3084 EnterCriticalSection( &csWSgetXXXbyYYY );
3085 serv = getservbyname(local_buffer,
3086 proto ? (local_buffer + i) : NULL);
3087 if( serv != NULL )
3089 if( WS_dup_se(serv, dup_flag) )
3090 retval = se_buffer;
3091 else SetLastError(WSAENOBUFS);
3093 else {
3094 MESSAGE("service %s protocol %s not found; You might want to add "
3095 "this to /etc/services\n", debugstr_a(local_buffer),
3096 proto ? debugstr_a(local_buffer+i):"*");
3097 SetLastError(WSANO_DATA);
3099 LeaveCriticalSection( &csWSgetXXXbyYYY );
3101 else SetLastError(WSAENOBUFS);
3102 return retval;
3105 /***********************************************************************
3106 * getservbyname (WINSOCK.55)
3108 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
3110 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3111 if (!__ws_getservbyname(name, proto, WS_DUP_SEGPTR)) return 0;
3112 return se_buffer_seg;
3115 /***********************************************************************
3116 * getservbyname (WS2_32.55)
3118 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
3120 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3121 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
3125 /***********************************************************************
3126 * __ws_getservbyport
3128 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
3130 WIN_servent* retval = NULL;
3131 #ifdef HAVE_GETSERVBYPORT
3132 struct servent* serv;
3133 if (!proto || wsi_strtolo( proto, NULL )) {
3134 EnterCriticalSection( &csWSgetXXXbyYYY );
3135 if( (serv = getservbyport(port, (proto) ? local_buffer : NULL)) != NULL ) {
3136 if( WS_dup_se(serv, dup_flag) )
3137 retval = se_buffer;
3138 else SetLastError(WSAENOBUFS);
3140 else {
3141 MESSAGE("service on port %lu protocol %s not found; You might want to add "
3142 "this to /etc/services\n", (unsigned long)ntohl(port),
3143 proto ? debugstr_a(local_buffer) : "*");
3144 SetLastError(WSANO_DATA);
3146 LeaveCriticalSection( &csWSgetXXXbyYYY );
3148 else SetLastError(WSAENOBUFS);
3149 #endif
3150 return retval;
3153 /***********************************************************************
3154 * getservbyport (WINSOCK.56)
3156 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
3158 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3159 if (!__ws_getservbyport(port, proto, WS_DUP_SEGPTR)) return 0;
3160 return se_buffer_seg;
3163 /***********************************************************************
3164 * getservbyport (WS2_32.56)
3166 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
3168 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3169 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
3173 /***********************************************************************
3174 * gethostname (WS2_32.57)
3176 int WINAPI WS_gethostname(char *name, int namelen)
3178 TRACE("name %p, len %d\n", name, namelen);
3180 if (gethostname(name, namelen) == 0)
3182 TRACE("<- '%s'\n", name);
3183 return 0;
3185 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
3186 TRACE("<- ERROR !\n");
3187 return SOCKET_ERROR;
3190 /***********************************************************************
3191 * gethostname (WINSOCK.57)
3193 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
3195 return (INT16)WS_gethostname(name, namelen);
3199 /* ------------------------------------- Windows sockets extensions -- *
3201 * ------------------------------------------------------------------- */
3203 /***********************************************************************
3204 * WSAEnumNetworkEvents (WS2_32.36)
3206 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
3208 int ret;
3210 TRACE("%08x, hEvent %08x, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
3212 SERVER_START_REQ( get_socket_event )
3214 req->handle = s;
3215 req->service = TRUE;
3216 req->c_event = hEvent;
3217 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
3218 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
3220 SERVER_END_REQ;
3221 if (!ret) return 0;
3222 SetLastError(WSAEINVAL);
3223 return SOCKET_ERROR;
3226 /***********************************************************************
3227 * WSAEventSelect (WS2_32.39)
3229 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
3231 int ret;
3233 TRACE("%08x, hEvent %08x, event %08x\n", s, hEvent, (unsigned)lEvent );
3235 SERVER_START_REQ( set_socket_event )
3237 req->handle = s;
3238 req->mask = lEvent;
3239 req->event = hEvent;
3240 req->window = 0;
3241 req->msg = 0;
3242 ret = wine_server_call( req );
3244 SERVER_END_REQ;
3245 if (!ret) return 0;
3246 SetLastError(WSAEINVAL);
3247 return SOCKET_ERROR;
3250 /**********************************************************************
3251 * WSAGetOverlappedResult (WS2_32.40)
3253 BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
3254 LPDWORD lpcbTransfer, BOOL fWait,
3255 LPDWORD lpdwFlags )
3257 DWORD r;
3259 TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
3260 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
3262 if ( !(lpOverlapped && lpOverlapped->hEvent) )
3264 ERR ( "Invalid pointer\n" );
3265 WSASetLastError (WSA_INVALID_PARAMETER);
3266 return FALSE;
3269 do {
3270 r = WaitForSingleObjectEx (lpOverlapped->hEvent, fWait ? INFINITE : 0, TRUE);
3271 } while (r == STATUS_USER_APC);
3273 if ( lpcbTransfer )
3274 *lpcbTransfer = lpOverlapped->InternalHigh;
3276 if ( lpdwFlags )
3277 *lpdwFlags = lpOverlapped->Offset;
3279 if ( r == WAIT_OBJECT_0 )
3280 return TRUE;
3282 WSASetLastError ( lpOverlapped->Internal == STATUS_PENDING ?
3283 WSA_IO_INCOMPLETE : NtStatusToWSAError ( lpOverlapped->Internal ) );
3284 return FALSE;
3288 /***********************************************************************
3289 * WSAAsyncSelect (WS2_32.101)
3291 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
3293 int ret;
3295 TRACE("%x, hWnd %x, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3297 SERVER_START_REQ( set_socket_event )
3299 req->handle = s;
3300 req->mask = lEvent;
3301 req->event = 0;
3302 req->window = hWnd;
3303 req->msg = uMsg;
3304 ret = wine_server_call( req );
3306 SERVER_END_REQ;
3307 if (!ret) return 0;
3308 SetLastError(WSAEINVAL);
3309 return SOCKET_ERROR;
3312 /***********************************************************************
3313 * WSAAsyncSelect (WINSOCK.101)
3315 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
3317 return (INT16)WSAAsyncSelect( s, HWND_32(hWnd), wMsg, lEvent );
3320 /***********************************************************************
3321 * WSARecvEx (WINSOCK.1107)
3323 * See description for WSARecvEx()
3325 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags)
3327 FIXME("(WSARecvEx16) partial packet return value not set \n");
3329 return WINSOCK_recv16(s, buf, len, *flags);
3333 /***********************************************************************
3334 * WSACreateEvent (WS2_32.31)
3337 WSAEVENT WINAPI WSACreateEvent(void)
3339 /* Create a manual-reset event, with initial state: unsignealed */
3340 TRACE("\n");
3342 return CreateEventA(NULL, TRUE, FALSE, NULL);
3345 /***********************************************************************
3346 * WSACloseEvent (WS2_32.29)
3349 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3351 TRACE ("event=0x%x\n", event);
3353 return CloseHandle(event);
3356 /***********************************************************************
3357 * WSASocketA (WS2_32.78)
3360 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3361 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3362 GROUP g, DWORD dwFlags)
3364 SOCKET ret;
3367 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
3368 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3371 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3372 af, type, protocol, lpProtocolInfo, g, dwFlags );
3374 /* hack for WSADuplicateSocket */
3375 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3376 ret = lpProtocolInfo->dwCatalogEntryId;
3377 TRACE("\tgot duplicate %04x\n", ret);
3378 return ret;
3381 /* check the socket family */
3382 switch(af)
3384 #ifdef HAVE_IPX
3385 case WS_AF_IPX: af = AF_IPX;
3386 #endif
3387 case AF_INET:
3388 case AF_UNSPEC:
3389 break;
3390 default:
3391 SetLastError(WSAEAFNOSUPPORT);
3392 return INVALID_SOCKET;
3395 /* check the socket type */
3396 switch(type)
3398 case WS_SOCK_STREAM:
3399 type=SOCK_STREAM;
3400 break;
3401 case WS_SOCK_DGRAM:
3402 type=SOCK_DGRAM;
3403 break;
3404 case WS_SOCK_RAW:
3405 type=SOCK_RAW;
3406 break;
3407 default:
3408 SetLastError(WSAESOCKTNOSUPPORT);
3409 return INVALID_SOCKET;
3412 /* check the protocol type */
3413 if ( protocol < 0 ) /* don't support negative values */
3415 SetLastError(WSAEPROTONOSUPPORT);
3416 return INVALID_SOCKET;
3419 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3420 switch(protocol)
3422 case IPPROTO_TCP:
3423 if (type == SOCK_STREAM) { af = AF_INET; break; }
3424 case IPPROTO_UDP:
3425 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3426 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3429 SERVER_START_REQ( create_socket )
3431 req->family = af;
3432 req->type = type;
3433 req->protocol = protocol;
3434 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3435 req->flags = dwFlags;
3436 req->inherit = TRUE;
3437 set_error( wine_server_call( req ) );
3438 ret = (SOCKET)reply->handle;
3440 SERVER_END_REQ;
3441 if (ret)
3443 TRACE("\tcreated %04x\n", ret );
3444 return ret;
3447 if (GetLastError() == WSAEACCES) /* raw socket denied */
3449 if (type == SOCK_RAW)
3450 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3451 else
3452 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3453 SetLastError(WSAESOCKTNOSUPPORT);
3456 WARN("\t\tfailed!\n");
3457 return INVALID_SOCKET;
3461 /***********************************************************************
3462 * __WSAFDIsSet (WINSOCK.151)
3464 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
3466 int i = set->fd_count;
3468 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3470 while (i--)
3471 if (set->fd_array[i] == s) return 1;
3472 return 0;
3475 /***********************************************************************
3476 * __WSAFDIsSet (WS2_32.151)
3478 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3480 int i = set->fd_count;
3482 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3484 while (i--)
3485 if (set->fd_array[i] == s) return 1;
3486 return 0;
3489 /***********************************************************************
3490 * WSAIsBlocking (WINSOCK.114)
3491 * WSAIsBlocking (WS2_32.114)
3493 BOOL WINAPI WSAIsBlocking(void)
3495 /* By default WinSock should set all its sockets to non-blocking mode
3496 * and poll in PeekMessage loop when processing "blocking" ones. This
3497 * function is supposed to tell if the program is in this loop. Our
3498 * blocking calls are truly blocking so we always return FALSE.
3500 * Note: It is allowed to call this function without prior WSAStartup().
3503 TRACE("\n");
3504 return FALSE;
3507 /***********************************************************************
3508 * WSACancelBlockingCall (WINSOCK.113)
3509 * WSACancelBlockingCall (WS2_32.113)
3511 INT WINAPI WSACancelBlockingCall(void)
3513 TRACE("\n");
3514 return 0;
3518 /***********************************************************************
3519 * WSASetBlockingHook (WINSOCK.109)
3521 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
3523 FARPROC16 prev = (FARPROC16)blocking_hook;
3524 blocking_hook = (FARPROC)lpBlockFunc;
3525 TRACE("hook %p\n", lpBlockFunc);
3526 return prev;
3530 /***********************************************************************
3531 * WSASetBlockingHook (WS2_32.109)
3533 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3535 FARPROC prev = blocking_hook;
3536 blocking_hook = lpBlockFunc;
3537 TRACE("hook %p\n", lpBlockFunc);
3538 return prev;
3542 /***********************************************************************
3543 * WSAUnhookBlockingHook (WINSOCK.110)
3545 INT16 WINAPI WSAUnhookBlockingHook16(void)
3547 blocking_hook = NULL;
3548 return 0;
3552 /***********************************************************************
3553 * WSAUnhookBlockingHook (WS2_32.110)
3555 INT WINAPI WSAUnhookBlockingHook(void)
3557 blocking_hook = NULL;
3558 return 0;
3562 /* ----------------------------------- end of API stuff */
3564 /* ----------------------------------- helper functions -
3566 * TODO: Merge WS_dup_..() stuff into one function that
3567 * would operate with a generic structure containing internal
3568 * pointers (via a template of some kind).
3571 static int list_size(char** l, int item_size)
3573 int i,j = 0;
3574 if(l)
3575 { for(i=0;l[i];i++)
3576 j += (item_size) ? item_size : strlen(l[i]) + 1;
3577 j += (i + 1) * sizeof(char*); }
3578 return j;
3581 static int list_dup(char** l_src, char* ref, char* base, int item_size)
3583 /* base is either either equal to ref or 0 or SEGPTR */
3585 char* p = ref;
3586 char** l_to = (char**)ref;
3587 int i,j,k;
3589 for(j=0;l_src[j];j++) ;
3590 p += (j + 1) * sizeof(char*);
3591 for(i=0;i<j;i++)
3592 { l_to[i] = base + (p - ref);
3593 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3594 memcpy(p, l_src[i], k); p += k; }
3595 l_to[i] = NULL;
3596 return (p - ref);
3599 /* ----- hostent */
3601 static int hostent_size(struct hostent* p_he)
3603 int size = 0;
3604 if( p_he )
3605 { size = sizeof(struct hostent);
3606 size += strlen(p_he->h_name) + 1;
3607 size += list_size(p_he->h_aliases, 0);
3608 size += list_size(p_he->h_addr_list, p_he->h_length ); }
3609 return size;
3612 /* duplicate hostent entry
3613 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3614 * Dito for protoent and servent.
3616 static int WS_dup_he(struct hostent* p_he, int flag)
3618 /* Convert hostent structure into ws_hostent so that the data fits
3619 * into local_buffer. Internal pointers can be linear, SEGPTR, or
3620 * relative to local_buffer depending on "flag" value. Returns size
3621 * of the data copied.
3624 int size = hostent_size(p_he);
3625 if( size )
3627 char *p_name,*p_aliases,*p_addr,*p_base,*p;
3628 char *p_to;
3629 struct ws_hostent16 *p_to16;
3630 struct WS_hostent *p_to32;
3632 check_buffer_he(size);
3633 p_to = he_buffer;
3634 p_to16 = he_buffer;
3635 p_to32 = he_buffer;
3637 p = p_to;
3638 p_base = (flag & WS_DUP_SEGPTR) ? (char*)he_buffer_seg : he_buffer;
3639 p += (flag & WS_DUP_SEGPTR) ?
3640 sizeof(struct ws_hostent16) : sizeof(struct WS_hostent);
3641 p_name = p;
3642 strcpy(p, p_he->h_name); p += strlen(p) + 1;
3643 p_aliases = p;
3644 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3645 p_addr = p;
3646 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
3648 if (flag & WS_DUP_SEGPTR) /* Win16 */
3650 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
3651 p_to16->h_length = (INT16)p_he->h_length;
3652 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3653 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3654 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3655 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3657 else /* Win32 */
3659 p_to32->h_addrtype = p_he->h_addrtype;
3660 p_to32->h_length = p_he->h_length;
3661 p_to32->h_name = (p_base + (p_name - p_to));
3662 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3663 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3664 size += (sizeof(struct WS_hostent) - sizeof(struct hostent));
3667 return size;
3670 /* ----- protoent */
3672 static int protoent_size(struct protoent* p_pe)
3674 int size = 0;
3675 if( p_pe )
3676 { size = sizeof(struct protoent);
3677 size += strlen(p_pe->p_name) + 1;
3678 size += list_size(p_pe->p_aliases, 0); }
3679 return size;
3682 static int WS_dup_pe(struct protoent* p_pe, int flag)
3684 int size = protoent_size(p_pe);
3685 if( size )
3687 char *p_to;
3688 struct ws_protoent16 *p_to16;
3689 struct WS_protoent *p_to32;
3690 char *p_name,*p_aliases,*p_base,*p;
3692 check_buffer_pe(size);
3693 p_to = pe_buffer;
3694 p_to16 = pe_buffer;
3695 p_to32 = pe_buffer;
3696 p = p_to;
3697 p_base = (flag & WS_DUP_SEGPTR) ? (char*)pe_buffer_seg : pe_buffer;
3698 p += (flag & WS_DUP_SEGPTR) ?
3699 sizeof(struct ws_protoent16) : sizeof(struct WS_protoent);
3700 p_name = p;
3701 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3702 p_aliases = p;
3703 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3705 if (flag & WS_DUP_SEGPTR) /* Win16 */
3707 p_to16->p_proto = (INT16)p_pe->p_proto;
3708 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3709 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3710 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3712 else /* Win32 */
3714 p_to32->p_proto = p_pe->p_proto;
3715 p_to32->p_name = (p_base) + (p_name - p_to);
3716 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3717 size += (sizeof(struct WS_protoent) - sizeof(struct protoent));
3720 return size;
3723 /* ----- servent */
3725 static int servent_size(struct servent* p_se)
3727 int size = 0;
3728 if( p_se )
3729 { size += sizeof(struct servent);
3730 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3731 size += list_size(p_se->s_aliases, 0); }
3732 return size;
3735 static int WS_dup_se(struct servent* p_se, int flag)
3737 int size = servent_size(p_se);
3738 if( size )
3740 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3741 char *p_to;
3742 struct ws_servent16 *p_to16;
3743 struct WS_servent *p_to32;
3745 check_buffer_se(size);
3746 p_to = se_buffer;
3747 p_to16 = se_buffer;
3748 p_to32 = se_buffer;
3749 p = p_to;
3750 p_base = (flag & WS_DUP_SEGPTR) ? (char*)se_buffer_seg : se_buffer;
3751 p += (flag & WS_DUP_SEGPTR) ?
3752 sizeof(struct ws_servent16) : sizeof(struct WS_servent);
3753 p_name = p;
3754 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3755 p_proto = p;
3756 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3757 p_aliases = p;
3758 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3760 if (flag & WS_DUP_SEGPTR) /* Win16 */
3762 p_to16->s_port = (INT16)p_se->s_port;
3763 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3764 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3765 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3766 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3768 else /* Win32 */
3770 p_to32->s_port = p_se->s_port;
3771 p_to32->s_name = (p_base + (p_name - p_to));
3772 p_to32->s_proto = (p_base + (p_proto - p_to));
3773 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3774 size += (sizeof(struct WS_servent) - sizeof(struct servent));
3777 return size;
3780 /* ----------------------------------- error handling */
3782 UINT16 wsaErrno(void)
3784 int loc_errno = errno;
3785 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3787 switch(loc_errno)
3789 case EINTR: return WSAEINTR;
3790 case EBADF: return WSAEBADF;
3791 case EPERM:
3792 case EACCES: return WSAEACCES;
3793 case EFAULT: return WSAEFAULT;
3794 case EINVAL: return WSAEINVAL;
3795 case EMFILE: return WSAEMFILE;
3796 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3797 case EINPROGRESS: return WSAEINPROGRESS;
3798 case EALREADY: return WSAEALREADY;
3799 case ENOTSOCK: return WSAENOTSOCK;
3800 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3801 case EMSGSIZE: return WSAEMSGSIZE;
3802 case EPROTOTYPE: return WSAEPROTOTYPE;
3803 case ENOPROTOOPT: return WSAENOPROTOOPT;
3804 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3805 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3806 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3807 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3808 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3809 case EADDRINUSE: return WSAEADDRINUSE;
3810 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3811 case ENETDOWN: return WSAENETDOWN;
3812 case ENETUNREACH: return WSAENETUNREACH;
3813 case ENETRESET: return WSAENETRESET;
3814 case ECONNABORTED: return WSAECONNABORTED;
3815 case EPIPE:
3816 case ECONNRESET: return WSAECONNRESET;
3817 case ENOBUFS: return WSAENOBUFS;
3818 case EISCONN: return WSAEISCONN;
3819 case ENOTCONN: return WSAENOTCONN;
3820 case ESHUTDOWN: return WSAESHUTDOWN;
3821 case ETOOMANYREFS: return WSAETOOMANYREFS;
3822 case ETIMEDOUT: return WSAETIMEDOUT;
3823 case ECONNREFUSED: return WSAECONNREFUSED;
3824 case ELOOP: return WSAELOOP;
3825 case ENAMETOOLONG: return WSAENAMETOOLONG;
3826 case EHOSTDOWN: return WSAEHOSTDOWN;
3827 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3828 case ENOTEMPTY: return WSAENOTEMPTY;
3829 #ifdef EPROCLIM
3830 case EPROCLIM: return WSAEPROCLIM;
3831 #endif
3832 #ifdef EUSERS
3833 case EUSERS: return WSAEUSERS;
3834 #endif
3835 #ifdef EDQUOT
3836 case EDQUOT: return WSAEDQUOT;
3837 #endif
3838 #ifdef ESTALE
3839 case ESTALE: return WSAESTALE;
3840 #endif
3841 #ifdef EREMOTE
3842 case EREMOTE: return WSAEREMOTE;
3843 #endif
3845 /* just in case we ever get here and there are no problems */
3846 case 0: return 0;
3847 default:
3848 WARN("Unknown errno %d!\n", loc_errno);
3849 return WSAEOPNOTSUPP;
3853 UINT16 wsaHerrno(int loc_errno)
3856 WARN("h_errno %d.\n", loc_errno);
3858 switch(loc_errno)
3860 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3861 case TRY_AGAIN: return WSATRY_AGAIN;
3862 case NO_RECOVERY: return WSANO_RECOVERY;
3863 case NO_DATA: return WSANO_DATA;
3864 case ENOBUFS: return WSAENOBUFS;
3866 case 0: return 0;
3867 default:
3868 WARN("Unknown h_errno %d!\n", loc_errno);
3869 return WSAEOPNOTSUPP;
3874 /***********************************************************************
3875 * WSARecv (WS2_32.67)
3877 int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3878 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3879 LPWSAOVERLAPPED lpOverlapped,
3880 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3882 return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3883 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3886 /***********************************************************************
3887 * WSARecvFrom (WS2_32.69)
3889 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3890 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3891 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3892 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3895 int i, n, fd, err = WSAENOTSOCK, flags, ret;
3896 struct iovec* iovec;
3897 struct ws2_async *wsa;
3898 enum fd_type type;
3900 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3901 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3902 (lpFromlen ? *lpFromlen : -1L),
3903 lpOverlapped, lpCompletionRoutine);
3905 fd = _get_sock_fd_type( s, GENERIC_READ, &type, &flags );
3906 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
3908 if (fd == -1)
3910 err = WSAGetLastError ();
3911 goto error;
3914 iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3915 if ( !iovec )
3917 err = WSAEFAULT;
3918 goto err_close;
3921 for (i = 0; i < dwBufferCount; i++)
3923 iovec[i].iov_base = lpBuffers[i].buf;
3924 iovec[i].iov_len = lpBuffers[i].len;
3927 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3929 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
3930 lpFlags, lpFrom, lpFromlen,
3931 lpOverlapped, lpCompletionRoutine );
3933 if ( !wsa )
3935 err = WSAEFAULT;
3936 goto err_free;
3939 if ( ( ret = register_new_async ( &wsa->async )) )
3941 err = NtStatusToWSAError ( ret );
3943 if ( !lpOverlapped )
3944 HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
3945 HeapFree ( GetProcessHeap(), 0, wsa );
3946 goto err_free;
3949 /* Try immediate completion */
3950 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
3952 if ( WSAGetOverlappedResult ( (HANDLE) s, lpOverlapped,
3953 lpNumberOfBytesRecvd, FALSE, lpFlags) )
3954 return 0;
3956 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
3957 goto error;
3960 WSASetLastError ( WSA_IO_PENDING );
3961 return SOCKET_ERROR;
3964 if ( _is_blocking(s) )
3966 /* block here */
3967 /* FIXME: OOB and exceptfds? */
3968 do_block(fd, 1);
3971 n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3972 if ( n == -1 )
3974 err = wsaErrno();
3975 goto err_free;
3978 TRACE(" -> %i bytes\n", n);
3979 *lpNumberOfBytesRecvd = n;
3981 HeapFree (GetProcessHeap(), 0, iovec);
3982 close(fd);
3983 _enable_event(s, FD_READ, 0, 0);
3985 return 0;
3987 err_free:
3988 HeapFree (GetProcessHeap(), 0, iovec);
3990 err_close:
3991 close (fd);
3993 error:
3994 WARN(" -> ERROR %d\n", err);
3995 WSASetLastError ( err );
3996 return SOCKET_ERROR;
3999 /***********************************************************************
4000 * WSCInstallProvider (WS2_32.88)
4002 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
4003 LPCWSTR lpszProviderDllPath,
4004 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
4005 DWORD dwNumberOfEntries,
4006 LPINT lpErrno )
4008 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
4009 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
4010 dwNumberOfEntries, lpErrno);
4011 *lpErrno = 0;
4012 return 0;
4016 /***********************************************************************
4017 * WSCDeinstallProvider (WS2_32.83)
4019 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
4021 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
4022 *lpErrno = 0;
4023 return 0;
4027 /***********************************************************************
4028 * WSAAccept (WS2_32.26)
4030 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
4031 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
4034 int ret = 0, size = 0;
4035 WSABUF CallerId, CallerData, CalleeId, CalleeData;
4036 /* QOS SQOS, GQOS; */
4037 GROUP g;
4038 SOCKET cs;
4039 SOCKADDR src_addr, dst_addr;
4041 TRACE("Socket %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
4042 s, addr, addrlen, lpfnCondition, dwCallbackData);
4045 size = sizeof(src_addr);
4046 cs = WS_accept(s, &src_addr, &size);
4048 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
4050 CallerId.buf = (char *)&src_addr;
4051 CallerId.len = sizeof(src_addr);
4053 CallerData.buf = NULL;
4054 CallerData.len = (ULONG)NULL;
4056 WS_getsockname(cs, &dst_addr, &size);
4058 CalleeId.buf = (char *)&dst_addr;
4059 CalleeId.len = sizeof(dst_addr);
4062 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
4063 &CalleeId, &CalleeData, &g, dwCallbackData);
4065 switch (ret)
4067 case CF_ACCEPT:
4068 if (addr && addrlen)
4069 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
4070 return cs;
4071 case CF_DEFER:
4072 SERVER_START_REQ ( set_socket_deferred )
4074 req->handle = s;
4075 req->deferred = cs;
4076 if ( !wine_server_call_err ( req ) )
4078 SetLastError ( WSATRY_AGAIN );
4079 CloseHandle ( cs );
4082 SERVER_END_REQ;
4083 return SOCKET_ERROR;
4084 case CF_REJECT:
4085 WS_closesocket(cs);
4086 SetLastError(WSAECONNREFUSED);
4087 return SOCKET_ERROR;
4088 default:
4089 FIXME("Unknown return type from Condition function\n");
4090 SetLastError(WSAENOTSOCK);
4091 return SOCKET_ERROR;
4094 SetLastError(WSAENOTSOCK);
4095 return SOCKET_ERROR;
4098 /***********************************************************************
4099 * WSAEnumProtocolsA (WS2_32.37)
4101 int WINAPI WSAEnumProtocolsA(LPINT lpiProtocols, LPWSAPROTOCOL_INFOA lpProtocolBuffer, LPDWORD lpdwBufferLength)
4103 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4104 return 0;
4107 /***********************************************************************
4108 * WSAEnumProtocolsW (WS2_32.38)
4110 int WINAPI WSAEnumProtocolsW(LPINT lpiProtocols, LPWSAPROTOCOL_INFOW lpProtocolBuffer, LPDWORD lpdwBufferLength)
4112 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4113 return 0;
4116 /***********************************************************************
4117 * WSADuplicateSocketA (WS2_32.32)
4119 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
4121 HANDLE hProcess;
4123 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
4124 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
4125 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
4126 /* I don't know what the real Windoze does next, this is a hack */
4127 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
4128 * the target use the global duplicate, or we could copy a reference to us to the structure
4129 * and let the target duplicate it from us, but let's do it as simple as possible */
4130 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
4131 DuplicateHandle(GetCurrentProcess(), s,
4132 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
4133 0, FALSE, DUPLICATE_SAME_ACCESS);
4134 CloseHandle(hProcess);
4135 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
4136 return 0;