Fixed wownt32.h to make it usable from inside Wine, and use it to
[wine/gsoc_dplay.git] / dlls / winsock / socket.c
blobb98d6304c0f5555935c31d6185a789f17ebb9815
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 "wownt32.h"
118 #include "wine/server.h"
119 #include "wine/debug.h"
122 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
124 /* critical section to protect some non-rentrant net function */
125 extern CRITICAL_SECTION csWSgetXXXbyYYY;
127 #define DEBUG_SOCKADDR 0
128 #define dump_sockaddr(a) \
129 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
130 ((struct sockaddr_in *)a)->sin_family, \
131 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
132 ntohs(((struct sockaddr_in *)a)->sin_port))
134 /****************************************************************
135 * Async IO declarations
136 ****************************************************************/
137 #include "async.h"
139 static DWORD ws2_async_get_status (const struct async_private *ovp);
140 static DWORD ws2_async_get_count (const struct async_private *ovp);
141 static void ws2_async_set_status (struct async_private *ovp, const DWORD status);
142 static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
143 static void ws2_async_cleanup ( struct async_private *ovp );
145 static struct async_ops ws2_async_ops =
147 ws2_async_get_status,
148 ws2_async_set_status,
149 ws2_async_get_count,
150 ws2_async_call_completion,
151 ws2_async_cleanup
154 static struct async_ops ws2_nocomp_async_ops =
156 ws2_async_get_status,
157 ws2_async_set_status,
158 ws2_async_get_count,
159 NULL, /* call_completion */
160 ws2_async_cleanup
163 typedef struct ws2_async
165 async_private async;
166 LPWSAOVERLAPPED overlapped;
167 LPWSAOVERLAPPED user_overlapped;
168 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
169 struct iovec *iovec;
170 int n_iovecs;
171 struct WS_sockaddr *addr;
172 union {
173 int val; /* for send operations */
174 int *ptr; /* for recv operations */
175 } addrlen;
176 DWORD flags;
177 } ws2_async;
179 /****************************************************************/
181 /* ----------------------------------- internal data */
183 /* ws_... struct conversion flags */
185 #define WS_DUP_LINEAR 0x0001
186 #define WS_DUP_SEGPTR 0x0002 /* internal pointers are SEGPTRs */
187 /* by default, internal pointers are linear */
188 typedef struct /* WSAAsyncSelect() control struct */
190 HANDLE service, event, sock;
191 HWND hWnd;
192 UINT uMsg;
193 LONG lEvent;
194 } ws_select_info;
196 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
197 #define WS_MAX_UDP_DATAGRAM 1024
199 #define PROCFS_NETDEV_FILE "/proc/net/dev" /* Points to the file in the /proc fs
200 that lists the network devices.
201 Do we need an #ifdef LINUX for this? */
203 static void *he_buffer; /* typecast for Win16/32 ws_hostent */
204 static SEGPTR he_buffer_seg;
205 static void *se_buffer; /* typecast for Win16/32 ws_servent */
206 static SEGPTR se_buffer_seg;
207 static void *pe_buffer; /* typecast for Win16/32 ws_protoent */
208 static SEGPTR pe_buffer_seg;
209 static char* local_buffer;
210 static SEGPTR dbuffer_seg;
211 static INT num_startup; /* reference counter */
212 static FARPROC blocking_hook;
214 /* function prototypes */
215 static int WS_dup_he(struct hostent* p_he, int flag);
216 static int WS_dup_pe(struct protoent* p_pe, int flag);
217 static int WS_dup_se(struct servent* p_se, int flag);
219 typedef void WIN_hostent;
220 typedef void WIN_protoent;
221 typedef void WIN_servent;
223 int WSAIOCTL_GetInterfaceCount(void);
224 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
226 UINT16 wsaErrno(void);
227 UINT16 wsaHerrno(int errnr);
229 static HANDLE _WSHeap = 0;
231 #define WS_ALLOC(size) \
232 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
233 #define WS_FREE(ptr) \
234 HeapFree(_WSHeap, 0, (ptr) )
236 static INT _ws_sock_ops[] =
237 { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
238 WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
239 WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE,
240 #ifdef SO_RCVTIMEO
241 WS_SO_RCVTIMEO,
242 #endif
243 #ifdef SO_SNDTIMEO
244 WS_SO_SNDTIMEO,
245 #endif
246 0 };
247 static int _px_sock_ops[] =
248 { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
249 SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
250 #ifdef SO_RCVTIMEO
251 SO_RCVTIMEO,
252 #endif
253 #ifdef SO_SNDTIMEO
254 SO_SNDTIMEO,
255 #endif
258 static INT _ws_tcp_ops[] = {
259 #ifdef TCP_NODELAY
260 WS_TCP_NODELAY,
261 #endif
264 static int _px_tcp_ops[] = {
265 #ifdef TCP_NODELAY
266 TCP_NODELAY,
267 #endif
271 static DWORD opentype_tls_index = -1; /* TLS index for SO_OPENTYPE flag */
273 inline static DWORD NtStatusToWSAError ( const DWORD status )
275 /* We only need to cover the status codes set by server async request handling */
276 DWORD wserr;
277 switch ( status )
279 case STATUS_SUCCESS: wserr = 0; break;
280 case STATUS_PENDING: wserr = WSA_IO_PENDING; break;
281 case STATUS_INVALID_HANDLE: wserr = WSAENOTSOCK; break; /* WSAEBADF ? */
282 case STATUS_INVALID_PARAMETER: wserr = WSAEINVAL; break;
283 case STATUS_PIPE_DISCONNECTED: wserr = WSAESHUTDOWN; break;
284 case STATUS_CANCELLED: wserr = WSA_OPERATION_ABORTED; break;
285 case STATUS_TIMEOUT: wserr = WSAETIMEDOUT; break;
286 case STATUS_NO_MEMORY: wserr = WSAEFAULT; break;
287 default:
288 if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
289 /* It is not a NT status code but a winsock error */
290 wserr = status;
291 else
293 wserr = RtlNtStatusToDosError( status );
294 FIXME ( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
297 return wserr;
300 /* set last error code from NT status without mapping WSA errors */
301 inline static unsigned int set_error( unsigned int err )
303 if (err)
305 err = NtStatusToWSAError ( err );
306 SetLastError( err );
308 return err;
311 static char* check_buffer(int size);
313 inline static int _get_sock_fd(SOCKET s)
315 int fd;
317 if (set_error( wine_server_handle_to_fd( s, GENERIC_READ, &fd, NULL, NULL ) )) return -1;
318 return fd;
321 inline static int _get_sock_fd_type( SOCKET s, DWORD access, enum fd_type *type, int *flags )
323 int fd;
324 if (set_error( wine_server_handle_to_fd( s, access, &fd, type, flags ) )) return -1;
325 if ( ( (access & GENERIC_READ) && (*flags & FD_FLAG_RECV_SHUTDOWN ) ) ||
326 ( (access & GENERIC_WRITE) && (*flags & FD_FLAG_SEND_SHUTDOWN ) ) )
328 close (fd);
329 WSASetLastError ( WSAESHUTDOWN );
330 return -1;
332 return fd;
335 static void _enable_event(SOCKET s, unsigned int event,
336 unsigned int sstate, unsigned int cstate)
338 SERVER_START_REQ( enable_socket_event )
340 req->handle = s;
341 req->mask = event;
342 req->sstate = sstate;
343 req->cstate = cstate;
344 wine_server_call( req );
346 SERVER_END_REQ;
349 static int _is_blocking(SOCKET s)
351 int ret;
352 SERVER_START_REQ( get_socket_event )
354 req->handle = s;
355 req->service = FALSE;
356 req->c_event = 0;
357 wine_server_call( req );
358 ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
360 SERVER_END_REQ;
361 return ret;
364 static unsigned int _get_sock_mask(SOCKET s)
366 unsigned int ret;
367 SERVER_START_REQ( get_socket_event )
369 req->handle = s;
370 req->service = FALSE;
371 req->c_event = 0;
372 wine_server_call( req );
373 ret = reply->mask;
375 SERVER_END_REQ;
376 return ret;
379 static void _sync_sock_state(SOCKET s)
381 /* do a dummy wineserver request in order to let
382 the wineserver run through its select loop once */
383 (void)_is_blocking(s);
386 static int _get_sock_error(SOCKET s, unsigned int bit)
388 int events[FD_MAX_EVENTS];
390 SERVER_START_REQ( get_socket_event )
392 req->handle = s;
393 req->service = FALSE;
394 req->c_event = 0;
395 wine_server_set_reply( req, events, sizeof(events) );
396 wine_server_call( req );
398 SERVER_END_REQ;
399 return events[bit];
402 static void WINSOCK_DeleteIData(void)
404 /* delete scratch buffers */
406 UnMapLS( he_buffer_seg );
407 UnMapLS( se_buffer_seg );
408 UnMapLS( pe_buffer_seg );
409 UnMapLS( dbuffer_seg );
410 if (he_buffer) HeapFree( GetProcessHeap(), 0, he_buffer );
411 if (se_buffer) HeapFree( GetProcessHeap(), 0, se_buffer );
412 if (pe_buffer) HeapFree( GetProcessHeap(), 0, pe_buffer );
413 if (local_buffer) HeapFree( GetProcessHeap(), 0, local_buffer );
414 he_buffer = NULL;
415 se_buffer = NULL;
416 pe_buffer = NULL;
417 local_buffer = NULL;
418 he_buffer_seg = 0;
419 se_buffer_seg = 0;
420 pe_buffer_seg = 0;
421 dbuffer_seg = 0;
422 num_startup = 0;
425 /***********************************************************************
426 * WS_LibMain (WS2_32.init)
428 BOOL WINAPI WS_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
430 TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
431 switch (fdwReason) {
432 case DLL_PROCESS_ATTACH:
433 opentype_tls_index = TlsAlloc();
434 break;
435 case DLL_PROCESS_DETACH:
436 TlsFree( opentype_tls_index );
437 WINSOCK_DeleteIData();
438 break;
440 return TRUE;
443 /***********************************************************************
444 * convert_sockopt()
446 * Converts socket flags from Windows format.
447 * Return 1 if converted, 0 if not (error).
449 static int convert_sockopt(INT *level, INT *optname)
451 int i;
452 switch (*level)
454 case WS_SOL_SOCKET:
455 *level = SOL_SOCKET;
456 for(i=0; _ws_sock_ops[i]; i++)
457 if( _ws_sock_ops[i] == *optname ) break;
458 if( _ws_sock_ops[i] ) {
459 *optname = _px_sock_ops[i];
460 return 1;
462 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
463 break;
464 case WS_IPPROTO_TCP:
465 *level = IPPROTO_TCP;
466 for(i=0; _ws_tcp_ops[i]; i++)
467 if ( _ws_tcp_ops[i] == *optname ) break;
468 if( _ws_tcp_ops[i] ) {
469 *optname = _px_tcp_ops[i];
470 return 1;
472 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
473 break;
475 return 0;
478 /* ----------------------------------- Per-thread info (or per-process?) */
480 static int wsi_strtolo(const char* name, const char* opt)
482 /* Stuff a lowercase copy of the string into the local buffer */
484 int i = strlen(name) + 2;
485 char* p = check_buffer(i + ((opt)?strlen(opt):0));
487 if( p )
489 do *p++ = tolower(*name); while(*name++);
490 i = (p - local_buffer);
491 if( opt ) do *p++ = tolower(*opt); while(*opt++);
492 return i;
494 return 0;
497 static fd_set* fd_set_import( fd_set* fds, void* wsfds, int* highfd, int lfd[], BOOL b32 )
499 /* translate Winsock fd set into local fd set */
501 if( wsfds )
503 #define wsfds16 ((ws_fd_set16*)wsfds)
504 #define wsfds32 ((WS_fd_set*)wsfds)
505 int i, count;
507 FD_ZERO(fds);
508 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
510 for( i = 0; i < count; i++ )
512 int s = (b32) ? wsfds32->fd_array[i]
513 : wsfds16->fd_array[i];
514 int fd = _get_sock_fd(s);
515 if (fd != -1)
517 lfd[ i ] = fd;
518 if( fd > *highfd ) *highfd = fd;
519 FD_SET(fd, fds);
521 else lfd[ i ] = -1;
523 #undef wsfds32
524 #undef wsfds16
525 return fds;
527 return NULL;
530 inline static int sock_error_p(int s)
532 unsigned int optval, optlen;
534 optlen = sizeof(optval);
535 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
536 if (optval) WARN("\t[%i] error: %d\n", s, optval);
537 return optval != 0;
540 static int fd_set_export( fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
542 int num_err = 0;
544 /* translate local fd set into Winsock fd set, adding
545 * errors to exceptfds (only if app requested it) */
547 if( wsfds )
549 #define wsfds16 ((ws_fd_set16*)wsfds)
550 #define wsfds32 ((WS_fd_set*)wsfds)
551 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
553 for( i = 0, j = 0; i < count; i++ )
555 if( lfd[i] >= 0 )
557 int fd = lfd[i];
558 if( FD_ISSET(fd, fds) )
560 if ( exceptfds && sock_error_p(fd) )
562 FD_SET(fd, exceptfds);
563 num_err++;
565 else if( b32 )
566 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
567 else
568 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
570 close(fd);
571 lfd[i] = -1;
575 if( b32 ) wsfds32->fd_count = j;
576 else wsfds16->fd_count = j;
578 TRACE("\n");
579 #undef wsfds32
580 #undef wsfds16
582 return num_err;
585 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
587 if ( wsfds )
589 #define wsfds16 ((ws_fd_set16*)wsfds)
590 #define wsfds32 ((WS_fd_set*)wsfds)
591 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
593 for( i = 0; i < count; i++ )
594 if ( lfd[i] >= 0 )
595 close(lfd[i]);
597 TRACE("\n");
598 #undef wsfds32
599 #undef wsfds16
603 static int do_block( int fd, int mask )
605 fd_set fds[3];
606 int i, r;
608 FD_ZERO(&fds[0]);
609 FD_ZERO(&fds[1]);
610 FD_ZERO(&fds[2]);
611 for (i=0; i<3; i++)
612 if (mask & (1<<i))
613 FD_SET(fd, &fds[i]);
614 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
615 if (i <= 0) return -1;
616 r = 0;
617 for (i=0; i<3; i++)
618 if (FD_ISSET(fd, &fds[i]))
619 r |= 1<<i;
620 return r;
623 void* __ws_memalloc( int size )
625 return WS_ALLOC(size);
628 void __ws_memfree(void* ptr)
630 WS_FREE(ptr);
634 /* ----------------------------------- API -----
636 * Init / cleanup / error checking.
639 /***********************************************************************
640 * WSAStartup (WINSOCK.115)
642 * Create socket control struct, attach it to the global list and
643 * update a pointer in the task struct.
645 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA16 lpWSAData)
647 static const WSADATA16 data =
649 0x0101, 0x0101,
650 "WINE Sockets 1.1",
651 #ifdef linux
652 "Linux/i386",
653 #elif defined(__NetBSD__)
654 "NetBSD/i386",
655 #elif defined(sunos)
656 "SunOS",
657 #elif defined(__FreeBSD__)
658 "FreeBSD",
659 #elif defined(__OpenBSD__)
660 "OpenBSD/i386",
661 #else
662 "Unknown",
663 #endif
664 WS_MAX_SOCKETS_PER_PROCESS,
665 WS_MAX_UDP_DATAGRAM,
669 TRACE("verReq=%x\n", wVersionRequested);
671 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
672 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
674 if (!lpWSAData) return WSAEINVAL;
676 /* initialize socket heap */
678 if( !_WSHeap )
680 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
681 if( !_WSHeap )
683 ERR("Fatal: failed to create WinSock heap\n");
684 return 0;
687 if( _WSHeap == 0 ) return WSASYSNOTREADY;
689 num_startup++;
691 /* return winsock information */
693 memcpy(lpWSAData, &data, sizeof(data));
695 TRACE("succeeded\n");
696 return 0;
699 /***********************************************************************
700 * WSAStartup (WS2_32.115)
702 int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
704 TRACE("verReq=%x\n", wVersionRequested);
706 if (LOBYTE(wVersionRequested) < 1)
707 return WSAVERNOTSUPPORTED;
709 if (!lpWSAData) return WSAEINVAL;
711 /* initialize socket heap */
713 if( !_WSHeap )
715 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
716 if( !_WSHeap )
718 ERR("Fatal: failed to create WinSock heap\n");
719 return 0;
722 if( _WSHeap == 0 ) return WSASYSNOTREADY;
724 num_startup++;
726 /* that's the whole of the negotiation for now */
727 lpWSAData->wVersion = wVersionRequested;
728 /* return winsock information */
729 lpWSAData->wHighVersion = 0x0202;
730 strcpy(lpWSAData->szDescription, "WinSock 2.0" );
731 strcpy(lpWSAData->szSystemStatus, "Running" );
732 lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
733 lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
734 /* don't do anything with lpWSAData->lpVendorInfo */
735 /* (some apps don't allocate the space for this field) */
737 TRACE("succeeded\n");
738 return 0;
742 /***********************************************************************
743 * WSACleanup (WINSOCK.116)
744 * WSACleanup (WS2_32.116)
746 INT WINAPI WSACleanup(void)
748 if (num_startup)
750 if (--num_startup > 0) return 0;
751 WINSOCK_DeleteIData();
752 return 0;
754 SetLastError(WSANOTINITIALISED);
755 return SOCKET_ERROR;
759 /***********************************************************************
760 * WSAGetLastError (WINSOCK.111)
761 * WSAGetLastError (WS2_32.111)
763 INT WINAPI WSAGetLastError(void)
765 return GetLastError();
768 /***********************************************************************
769 * WSASetLastError (WS2_32.112)
771 void WINAPI WSASetLastError(INT iError) {
772 SetLastError(iError);
775 /***********************************************************************
776 * WSASetLastError (WINSOCK.112)
778 void WINAPI WSASetLastError16(INT16 iError)
780 WSASetLastError(iError);
783 static char* check_buffer(int size)
785 static int local_buflen;
787 if (local_buffer)
789 if (local_buflen >= size ) return local_buffer;
790 HeapFree( GetProcessHeap(), 0, local_buffer );
792 local_buffer = HeapAlloc( GetProcessHeap(), 0, (local_buflen = size) );
793 return local_buffer;
796 static struct ws_hostent* check_buffer_he(int size)
798 static int he_len;
799 if (he_buffer)
801 if (he_len >= size ) return he_buffer;
802 UnMapLS( he_buffer_seg );
803 HeapFree( GetProcessHeap(), 0, he_buffer );
805 he_buffer = HeapAlloc( GetProcessHeap(), 0, (he_len = size) );
806 he_buffer_seg = MapLS( he_buffer );
807 return he_buffer;
810 static void* check_buffer_se(int size)
812 static int se_len;
813 if (se_buffer)
815 if (se_len >= size ) return se_buffer;
816 UnMapLS( se_buffer_seg );
817 HeapFree( GetProcessHeap(), 0, se_buffer );
819 se_buffer = HeapAlloc( GetProcessHeap(), 0, (se_len = size) );
820 se_buffer_seg = MapLS( se_buffer );
821 return se_buffer;
824 static struct ws_protoent* check_buffer_pe(int size)
826 static int pe_len;
827 if (pe_buffer)
829 if (pe_len >= size ) return pe_buffer;
830 UnMapLS( pe_buffer_seg );
831 HeapFree( GetProcessHeap(), 0, pe_buffer );
833 pe_buffer = HeapAlloc( GetProcessHeap(), 0, (pe_len = size) );
834 pe_buffer_seg = MapLS( he_buffer );
835 return pe_buffer;
838 /* ----------------------------------- i/o APIs */
840 #ifdef HAVE_IPX
841 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
842 #else
843 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
844 #endif
847 /**********************************************************************/
849 /* Returns the converted address if successful, NULL if it was too small to
850 * start with. Note that the returned pointer may be the original pointer
851 * if no conversion is necessary.
853 static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
855 switch (wsaddr->sa_family)
857 #ifdef HAVE_IPX
858 case WS_AF_IPX:
860 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
861 struct sockaddr_ipx* uipx;
863 if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
864 return NULL;
866 *uaddrlen=sizeof(struct sockaddr_ipx);
867 uipx=malloc(*uaddrlen);
868 uipx->sipx_family=AF_IPX;
869 uipx->sipx_port=wsipx->sa_socket;
870 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
871 * in one go
873 memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
874 uipx->sipx_type=IPX_FRAME_NONE;
875 uipx->sipx_zero=0;
876 return (const struct sockaddr*)uipx;
878 #endif
880 default:
881 if (wsaddrlen<sizeof(struct WS_sockaddr))
882 return NULL;
884 /* No conversion needed, just return the original address */
885 *uaddrlen=wsaddrlen;
886 return (const struct sockaddr*)wsaddr;
888 return NULL;
891 /* Allocates a Unix sockaddr structure to receive the data */
892 inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
894 if (wsaddr==NULL)
896 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
898 /* This is not strictly the right thing to do. Hope it works however */
899 *uaddrlen=0;
901 return NULL;
904 if (*wsaddrlen==0)
905 *uaddrlen=0;
906 else
907 *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
909 return malloc(*uaddrlen);
912 /* Returns 0 if successful, -1 if the buffer is too small */
913 static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
915 int res;
917 switch(uaddr->sa_family)
919 #ifdef HAVE_IPX
920 case AF_IPX:
922 struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
923 struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
925 res=-1;
926 switch (*wsaddrlen) /* how much can we copy? */
928 default:
929 res=0; /* enough */
930 *wsaddrlen=uaddrlen;
931 wsipx->sa_socket=uipx->sipx_port;
932 /* fall through */
933 case 13:
934 case 12:
935 memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
936 /* fall through */
937 case 11:
938 case 10:
939 case 9:
940 case 8:
941 case 7:
942 case 6:
943 memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
944 /* fall through */
945 case 5:
946 case 4:
947 case 3:
948 case 2:
949 wsipx->sa_family=WS_AF_IPX;
950 /* fall through */
951 case 1:
952 case 0:
953 /* way too small */
954 break;
957 break;
958 #endif
960 default:
961 /* No conversion needed */
962 memcpy(wsaddr,uaddr,*wsaddrlen);
963 if (*wsaddrlen<uaddrlen) {
964 res=-1;
965 } else {
966 *wsaddrlen=uaddrlen;
967 res=0;
970 return res;
973 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
974 * ws_sockaddr_alloc
976 inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
978 if (uaddr!=NULL && uaddr!=(const struct sockaddr*)wsaddr)
979 free((void*)uaddr);
982 /**************************************************************************
983 * Functions for handling overlapped I/O
984 **************************************************************************/
986 static DWORD ws2_async_get_status (const struct async_private *ovp)
988 return ((ws2_async*) ovp)->overlapped->Internal;
991 static VOID ws2_async_set_status (struct async_private *ovp, const DWORD status)
993 ((ws2_async*) ovp)->overlapped->Internal = status;
996 static DWORD ws2_async_get_count (const struct async_private *ovp)
998 return ((ws2_async*) ovp)->overlapped->InternalHigh;
1001 static void ws2_async_cleanup ( struct async_private *ap )
1003 struct ws2_async *as = (struct ws2_async*) ap;
1005 TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->overlapped );
1006 if ( !as->user_overlapped )
1008 if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
1009 WSACloseEvent ( as->overlapped->hEvent );
1010 HeapFree ( GetProcessHeap(), 0, as->overlapped );
1013 if ( as->iovec )
1014 HeapFree ( GetProcessHeap(), 0, as->iovec );
1016 HeapFree ( GetProcessHeap(), 0, as );
1019 static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
1021 ws2_async* as = (ws2_async*) data;
1023 TRACE ("data: %p\n", as);
1025 as->completion_func ( NtStatusToWSAError (as->overlapped->Internal),
1026 as->overlapped->InternalHigh,
1027 as->user_overlapped,
1028 as->flags );
1029 ws2_async_cleanup ( &as->async );
1032 /***********************************************************************
1033 * WS2_make_async (INTERNAL)
1036 static void WS2_async_recv (async_private *as);
1037 static void WS2_async_send (async_private *as);
1039 inline static struct ws2_async*
1040 WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferCount,
1041 LPDWORD lpFlags, struct WS_sockaddr *addr,
1042 LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
1043 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1045 struct ws2_async *wsa = HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async ) );
1047 TRACE ( "wsa %p\n", wsa );
1049 if (!wsa)
1050 return NULL;
1052 wsa->async.ops = ( lpCompletionRoutine ? &ws2_async_ops : &ws2_nocomp_async_ops );
1053 wsa->async.handle = (HANDLE) s;
1054 wsa->async.fd = fd;
1055 wsa->async.type = type;
1056 switch (type)
1058 case ASYNC_TYPE_READ:
1059 wsa->flags = *lpFlags;
1060 wsa->async.func = WS2_async_recv;
1061 wsa->addrlen.ptr = addrlen;
1062 break;
1063 case ASYNC_TYPE_WRITE:
1064 wsa->flags = 0;
1065 wsa->async.func = WS2_async_send;
1066 wsa->addrlen.val = *addrlen;
1067 break;
1068 default:
1069 ERR ("Invalid async type: %d\n", type);
1071 wsa->user_overlapped = lpOverlapped;
1072 wsa->completion_func = lpCompletionRoutine;
1073 wsa->iovec = iovec;
1074 wsa->n_iovecs = dwBufferCount;
1075 wsa->addr = addr;
1077 if ( lpOverlapped )
1079 wsa->overlapped = lpOverlapped;
1080 wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
1082 else
1084 wsa->overlapped = HeapAlloc ( GetProcessHeap(), 0,
1085 sizeof (WSAOVERLAPPED) );
1086 if ( !wsa->overlapped )
1087 goto error;
1088 wsa->async.event = wsa->overlapped->hEvent = INVALID_HANDLE_VALUE;
1091 wsa->overlapped->InternalHigh = 0;
1092 TRACE ( "wsa %p, ops %p, h %d, ev %d, fd %d, func %p, ov %p, uov %p, cfunc %p\n",
1093 wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
1094 wsa->overlapped, wsa->user_overlapped, wsa->completion_func );
1096 return wsa;
1098 error:
1099 TRACE ("Error\n");
1100 HeapFree ( GetProcessHeap(), 0, wsa );
1101 return NULL;
1104 /***********************************************************************
1105 * WS2_recv (INTERNAL)
1107 * Work horse for both synchronous and asynchronous recv() operations.
1109 static int WS2_recv ( int fd, struct iovec* iov, int count,
1110 struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1111 LPDWORD lpFlags )
1113 struct msghdr hdr;
1114 int n;
1115 TRACE ( "fd %d, iovec %p, count %d addr %p, len %p, flags %lx\n",
1116 fd, iov, count, lpFrom, lpFromlen, *lpFlags);
1118 hdr.msg_name = NULL;
1120 if ( lpFrom )
1122 #if DEBUG_SOCKADDR
1123 dump_sockaddr (lpFrom);
1124 #endif
1126 hdr.msg_namelen = *lpFromlen;
1127 hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
1128 if ( !hdr.msg_name )
1130 WSASetLastError ( WSAEFAULT );
1131 n = -1;
1132 goto out;
1135 else
1136 hdr.msg_namelen = 0;
1138 hdr.msg_iov = iov;
1139 hdr.msg_iovlen = count;
1140 #ifdef HAVE_MSGHDR_ACCRIGHTS
1141 hdr.msg_accrights = NULL;
1142 hdr.msg_accrightslen = 0;
1143 #else
1144 hdr.msg_control = NULL;
1145 hdr.msg_controllen = 0;
1146 hdr.msg_flags = 0;
1147 #endif
1149 if ( (n = recvmsg (fd, &hdr, *lpFlags)) == -1 )
1151 TRACE ( "recvmsg error %d\n", errno);
1152 goto out;
1155 if ( lpFrom &&
1156 ws_sockaddr_u2ws ( hdr.msg_name, hdr.msg_namelen,
1157 lpFrom, lpFromlen ) != 0 )
1159 /* The from buffer was too small, but we read the data
1160 * anyway. Is that really bad?
1162 WSASetLastError ( WSAEFAULT );
1163 WARN ( "Address buffer too small\n" );
1166 out:
1168 ws_sockaddr_free ( hdr.msg_name, lpFrom );
1169 TRACE ("-> %d\n", n);
1170 return n;
1173 /***********************************************************************
1174 * WS2_async_recv (INTERNAL)
1176 * Handler for overlapped recv() operations.
1178 static void WS2_async_recv ( async_private *as )
1180 ws2_async* wsa = (ws2_async*) as;
1181 int result, err;
1183 TRACE ( "async %p\n", wsa );
1185 if ( wsa->overlapped->Internal != STATUS_PENDING )
1187 TRACE ( "status: %ld\n", wsa->overlapped->Internal );
1188 return;
1191 result = WS2_recv ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1192 wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1194 if (result >= 0)
1196 wsa->overlapped->Internal = STATUS_SUCCESS;
1197 wsa->overlapped->InternalHigh = result;
1198 TRACE ( "received %d bytes\n", result );
1199 _enable_event ( (SOCKET) wsa->async.handle, FD_READ, 0, 0 );
1200 return;
1203 err = wsaErrno ();
1204 if ( err == WSAEINTR || err == WSAEWOULDBLOCK ) /* errno: EINTR / EAGAIN */
1206 wsa->overlapped->Internal = STATUS_PENDING;
1207 _enable_event ( (SOCKET) wsa->async.handle, FD_READ, 0, 0 );
1208 TRACE ( "still pending\n" );
1210 else
1212 wsa->overlapped->Internal = err;
1213 TRACE ( "Error: %x\n", err );
1217 /***********************************************************************
1218 * WS2_send (INTERNAL)
1220 * Work horse for both synchronous and asynchronous send() operations.
1222 static int WS2_send ( int fd, struct iovec* iov, int count,
1223 const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1225 struct msghdr hdr;
1226 int n = -1;
1227 TRACE ( "fd %d, iovec %p, count %d addr %p, len %d, flags %lx\n",
1228 fd, iov, count, to, tolen, dwFlags);
1230 hdr.msg_name = NULL;
1232 if ( to )
1234 #if DEBUG_SOCKADDR
1235 dump_sockaddr (to);
1236 #endif
1237 hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
1238 if ( !hdr.msg_name )
1240 WSASetLastError ( WSAEFAULT );
1241 goto out;
1244 else
1245 hdr.msg_namelen = 0;
1247 hdr.msg_iov = iov;
1248 hdr.msg_iovlen = count;
1249 #ifdef HAVE_MSGHDR_ACCRIGHTS
1250 hdr.msg_accrights = NULL;
1251 hdr.msg_accrightslen = 0;
1252 #else
1253 hdr.msg_control = NULL;
1254 hdr.msg_controllen = 0;
1255 hdr.msg_flags = 0;
1256 #endif
1258 n = sendmsg (fd, &hdr, dwFlags);
1260 out:
1261 ws_sockaddr_free ( hdr.msg_name, to );
1262 return n;
1265 /***********************************************************************
1266 * WS2_async_send (INTERNAL)
1268 * Handler for overlapped send() operations.
1270 static void WS2_async_send ( async_private *as )
1272 ws2_async* wsa = (ws2_async*) as;
1273 int result, err;
1275 TRACE ( "async %p\n", wsa );
1277 if ( wsa->overlapped->Internal != STATUS_PENDING )
1279 TRACE ( "status: %ld\n", wsa->overlapped->Internal );
1280 return;
1283 result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
1284 wsa->addr, wsa->addrlen.val, wsa->flags );
1286 if (result >= 0)
1288 wsa->overlapped->Internal = STATUS_SUCCESS;
1289 wsa->overlapped->InternalHigh = result;
1290 TRACE ( "sent %d bytes\n", result );
1291 _enable_event ( (SOCKET) wsa->async.handle, FD_WRITE, 0, 0 );
1292 return;
1295 err = wsaErrno ();
1296 if ( err == WSAEINTR )
1298 wsa->overlapped->Internal = STATUS_PENDING;
1299 _enable_event ( (SOCKET) wsa->async.handle, FD_WRITE, 0, 0 );
1300 TRACE ( "still pending\n" );
1302 else
1304 /* We set the status to a winsock error code and check for that
1305 later in NtStatusToWSAError () */
1306 wsa->overlapped->Internal = err;
1307 TRACE ( "Error: %x\n", err );
1311 /***********************************************************************
1312 * WS2_async_shutdown (INTERNAL)
1314 * Handler for shutdown() operations on overlapped sockets.
1316 static void WS2_async_shutdown ( async_private *as )
1318 ws2_async* wsa = (ws2_async*) as;
1319 int err = 1;
1321 TRACE ( "async %p %d\n", wsa, wsa->async.type );
1322 switch ( wsa->async.type )
1324 case ASYNC_TYPE_READ:
1325 err = shutdown ( wsa->async.fd, 0 );
1326 break;
1327 case ASYNC_TYPE_WRITE:
1328 err = shutdown ( wsa->async.fd, 1 );
1329 break;
1330 default:
1331 ERR ("invalid type: %d\n", wsa->async.type );
1334 if ( err )
1335 wsa->overlapped->Internal = wsaErrno ();
1336 else
1337 wsa->overlapped->Internal = STATUS_SUCCESS;
1340 /***********************************************************************
1341 * WS2_register_async_shutdown (INTERNAL)
1343 * Helper function for WS_shutdown() on overlapped sockets.
1345 static int WS2_register_async_shutdown ( SOCKET s, int fd, int type )
1347 struct ws2_async *wsa;
1348 int ret, err = WSAEFAULT;
1349 DWORD dwflags = 0;
1350 int len = 0;
1351 LPWSAOVERLAPPED ovl = HeapAlloc (GetProcessHeap(), 0, sizeof ( WSAOVERLAPPED ));
1353 TRACE ("s %d fd %d type %d\n", s, fd, type);
1354 if (!ovl)
1355 goto out;
1357 ovl->hEvent = WSACreateEvent ();
1358 if ( ovl->hEvent == WSA_INVALID_EVENT )
1359 goto out_free;
1361 wsa = WS2_make_async ( s, fd, type, NULL, 0,
1362 &dwflags, NULL, &len, ovl, NULL );
1363 if ( !wsa )
1364 goto out_close;
1366 /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
1367 wsa->user_overlapped = NULL;
1368 wsa->async.func = WS2_async_shutdown;
1369 if ( (ret = register_new_async ( &wsa->async )) )
1371 err = NtStatusToWSAError ( ret );
1372 ws2_async_cleanup ( &wsa->async );
1373 goto out;
1375 /* Try immediate completion */
1376 if ( WSAGetOverlappedResult ( (HANDLE) s, ovl, NULL, FALSE, NULL ) )
1377 return 0;
1378 if ( (err = WSAGetLastError ()) == WSA_IO_INCOMPLETE )
1379 return 0;
1380 return WSAEINVAL;
1382 out_close:
1383 WSACloseEvent ( ovl->hEvent );
1384 out_free:
1385 HeapFree ( GetProcessHeap(), 0, ovl );
1386 out:
1387 return err;
1390 /***********************************************************************
1391 * accept (WS2_32.1)
1393 SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1394 int *addrlen32)
1396 int fd = _get_sock_fd(s);
1398 TRACE("socket %04x\n", (UINT16)s );
1399 if (fd != -1)
1401 SOCKET as;
1402 if (_is_blocking(s))
1404 /* block here */
1405 do_block(fd, 5);
1406 _sync_sock_state(s); /* let wineserver notice connection */
1407 /* retrieve any error codes from it */
1408 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1409 /* FIXME: care about the error? */
1411 close(fd);
1412 SERVER_START_REQ( accept_socket )
1414 req->lhandle = s;
1415 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1416 req->inherit = TRUE;
1417 set_error( wine_server_call( req ) );
1418 as = (SOCKET)reply->handle;
1420 SERVER_END_REQ;
1421 if (as)
1423 if (addr)
1424 WS_getpeername(as, addr, addrlen32);
1425 return as;
1428 else
1430 SetLastError(WSAENOTSOCK);
1432 return INVALID_SOCKET;
1435 /***********************************************************************
1436 * accept (WINSOCK.1)
1438 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct WS_sockaddr* addr,
1439 INT16* addrlen16 )
1441 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
1442 SOCKET retSocket = WS_accept( s, addr, &addrlen32 );
1443 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
1444 return (SOCKET16)retSocket;
1447 /***********************************************************************
1448 * bind (WS2_32.2)
1450 int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1452 int fd = _get_sock_fd(s);
1453 int res;
1455 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
1456 #if DEBUG_SOCKADDR
1457 dump_sockaddr(name);
1458 #endif
1460 res=SOCKET_ERROR;
1461 if (fd != -1)
1463 if (!name || !SUPPORTED_PF(name->sa_family))
1465 SetLastError(WSAEAFNOSUPPORT);
1467 else
1469 const struct sockaddr* uaddr;
1470 int uaddrlen;
1472 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1473 if (uaddr == NULL)
1475 SetLastError(WSAEFAULT);
1477 else
1479 if (bind(fd, uaddr, uaddrlen) < 0)
1481 int loc_errno = errno;
1482 WARN("\tfailure - errno = %i\n", errno);
1483 errno = loc_errno;
1484 switch (errno)
1486 case EBADF:
1487 SetLastError(WSAENOTSOCK);
1488 break;
1489 case EADDRNOTAVAIL:
1490 SetLastError(WSAEINVAL);
1491 break;
1492 default:
1493 SetLastError(wsaErrno());
1494 break;
1497 else
1499 res=0; /* success */
1501 ws_sockaddr_free(uaddr,name);
1504 close(fd);
1506 else
1508 SetLastError(WSAENOTSOCK);
1510 return res;
1513 /***********************************************************************
1514 * bind (WINSOCK.2)
1516 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1518 return (INT16)WS_bind( s, name, namelen );
1521 /***********************************************************************
1522 * closesocket (WS2_32.3)
1524 int WINAPI WS_closesocket(SOCKET s)
1526 TRACE("socket %08x\n", s);
1527 if (CloseHandle(s)) return 0;
1528 return SOCKET_ERROR;
1531 /***********************************************************************
1532 * closesocket (WINSOCK.3)
1534 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
1536 return (INT16)WS_closesocket(s);
1539 /***********************************************************************
1540 * connect (WS2_32.4)
1542 int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1544 int fd = _get_sock_fd(s);
1546 TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
1547 #if DEBUG_SOCKADDR
1548 dump_sockaddr(name);
1549 #endif
1551 if (fd != -1)
1553 const struct sockaddr* uaddr;
1554 int uaddrlen;
1556 uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1557 if (uaddr == NULL)
1559 SetLastError(WSAEFAULT);
1561 else
1563 int rc;
1565 rc=connect(fd, uaddr, uaddrlen);
1566 ws_sockaddr_free(uaddr,name);
1567 if (rc == 0)
1568 goto connect_success;
1571 if (errno == EINPROGRESS)
1573 /* tell wineserver that a connection is in progress */
1574 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1575 FD_CONNECT|FD_READ|FD_WRITE,
1576 FD_WINE_CONNECTED|FD_WINE_LISTENING);
1577 if (_is_blocking(s))
1579 int result;
1580 /* block here */
1581 do_block(fd, 7);
1582 _sync_sock_state(s); /* let wineserver notice connection */
1583 /* retrieve any error codes from it */
1584 result = _get_sock_error(s, FD_CONNECT_BIT);
1585 if (result)
1586 SetLastError(result);
1587 else
1589 goto connect_success;
1592 else
1594 SetLastError(WSAEWOULDBLOCK);
1597 else
1599 SetLastError(wsaErrno());
1601 close(fd);
1603 else
1605 SetLastError(WSAENOTSOCK);
1607 return SOCKET_ERROR;
1609 connect_success:
1610 close(fd);
1611 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1612 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1613 FD_CONNECT|FD_WINE_LISTENING);
1614 return 0;
1617 /***********************************************************************
1618 * connect (WINSOCK.4)
1620 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
1622 return (INT16)WS_connect( s, name, namelen );
1625 /***********************************************************************
1626 * WSAConnect (WS2_32.30)
1628 int WINAPI WSAConnect ( SOCKET s, const struct WS_sockaddr* name, int namelen,
1629 LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1630 LPQOS lpSQOS, LPQOS lpGQOS )
1632 if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1633 FIXME ("unsupported parameters!\n");
1634 return WS_connect ( s, name, namelen );
1638 /***********************************************************************
1639 * getpeername (WS2_32.5)
1641 int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1643 int fd;
1644 int res;
1646 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1648 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1649 if( (name == NULL) || (namelen == NULL) )
1651 SetLastError( WSAEFAULT );
1652 return SOCKET_ERROR;
1655 fd = _get_sock_fd(s);
1656 res = SOCKET_ERROR;
1658 if (fd != -1)
1660 struct sockaddr* uaddr;
1661 int uaddrlen;
1663 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1664 if (getpeername(fd, uaddr, &uaddrlen) != 0)
1666 SetLastError(wsaErrno());
1668 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1670 /* The buffer was too small */
1671 SetLastError(WSAEFAULT);
1673 else
1675 res=0;
1677 ws_sockaddr_free(uaddr,name);
1678 close(fd);
1680 else
1682 SetLastError(WSAENOTSOCK);
1684 return res;
1687 /***********************************************************************
1688 * getpeername (WINSOCK.5)
1690 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct WS_sockaddr *name,
1691 INT16 *namelen16)
1693 INT namelen32 = *namelen16;
1694 INT retVal = WS_getpeername( s, name, &namelen32 );
1696 #if DEBUG_SOCKADDR
1697 dump_sockaddr(name);
1698 #endif
1700 *namelen16 = namelen32;
1701 return (INT16)retVal;
1704 /***********************************************************************
1705 * getsockname (WS2_32.6)
1707 int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1709 int fd;
1710 int res;
1712 TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1714 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1715 if( (name == NULL) || (namelen == NULL) )
1717 SetLastError( WSAEFAULT );
1718 return SOCKET_ERROR;
1721 fd = _get_sock_fd(s);
1722 res = SOCKET_ERROR;
1724 if (fd != -1)
1726 struct sockaddr* uaddr;
1727 int uaddrlen;
1729 uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1730 if (getsockname(fd, uaddr, &uaddrlen) != 0)
1732 SetLastError(wsaErrno());
1734 else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1736 /* The buffer was too small */
1737 SetLastError(WSAEFAULT);
1739 else
1741 res=0;
1743 close(fd);
1745 else
1747 SetLastError(WSAENOTSOCK);
1749 return res;
1752 /***********************************************************************
1753 * getsockname (WINSOCK.6)
1755 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct WS_sockaddr *name,
1756 INT16 *namelen16)
1758 INT retVal;
1760 if( namelen16 )
1762 INT namelen32 = *namelen16;
1763 retVal = WS_getsockname( s, name, &namelen32 );
1764 *namelen16 = namelen32;
1766 #if DEBUG_SOCKADDR
1767 dump_sockaddr(name);
1768 #endif
1771 else retVal = SOCKET_ERROR;
1772 return (INT16)retVal;
1776 /***********************************************************************
1777 * getsockopt (WS2_32.7)
1779 INT WINAPI WS_getsockopt(SOCKET s, INT level,
1780 INT optname, char *optval, INT *optlen)
1782 int fd;
1784 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1785 (int) optname, (int) optval, (int) *optlen);
1786 /* SO_OPENTYPE does not require a valid socket handle. */
1787 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1789 if (!optlen || *optlen < sizeof(int) || !optval)
1791 SetLastError(WSAEFAULT);
1792 return SOCKET_ERROR;
1794 *(int *)optval = (int)TlsGetValue( opentype_tls_index );
1795 *optlen = sizeof(int);
1796 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1797 return 0;
1800 fd = _get_sock_fd(s);
1801 if (fd != -1)
1803 if (!convert_sockopt(&level, &optname)) {
1804 SetLastError(WSAENOPROTOOPT); /* Unknown option */
1805 } else {
1806 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1808 close(fd);
1809 return 0;
1811 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1813 close(fd);
1815 return SOCKET_ERROR;
1819 /***********************************************************************
1820 * getsockopt (WINSOCK.7)
1822 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1823 INT16 optname, char *optval, INT16 *optlen)
1825 INT optlen32;
1826 INT *p = &optlen32;
1827 INT retVal;
1828 if( optlen ) optlen32 = *optlen; else p = NULL;
1829 retVal = WS_getsockopt( s, (UINT16)level, optname, optval, p );
1830 if( optlen ) *optlen = optlen32;
1831 return (INT16)retVal;
1835 /***********************************************************************
1836 * htonl (WINSOCK.8)
1837 * htonl (WS2_32.8)
1839 u_long WINAPI WS_htonl(u_long hostlong)
1841 return htonl(hostlong);
1845 /***********************************************************************
1846 * htons (WINSOCK.9)
1847 * htons (WS2_32.9)
1849 u_short WINAPI WS_htons(u_short hostshort)
1851 return htons(hostshort);
1855 /***********************************************************************
1856 * inet_addr (WINSOCK.10)
1857 * inet_addr (WS2_32.11)
1859 u_long WINAPI WS_inet_addr(const char *cp)
1861 return inet_addr(cp);
1865 /***********************************************************************
1866 * ntohl (WINSOCK.14)
1867 * ntohl (WS2_32.14)
1869 u_long WINAPI WS_ntohl(u_long netlong)
1871 return ntohl(netlong);
1875 /***********************************************************************
1876 * ntohs (WINSOCK.15)
1877 * ntohs (WS2_32.15)
1879 u_short WINAPI WS_ntohs(u_short netshort)
1881 return ntohs(netshort);
1885 /***********************************************************************
1886 * inet_ntoa (WS2_32.12)
1888 char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1890 /* use "buffer for dummies" here because some applications have
1891 * propensity to decode addresses in ws_hostent structure without
1892 * saving them first...
1894 static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1896 char* s = inet_ntoa(*((struct in_addr*)&in));
1897 if( s )
1899 strcpy(dbuffer, s);
1900 return dbuffer;
1902 SetLastError(wsaErrno());
1903 return NULL;
1906 /***********************************************************************
1907 * inet_ntoa (WINSOCK.11)
1909 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1911 char* retVal;
1912 if (!(retVal = WS_inet_ntoa(*((struct WS_in_addr*)&in)))) return 0;
1913 if (!dbuffer_seg) dbuffer_seg = MapLS( retVal );
1914 return dbuffer_seg;
1918 /**********************************************************************
1919 * WSAIoctl (WS2_32.50)
1922 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1924 INT WINAPI WSAIoctl (SOCKET s,
1925 DWORD dwIoControlCode,
1926 LPVOID lpvInBuffer,
1927 DWORD cbInBuffer,
1928 LPVOID lpbOutBuffer,
1929 DWORD cbOutBuffer,
1930 LPDWORD lpcbBytesReturned,
1931 LPWSAOVERLAPPED lpOverlapped,
1932 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1934 int fd = _get_sock_fd(s);
1936 if (fd != -1)
1938 switch( dwIoControlCode )
1940 case SIO_GET_INTERFACE_LIST:
1942 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1943 int i, numInt;
1944 struct ifreq ifInfo;
1945 char ifName[512];
1948 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1950 numInt = WSAIOCTL_GetInterfaceCount();
1951 if (numInt < 0)
1953 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1954 close(fd);
1955 WSASetLastError(WSAEINVAL);
1956 return (SOCKET_ERROR);
1959 for (i=0; i<numInt; i++)
1961 if (!WSAIOCTL_GetInterfaceName(i, ifName))
1963 ERR ("Error parsing /proc filesystem!\n");
1964 close(fd);
1965 WSASetLastError(WSAEINVAL);
1966 return (SOCKET_ERROR);
1969 ifInfo.ifr_addr.sa_family = AF_INET;
1971 /* IP Address */
1972 strcpy (ifInfo.ifr_name, ifName);
1973 if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
1975 ERR ("Error obtaining IP address\n");
1976 close(fd);
1977 WSASetLastError(WSAEINVAL);
1978 return (SOCKET_ERROR);
1980 else
1982 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_addr;
1984 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1985 intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1986 intArray->iiAddress.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
1989 /* Broadcast Address */
1990 strcpy (ifInfo.ifr_name, ifName);
1991 if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1993 ERR ("Error obtaining Broadcast IP address\n");
1994 close(fd);
1995 WSASetLastError(WSAEINVAL);
1996 return (SOCKET_ERROR);
1998 else
2000 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_broadaddr;
2002 intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
2003 intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
2004 intArray->iiBroadcastAddress.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
2007 /* Subnet Mask */
2008 strcpy (ifInfo.ifr_name, ifName);
2009 if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
2011 ERR ("Error obtaining Subnet IP address\n");
2012 close(fd);
2013 WSASetLastError(WSAEINVAL);
2014 return (SOCKET_ERROR);
2016 else
2018 /* Trying to avoid some compile problems across platforms.
2019 (Linux, FreeBSD, Solaris...) */
2020 #ifndef ifr_netmask
2021 #ifndef ifr_addr
2022 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2023 intArray->iiNetmask.AddressIn.sin_port = 0;
2024 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = 0;
2025 ERR ("Unable to determine Netmask on your platform!\n");
2026 #else
2027 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_addr;
2029 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2030 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
2031 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
2032 #endif
2033 #else
2034 struct WS_sockaddr_in *ipTemp = (struct WS_sockaddr_in *)&ifInfo.ifr_netmask;
2036 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2037 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
2038 intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr = ipTemp->sin_addr.S_un.S_addr;
2039 #endif
2042 /* Socket Status Flags */
2043 strcpy(ifInfo.ifr_name, ifName);
2044 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
2046 ERR ("Error obtaining status flags for socket!\n");
2047 close(fd);
2048 WSASetLastError(WSAEINVAL);
2049 return (SOCKET_ERROR);
2051 else
2053 /* FIXME - Is this the right flag to use? */
2054 intArray->iiFlags = ifInfo.ifr_flags;
2056 intArray++; /* Prepare for another interface */
2059 /* Calculate the size of the array being returned */
2060 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2061 break;
2064 default:
2066 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2067 close(fd);
2068 WSASetLastError(WSAEOPNOTSUPP);
2069 return (SOCKET_ERROR);
2073 /* Function executed with no errors */
2074 close(fd);
2075 return (0);
2077 else
2079 WSASetLastError(WSAENOTSOCK);
2080 return (SOCKET_ERROR);
2086 Helper function for WSAIoctl - Get count of the number of interfaces
2087 by parsing /proc filesystem.
2089 int WSAIOCTL_GetInterfaceCount(void)
2091 FILE *procfs;
2092 char buf[512]; /* Size doesn't matter, something big */
2093 int intcnt=0;
2096 /* Open /proc filesystem file for network devices */
2097 procfs = fopen(PROCFS_NETDEV_FILE, "r");
2098 if (!procfs)
2100 /* If we can't open the file, return an error */
2101 return (-1);
2104 /* Omit first two lines, they are only headers */
2105 fgets(buf, sizeof buf, procfs);
2106 fgets(buf, sizeof buf, procfs);
2108 while (fgets(buf, sizeof buf, procfs))
2110 /* Each line in the file represents a network interface */
2111 intcnt++;
2114 fclose(procfs);
2115 return(intcnt);
2120 Helper function for WSAIoctl - Get name of device from interface number
2121 by parsing /proc filesystem.
2123 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
2125 FILE *procfs;
2126 char buf[512]; /* Size doesn't matter, something big */
2127 int i;
2129 /* Open /proc filesystem file for network devices */
2130 procfs = fopen(PROCFS_NETDEV_FILE, "r");
2131 if (!procfs)
2133 /* If we can't open the file, return an error */
2134 return (-1);
2137 /* Omit first two lines, they are only headers */
2138 fgets(buf, sizeof(buf), procfs);
2139 fgets(buf, sizeof(buf), procfs);
2141 for (i=0; i<intNumber; i++)
2143 /* Skip the lines that don't interest us. */
2144 fgets(buf, sizeof(buf), procfs);
2146 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
2149 /* Parse out the line, grabbing only the name of the device
2150 to the intName variable
2152 The Line comes in like this: (we only care about the device name)
2153 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
2155 i=0;
2156 while (isspace(buf[i])) /* Skip initial space(s) */
2158 i++;
2161 while (buf[i])
2163 if (isspace(buf[i]))
2165 break;
2168 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
2170 /* This interface could be an alias... */
2171 int hold = i;
2172 char *dotname = intName;
2173 *intName++ = buf[i++];
2175 while (isdigit(buf[i]))
2177 *intName++ = buf[i++];
2180 if (buf[i] != ':')
2182 /* ... It wasn't, so back up */
2183 i = hold;
2184 intName = dotname;
2187 if (buf[i] == '\0')
2189 fclose(procfs);
2190 return(FALSE);
2193 i++;
2194 break;
2197 *intName++ = buf[i++];
2199 *intName++ = '\0';
2201 fclose(procfs);
2202 return(TRUE);
2206 /***********************************************************************
2207 * ioctlsocket (WS2_32.10)
2209 int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2211 int fd = _get_sock_fd(s);
2213 TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
2214 if (fd != -1)
2216 long newcmd = cmd;
2218 switch( cmd )
2220 case WS_FIONREAD:
2221 newcmd=FIONREAD;
2222 break;
2224 case WS_FIONBIO:
2225 newcmd=FIONBIO;
2226 if( _get_sock_mask(s) )
2228 /* AsyncSelect()'ed sockets are always nonblocking */
2229 if (*argp) {
2230 close(fd);
2231 return 0;
2233 SetLastError(WSAEINVAL);
2234 close(fd);
2235 return SOCKET_ERROR;
2237 close(fd);
2238 if (*argp)
2239 _enable_event(s, 0, FD_WINE_NONBLOCKING, 0);
2240 else
2241 _enable_event(s, 0, 0, FD_WINE_NONBLOCKING);
2242 return 0;
2244 case WS_SIOCATMARK:
2245 newcmd=SIOCATMARK;
2246 break;
2248 case WS__IOW('f',125,u_long):
2249 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2250 SetLastError(WSAEINVAL);
2251 return SOCKET_ERROR;
2253 case SIOCGIFBRDADDR:
2254 case SIOCGIFNETMASK:
2255 case SIOCGIFADDR:
2256 /* These don't need any special handling. They are used by
2257 WsControl, and are here to suppress an unecessary warning. */
2258 break;
2261 default:
2262 /* Netscape tries hard to use bogus ioctl 0x667e */
2263 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2265 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2267 close(fd);
2268 return 0;
2270 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2271 close(fd);
2273 return SOCKET_ERROR;
2276 /***********************************************************************
2277 * ioctlsocket (WINSOCK.12)
2279 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
2281 return (INT16)WS_ioctlsocket( s, cmd, argp );
2285 /***********************************************************************
2286 * listen (WS2_32.13)
2288 int WINAPI WS_listen(SOCKET s, int backlog)
2290 int fd = _get_sock_fd(s);
2292 TRACE("socket %04x, backlog %d\n", s, backlog);
2293 if (fd != -1)
2295 if (listen(fd, backlog) == 0)
2297 close(fd);
2298 _enable_event(s, FD_ACCEPT,
2299 FD_WINE_LISTENING,
2300 FD_CONNECT|FD_WINE_CONNECTED);
2301 return 0;
2303 SetLastError(wsaErrno());
2305 else SetLastError(WSAENOTSOCK);
2306 return SOCKET_ERROR;
2309 /***********************************************************************
2310 * listen (WINSOCK.13)
2312 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
2314 return (INT16)WS_listen( s, backlog );
2318 /***********************************************************************
2319 * recv (WS2_32.16)
2321 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2323 DWORD n, dwFlags = flags;
2324 WSABUF wsabuf;
2326 wsabuf.len = len;
2327 wsabuf.buf = buf;
2329 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2330 return SOCKET_ERROR;
2331 else
2332 return n;
2335 /***********************************************************************
2336 * recv (WINSOCK.16)
2338 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2340 return (INT16)WS_recv( s, buf, len, flags );
2344 /***********************************************************************
2345 * recvfrom (WS2_32.17)
2347 int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2348 struct WS_sockaddr *from, int *fromlen)
2350 DWORD n, dwFlags = flags;
2351 WSABUF wsabuf;
2353 wsabuf.len = len;
2354 wsabuf.buf = buf;
2356 if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2357 return SOCKET_ERROR;
2358 else
2359 return n;
2362 /***********************************************************************
2363 * recvfrom (WINSOCK.17)
2365 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2366 struct WS_sockaddr *from, INT16 *fromlen16)
2368 INT fromlen32;
2369 INT *p = &fromlen32;
2370 INT retVal;
2372 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
2373 retVal = WS_recvfrom( s, buf, len, flags, from, p );
2374 if( fromlen16 ) *fromlen16 = fromlen32;
2375 return (INT16)retVal;
2378 /***********************************************************************
2379 * __ws_select
2381 static int __ws_select(BOOL b32,
2382 void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
2383 const struct WS_timeval *ws_timeout)
2385 int highfd = 0;
2386 fd_set readfds, writefds, exceptfds;
2387 fd_set *p_read, *p_write, *p_except;
2388 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2389 struct timeval timeout, *timeoutaddr = NULL;
2391 TRACE("read %p, write %p, excp %p timeout %p\n",
2392 ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2394 p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
2395 p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
2396 p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
2397 if (ws_timeout)
2399 timeoutaddr = &timeout;
2400 timeout.tv_sec=ws_timeout->tv_sec;
2401 timeout.tv_usec=ws_timeout->tv_usec;
2404 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2406 fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
2407 fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
2409 if (p_except && ws_exceptfds)
2411 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
2412 #define wsfds32 ((WS_fd_set*)ws_exceptfds)
2413 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
2415 for (i = j = 0; i < count; i++)
2417 int fd = exceptfd[i];
2418 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
2420 if( b32 )
2421 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
2422 else
2423 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
2425 if( fd >= 0 ) close(fd);
2426 exceptfd[i] = -1;
2428 if( b32 )
2429 wsfds32->fd_count = j;
2430 else
2431 wsfds16->fd_count = j;
2432 #undef wsfds32
2433 #undef wsfds16
2435 return highfd;
2437 fd_set_unimport(ws_readfds, readfd, b32);
2438 fd_set_unimport(ws_writefds, writefd, b32);
2439 fd_set_unimport(ws_exceptfds, exceptfd, b32);
2440 if( ws_readfds ) ((WS_fd_set*)ws_readfds)->fd_count = 0;
2441 if( ws_writefds ) ((WS_fd_set*)ws_writefds)->fd_count = 0;
2442 if( ws_exceptfds ) ((WS_fd_set*)ws_exceptfds)->fd_count = 0;
2444 if( highfd == 0 ) return 0;
2445 SetLastError(wsaErrno());
2446 return SOCKET_ERROR;
2449 /***********************************************************************
2450 * select (WINSOCK.18)
2452 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
2453 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
2454 struct WS_timeval* timeout)
2456 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2459 /***********************************************************************
2460 * select (WS2_32.18)
2462 int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2463 WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2464 const struct WS_timeval* timeout)
2466 /* struct timeval is the same for both 32- and 16-bit code */
2467 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
2471 /***********************************************************************
2472 * send (WS2_32.19)
2474 int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2476 DWORD n;
2477 WSABUF wsabuf;
2479 wsabuf.len = len;
2480 wsabuf.buf = (char*) buf;
2482 if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2483 return SOCKET_ERROR;
2484 else
2485 return n;
2488 /***********************************************************************
2489 * WSASend (WS2_32.72)
2491 INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2492 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2493 LPWSAOVERLAPPED lpOverlapped,
2494 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2496 return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2497 NULL, 0, lpOverlapped, lpCompletionRoutine );
2500 /***********************************************************************
2501 * WSASendTo (WS2_32.74)
2503 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2504 LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2505 const struct WS_sockaddr *to, int tolen,
2506 LPWSAOVERLAPPED lpOverlapped,
2507 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2509 int i, n, fd, err = WSAENOTSOCK, flags, ret;
2510 struct iovec* iovec;
2511 struct ws2_async *wsa;
2512 enum fd_type type;
2514 TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2515 s, lpBuffers, dwBufferCount, dwFlags,
2516 to, tolen, lpOverlapped, lpCompletionRoutine);
2518 fd = _get_sock_fd_type( s, GENERIC_WRITE, &type, &flags );
2519 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
2521 if ( fd == -1 )
2523 err = WSAGetLastError ();
2524 goto error;
2527 iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
2529 if ( !iovec )
2531 err = WSAEFAULT;
2532 goto err_close;
2535 for ( i = 0; i < dwBufferCount; i++ )
2537 iovec[i].iov_base = lpBuffers[i].buf;
2538 iovec[i].iov_len = lpBuffers[i].len;
2541 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2543 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
2544 &dwFlags, (struct WS_sockaddr*) to, &tolen,
2545 lpOverlapped, lpCompletionRoutine );
2546 if ( !wsa )
2548 err = WSAEFAULT;
2549 goto err_free;
2552 if ( ( ret = register_new_async ( &wsa->async )) )
2554 err = NtStatusToWSAError ( ret );
2556 if ( !lpOverlapped )
2557 HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
2558 HeapFree ( GetProcessHeap(), 0, wsa );
2559 goto err_free;
2562 /* Try immediate completion */
2563 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
2565 if ( WSAGetOverlappedResult ( (HANDLE) s, lpOverlapped,
2566 lpNumberOfBytesSent, FALSE, &dwFlags) )
2567 return 0;
2569 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
2570 goto error;
2573 WSASetLastError ( WSA_IO_PENDING );
2574 return SOCKET_ERROR;
2577 if (_is_blocking(s))
2579 /* FIXME: exceptfds? */
2580 do_block(fd, 2);
2583 n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2584 if ( n == -1 )
2586 err = wsaErrno();
2587 if ( err == WSAEWOULDBLOCK )
2588 _enable_event (s, FD_WRITE, 0, 0);
2589 goto err_free;
2592 TRACE(" -> %i bytes\n", n);
2593 *lpNumberOfBytesSent = n;
2595 HeapFree ( GetProcessHeap(), 0, iovec );
2596 close ( fd );
2597 return 0;
2599 err_free:
2600 HeapFree ( GetProcessHeap(), 0, iovec );
2602 err_close:
2603 close ( fd );
2605 error:
2606 WARN (" -> ERROR %d\n", err);
2607 WSASetLastError (err);
2608 return SOCKET_ERROR;
2611 /***********************************************************************
2612 * send (WINSOCK.19)
2614 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
2616 return WS_send( s, buf, len, flags );
2619 /***********************************************************************
2620 * sendto (WS2_32.20)
2622 int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2623 const struct WS_sockaddr *to, int tolen)
2625 DWORD n;
2626 WSABUF wsabuf;
2628 wsabuf.len = len;
2629 wsabuf.buf = (char*) buf;
2631 if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2632 return SOCKET_ERROR;
2633 else
2634 return n;
2637 /***********************************************************************
2638 * sendto (WINSOCK.20)
2640 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2641 struct WS_sockaddr *to, INT16 tolen)
2643 return (INT16)WS_sendto( s, buf, len, flags, to, tolen );
2646 /***********************************************************************
2647 * setsockopt (WS2_32.21)
2649 int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2650 const char *optval, int optlen)
2652 int fd;
2654 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
2655 (int) optname, (int) optval, optlen);
2656 /* SO_OPENTYPE does not require a valid socket handle. */
2657 if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2659 if (optlen < sizeof(int) || !optval)
2661 SetLastError(WSAEFAULT);
2662 return SOCKET_ERROR;
2664 TlsSetValue( opentype_tls_index, (LPVOID)*(int *)optval );
2665 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2666 return 0;
2669 fd = _get_sock_fd(s);
2670 if (fd != -1)
2672 struct linger linger;
2673 int woptval;
2674 struct timeval tval;
2676 /* Is a privileged and useless operation, so we don't. */
2677 if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
2678 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2679 return 0;
2682 if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2683 /* This is unique to WinSock and takes special conversion */
2684 linger.l_onoff = *((int*)optval) ? 0: 1;
2685 linger.l_linger = 0;
2686 optname=SO_LINGER;
2687 optval = (char*)&linger;
2688 optlen = sizeof(struct linger);
2689 level = SOL_SOCKET;
2690 }else{
2691 if (!convert_sockopt(&level, &optname)) {
2692 SetLastError(WSAENOPROTOOPT);
2693 close(fd);
2694 return SOCKET_ERROR;
2696 if (optname == SO_LINGER && optval) {
2697 /* yes, uses unsigned short in both win16/win32 */
2698 linger.l_onoff = ((UINT16*)optval)[0];
2699 linger.l_linger = ((UINT16*)optval)[1];
2700 /* FIXME: what is documented behavior if SO_LINGER optval
2701 is null?? */
2702 optval = (char*)&linger;
2703 optlen = sizeof(struct linger);
2704 } else if (optlen < sizeof(int)){
2705 woptval= *((INT16 *) optval);
2706 optval= (char*) &woptval;
2707 optlen=sizeof(int);
2709 #ifdef SO_RCVTIMEO
2710 if (level == SOL_SOCKET && optname == SO_RCVTIMEO) {
2711 if (optlen == sizeof(UINT32)) {
2712 /* WinSock passes miliseconds instead of struct timeval */
2713 tval.tv_usec = *(PUINT32)optval % 1000;
2714 tval.tv_sec = *(PUINT32)optval / 1000;
2715 /* min of 500 milisec */
2716 if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2717 optlen = sizeof(struct timeval);
2718 optval = (char*)&tval;
2719 } else if (optlen == sizeof(struct timeval)) {
2720 WARN("SO_RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2721 } else {
2722 WARN("SO_RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2723 close(fd);
2724 return 0;
2727 #endif
2728 #ifdef SO_SNDTIMEO
2729 if (level == SOL_SOCKET && optname == SO_SNDTIMEO) {
2730 if (optlen == sizeof(UINT32)) {
2731 /* WinSock passes miliseconds instead of struct timeval */
2732 tval.tv_usec = *(PUINT32)optval % 1000;
2733 tval.tv_sec = *(PUINT32)optval / 1000;
2734 /* min of 500 milisec */
2735 if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
2736 optlen = sizeof(struct timeval);
2737 optval = (char*)&tval;
2738 } else if (optlen == sizeof(struct timeval)) {
2739 WARN("SO_SNDTIMEO for %d bytes: assuming unixism\n", optlen);
2740 } else {
2741 WARN("SO_SNDTIMEO for %d bytes is weird: ignored\n", optlen);
2742 close(fd);
2743 return 0;
2746 #endif
2748 if(optname == SO_RCVBUF && *(int*)optval < 2048) {
2749 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2750 close( fd);
2751 return 0;
2754 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2756 close(fd);
2757 return 0;
2759 SetLastError(wsaErrno());
2760 close(fd);
2762 else SetLastError(WSAENOTSOCK);
2763 return SOCKET_ERROR;
2766 /***********************************************************************
2767 * setsockopt (WINSOCK.21)
2769 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2770 char *optval, INT16 optlen)
2772 if( !optval ) return SOCKET_ERROR;
2773 return (INT16)WS_setsockopt( s, (UINT16)level, optname, optval, optlen );
2777 /***********************************************************************
2778 * shutdown (WS2_32.22)
2780 int WINAPI WS_shutdown(SOCKET s, int how)
2782 int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2783 enum fd_type type;
2784 unsigned int clear_flags = 0;
2786 fd = _get_sock_fd_type ( s, 0, &type, &flags );
2787 TRACE("socket %04x, how %i %d %d \n", s, how, type, flags );
2789 if (fd == -1)
2790 return SOCKET_ERROR;
2792 switch( how )
2794 case 0: /* drop receives */
2795 clear_flags |= FD_READ;
2796 break;
2797 case 1: /* drop sends */
2798 clear_flags |= FD_WRITE;
2799 break;
2800 case 2: /* drop all */
2801 clear_flags |= FD_READ|FD_WRITE;
2802 default:
2803 clear_flags |= FD_WINE_CONNECTED|FD_WINE_LISTENING;
2806 if ( flags & FD_FLAG_OVERLAPPED ) {
2808 switch ( how )
2810 case SD_RECEIVE:
2811 fd0 = fd;
2812 break;
2813 case SD_SEND:
2814 fd1 = fd;
2815 break;
2816 case SD_BOTH:
2817 default:
2818 fd0 = fd;
2819 fd1 = _get_sock_fd ( s );
2822 if ( fd0 != -1 )
2824 err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
2825 if ( err )
2827 close ( fd0 );
2828 goto error;
2831 if ( fd1 != -1 )
2833 err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
2834 if ( err )
2836 close ( fd1 );
2837 goto error;
2841 else /* non-overlapped mode */
2843 if ( shutdown( fd, how ) )
2845 err = wsaErrno ();
2846 close ( fd );
2847 goto error;
2849 close(fd);
2852 _enable_event( s, 0, 0, clear_flags );
2853 if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2854 return 0;
2856 error:
2857 _enable_event( s, 0, 0, clear_flags );
2858 WSASetLastError ( err );
2859 return SOCKET_ERROR;
2862 /***********************************************************************
2863 * shutdown (WINSOCK.22)
2865 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2867 return (INT16)WS_shutdown( s, how );
2871 /***********************************************************************
2872 * socket (WS2_32.23)
2874 SOCKET WINAPI WS_socket(int af, int type, int protocol)
2876 TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2878 return WSASocketA ( af, type, protocol, NULL, 0,
2879 (TlsGetValue(opentype_tls_index) ? 0 : WSA_FLAG_OVERLAPPED) );
2882 /***********************************************************************
2883 * socket (WINSOCK.23)
2885 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2887 return (SOCKET16)WS_socket( af, type, protocol );
2891 /* ----------------------------------- DNS services
2893 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2894 * Also, we have to use wsock32 stubs to convert structures and
2895 * error codes from Unix to WSA, hence there is no direct mapping in
2896 * the relay32/wsock32.spec.
2900 /***********************************************************************
2901 * __ws_gethostbyaddr
2903 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2905 WIN_hostent *retval = NULL;
2907 struct hostent* host;
2908 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2909 char *extrabuf;
2910 int ebufsize=1024;
2911 struct hostent hostentry;
2912 int locerr=ENOBUFS;
2913 host = NULL;
2914 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2915 while(extrabuf) {
2916 int res = gethostbyaddr_r(addr, len, type,
2917 &hostentry, extrabuf, ebufsize, &host, &locerr);
2918 if( res != ERANGE) break;
2919 ebufsize *=2;
2920 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2922 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2923 #else
2924 EnterCriticalSection( &csWSgetXXXbyYYY );
2925 host = gethostbyaddr(addr, len, type);
2926 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2927 #endif
2928 if( host != NULL )
2930 if( WS_dup_he(host, dup_flag) )
2931 retval = he_buffer;
2932 else
2933 SetLastError(WSAENOBUFS);
2935 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2936 HeapFree(GetProcessHeap(),0,extrabuf);
2937 #else
2938 LeaveCriticalSection( &csWSgetXXXbyYYY );
2939 #endif
2940 return retval;
2943 /***********************************************************************
2944 * gethostbyaddr (WINSOCK.51)
2946 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2948 TRACE("ptr %p, len %d, type %d\n", addr, len, type);
2949 if (!__ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR )) return 0;
2950 return he_buffer_seg;
2953 /***********************************************************************
2954 * gethostbyaddr (WS2_32.51)
2956 struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len,
2957 int type)
2959 TRACE("ptr %08x, len %d, type %d\n",
2960 (unsigned) addr, len, type);
2961 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2964 /***********************************************************************
2965 * __ws_gethostbyname
2967 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2969 WIN_hostent *retval = NULL;
2970 struct hostent* host;
2971 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2972 char *extrabuf;
2973 int ebufsize=1024;
2974 struct hostent hostentry;
2975 int locerr = ENOBUFS;
2976 host = NULL;
2977 extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2978 while(extrabuf) {
2979 int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2980 if( res != ERANGE) break;
2981 ebufsize *=2;
2982 extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2984 if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2985 #else
2986 EnterCriticalSection( &csWSgetXXXbyYYY );
2987 host = gethostbyname(name);
2988 if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2989 #endif
2990 if( host != NULL )
2992 if( WS_dup_he(host, dup_flag) )
2993 retval = he_buffer;
2994 else SetLastError(WSAENOBUFS);
2996 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2997 HeapFree(GetProcessHeap(),0,extrabuf);
2998 #else
2999 LeaveCriticalSection( &csWSgetXXXbyYYY );
3000 #endif
3001 return retval;
3004 /***********************************************************************
3005 * gethostbyname (WINSOCK.52)
3007 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
3009 TRACE( "%s\n", debugstr_a(name) );
3010 if (!__ws_gethostbyname( name, WS_DUP_SEGPTR )) return 0;
3011 return he_buffer_seg;
3014 /***********************************************************************
3015 * gethostbyname (WS2_32.52)
3017 struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
3019 TRACE( "%s\n", debugstr_a(name) );
3020 return __ws_gethostbyname( name, WS_DUP_LINEAR );
3024 /***********************************************************************
3025 * __ws_getprotobyname
3027 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
3029 WIN_protoent* retval = NULL;
3030 #ifdef HAVE_GETPROTOBYNAME
3031 struct protoent* proto;
3032 EnterCriticalSection( &csWSgetXXXbyYYY );
3033 if( (proto = getprotobyname(name)) != NULL )
3035 if( WS_dup_pe(proto, dup_flag) )
3036 retval = pe_buffer;
3037 else SetLastError(WSAENOBUFS);
3039 else {
3040 MESSAGE("protocol %s not found; You might want to add "
3041 "this to /etc/protocols\n", debugstr_a(name) );
3042 SetLastError(WSANO_DATA);
3044 LeaveCriticalSection( &csWSgetXXXbyYYY );
3045 #endif
3046 return retval;
3049 /***********************************************************************
3050 * getprotobyname (WINSOCK.53)
3052 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
3054 TRACE( "%s\n", debugstr_a(name) );
3055 if (!__ws_getprotobyname(name, WS_DUP_SEGPTR)) return 0;
3056 return pe_buffer_seg;
3059 /***********************************************************************
3060 * getprotobyname (WS2_32.53)
3062 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
3064 TRACE( "%s\n", debugstr_a(name) );
3065 return __ws_getprotobyname(name, WS_DUP_LINEAR);
3069 /***********************************************************************
3070 * __ws_getprotobynumber
3072 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
3074 WIN_protoent* retval = NULL;
3075 #ifdef HAVE_GETPROTOBYNUMBER
3076 struct protoent* proto;
3077 EnterCriticalSection( &csWSgetXXXbyYYY );
3078 if( (proto = getprotobynumber(number)) != NULL )
3080 if( WS_dup_pe(proto, dup_flag) )
3081 retval = pe_buffer;
3082 else SetLastError(WSAENOBUFS);
3084 else {
3085 MESSAGE("protocol number %d not found; You might want to add "
3086 "this to /etc/protocols\n", number );
3087 SetLastError(WSANO_DATA);
3089 LeaveCriticalSection( &csWSgetXXXbyYYY );
3090 #endif
3091 return retval;
3094 /***********************************************************************
3095 * getprotobynumber (WINSOCK.54)
3097 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
3099 TRACE("%i\n", number);
3100 if (!__ws_getprotobynumber(number, WS_DUP_SEGPTR)) return 0;
3101 return pe_buffer_seg;
3104 /***********************************************************************
3105 * getprotobynumber (WS2_32.54)
3107 struct WS_protoent* WINAPI WS_getprotobynumber(int number)
3109 TRACE("%i\n", number);
3110 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
3114 /***********************************************************************
3115 * __ws_getservbyname
3117 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
3119 WIN_servent* retval = NULL;
3120 struct servent* serv;
3121 int i = wsi_strtolo( name, proto );
3123 if( i ) {
3124 EnterCriticalSection( &csWSgetXXXbyYYY );
3125 serv = getservbyname(local_buffer,
3126 proto ? (local_buffer + i) : NULL);
3127 if( serv != NULL )
3129 if( WS_dup_se(serv, dup_flag) )
3130 retval = se_buffer;
3131 else SetLastError(WSAENOBUFS);
3133 else {
3134 MESSAGE("service %s protocol %s not found; You might want to add "
3135 "this to /etc/services\n", debugstr_a(local_buffer),
3136 proto ? debugstr_a(local_buffer+i):"*");
3137 SetLastError(WSANO_DATA);
3139 LeaveCriticalSection( &csWSgetXXXbyYYY );
3141 else SetLastError(WSAENOBUFS);
3142 return retval;
3145 /***********************************************************************
3146 * getservbyname (WINSOCK.55)
3148 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
3150 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3151 if (!__ws_getservbyname(name, proto, WS_DUP_SEGPTR)) return 0;
3152 return se_buffer_seg;
3155 /***********************************************************************
3156 * getservbyname (WS2_32.55)
3158 struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
3160 TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
3161 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
3165 /***********************************************************************
3166 * __ws_getservbyport
3168 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
3170 WIN_servent* retval = NULL;
3171 #ifdef HAVE_GETSERVBYPORT
3172 struct servent* serv;
3173 if (!proto || wsi_strtolo( proto, NULL )) {
3174 EnterCriticalSection( &csWSgetXXXbyYYY );
3175 if( (serv = getservbyport(port, (proto) ? local_buffer : NULL)) != NULL ) {
3176 if( WS_dup_se(serv, dup_flag) )
3177 retval = se_buffer;
3178 else SetLastError(WSAENOBUFS);
3180 else {
3181 MESSAGE("service on port %lu protocol %s not found; You might want to add "
3182 "this to /etc/services\n", (unsigned long)ntohl(port),
3183 proto ? debugstr_a(local_buffer) : "*");
3184 SetLastError(WSANO_DATA);
3186 LeaveCriticalSection( &csWSgetXXXbyYYY );
3188 else SetLastError(WSAENOBUFS);
3189 #endif
3190 return retval;
3193 /***********************************************************************
3194 * getservbyport (WINSOCK.56)
3196 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
3198 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3199 if (!__ws_getservbyport(port, proto, WS_DUP_SEGPTR)) return 0;
3200 return se_buffer_seg;
3203 /***********************************************************************
3204 * getservbyport (WS2_32.56)
3206 struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
3208 TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
3209 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
3213 /***********************************************************************
3214 * gethostname (WS2_32.57)
3216 int WINAPI WS_gethostname(char *name, int namelen)
3218 TRACE("name %p, len %d\n", name, namelen);
3220 if (gethostname(name, namelen) == 0)
3222 TRACE("<- '%s'\n", name);
3223 return 0;
3225 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
3226 TRACE("<- ERROR !\n");
3227 return SOCKET_ERROR;
3230 /***********************************************************************
3231 * gethostname (WINSOCK.57)
3233 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
3235 return (INT16)WS_gethostname(name, namelen);
3239 /* ------------------------------------- Windows sockets extensions -- *
3241 * ------------------------------------------------------------------- */
3243 /***********************************************************************
3244 * WSAEnumNetworkEvents (WS2_32.36)
3246 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
3248 int ret;
3250 TRACE("%08x, hEvent %08x, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
3252 SERVER_START_REQ( get_socket_event )
3254 req->handle = s;
3255 req->service = TRUE;
3256 req->c_event = hEvent;
3257 wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
3258 if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
3260 SERVER_END_REQ;
3261 if (!ret) return 0;
3262 SetLastError(WSAEINVAL);
3263 return SOCKET_ERROR;
3266 /***********************************************************************
3267 * WSAEventSelect (WS2_32.39)
3269 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
3271 int ret;
3273 TRACE("%08x, hEvent %08x, event %08x\n", s, hEvent, (unsigned)lEvent );
3275 SERVER_START_REQ( set_socket_event )
3277 req->handle = s;
3278 req->mask = lEvent;
3279 req->event = hEvent;
3280 req->window = 0;
3281 req->msg = 0;
3282 ret = wine_server_call( req );
3284 SERVER_END_REQ;
3285 if (!ret) return 0;
3286 SetLastError(WSAEINVAL);
3287 return SOCKET_ERROR;
3290 /**********************************************************************
3291 * WSAGetOverlappedResult (WS2_32.40)
3293 BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
3294 LPDWORD lpcbTransfer, BOOL fWait,
3295 LPDWORD lpdwFlags )
3297 DWORD r;
3299 TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
3300 s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
3302 if ( !(lpOverlapped && lpOverlapped->hEvent) )
3304 ERR ( "Invalid pointer\n" );
3305 WSASetLastError (WSA_INVALID_PARAMETER);
3306 return FALSE;
3309 if ( fWait )
3311 while ( WaitForSingleObjectEx (lpOverlapped->hEvent, INFINITE, TRUE) == STATUS_USER_APC );
3313 else if ( lpOverlapped->Internal == STATUS_PENDING )
3315 /* Wait in order to give APCs a chance to run. */
3316 /* This is cheating, so we must set the event again in case of success -
3317 it may be a non-manual reset event. */
3318 while ( (r = WaitForSingleObjectEx (lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
3319 if ( r == WAIT_OBJECT_0 )
3320 NtSetEvent ( lpOverlapped->hEvent, NULL );
3323 if ( lpcbTransfer )
3324 *lpcbTransfer = lpOverlapped->InternalHigh;
3326 if ( lpdwFlags )
3327 *lpdwFlags = lpOverlapped->Offset;
3329 switch ( lpOverlapped->Internal )
3331 case STATUS_SUCCESS:
3332 return TRUE;
3333 case STATUS_PENDING:
3334 WSASetLastError ( WSA_IO_INCOMPLETE );
3335 if (fWait) ERR ("PENDING status after waiting!\n");
3336 return FALSE;
3337 default:
3338 WSASetLastError ( NtStatusToWSAError ( lpOverlapped->Internal ));
3339 return FALSE;
3344 /***********************************************************************
3345 * WSAAsyncSelect (WS2_32.101)
3347 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
3349 int ret;
3351 TRACE("%x, hWnd %x, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3353 SERVER_START_REQ( set_socket_event )
3355 req->handle = s;
3356 req->mask = lEvent;
3357 req->event = 0;
3358 req->window = hWnd;
3359 req->msg = uMsg;
3360 ret = wine_server_call( req );
3362 SERVER_END_REQ;
3363 if (!ret) return 0;
3364 SetLastError(WSAEINVAL);
3365 return SOCKET_ERROR;
3368 /***********************************************************************
3369 * WSAAsyncSelect (WINSOCK.101)
3371 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
3373 return (INT16)WSAAsyncSelect( s, HWND_32(hWnd), wMsg, lEvent );
3376 /***********************************************************************
3377 * WSARecvEx (WINSOCK.1107)
3379 * See description for WSARecvEx()
3381 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags)
3383 FIXME("(WSARecvEx16) partial packet return value not set \n");
3385 return WINSOCK_recv16(s, buf, len, *flags);
3389 /***********************************************************************
3390 * WSACreateEvent (WS2_32.31)
3393 WSAEVENT WINAPI WSACreateEvent(void)
3395 /* Create a manual-reset event, with initial state: unsignealed */
3396 TRACE("\n");
3398 return CreateEventA(NULL, TRUE, FALSE, NULL);
3401 /***********************************************************************
3402 * WSACloseEvent (WS2_32.29)
3405 BOOL WINAPI WSACloseEvent(WSAEVENT event)
3407 TRACE ("event=0x%x\n", event);
3409 return CloseHandle(event);
3412 /***********************************************************************
3413 * WSASocketA (WS2_32.78)
3416 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3417 LPWSAPROTOCOL_INFOA lpProtocolInfo,
3418 GROUP g, DWORD dwFlags)
3420 SOCKET ret;
3423 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
3424 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3427 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3428 af, type, protocol, lpProtocolInfo, g, dwFlags );
3430 /* hack for WSADuplicateSocket */
3431 if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3432 ret = lpProtocolInfo->dwCatalogEntryId;
3433 TRACE("\tgot duplicate %04x\n", ret);
3434 return ret;
3437 /* check the socket family */
3438 switch(af)
3440 #ifdef HAVE_IPX
3441 case WS_AF_IPX: af = AF_IPX;
3442 #endif
3443 case AF_INET:
3444 case AF_UNSPEC:
3445 break;
3446 default:
3447 SetLastError(WSAEAFNOSUPPORT);
3448 return INVALID_SOCKET;
3451 /* check the socket type */
3452 switch(type)
3454 case WS_SOCK_STREAM:
3455 type=SOCK_STREAM;
3456 break;
3457 case WS_SOCK_DGRAM:
3458 type=SOCK_DGRAM;
3459 break;
3460 case WS_SOCK_RAW:
3461 type=SOCK_RAW;
3462 break;
3463 default:
3464 SetLastError(WSAESOCKTNOSUPPORT);
3465 return INVALID_SOCKET;
3468 /* check the protocol type */
3469 if ( protocol < 0 ) /* don't support negative values */
3471 SetLastError(WSAEPROTONOSUPPORT);
3472 return INVALID_SOCKET;
3475 if ( af == AF_UNSPEC) /* did they not specify the address family? */
3476 switch(protocol)
3478 case IPPROTO_TCP:
3479 if (type == SOCK_STREAM) { af = AF_INET; break; }
3480 case IPPROTO_UDP:
3481 if (type == SOCK_DGRAM) { af = AF_INET; break; }
3482 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3485 SERVER_START_REQ( create_socket )
3487 req->family = af;
3488 req->type = type;
3489 req->protocol = protocol;
3490 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3491 req->flags = dwFlags;
3492 req->inherit = TRUE;
3493 set_error( wine_server_call( req ) );
3494 ret = (SOCKET)reply->handle;
3496 SERVER_END_REQ;
3497 if (ret)
3499 TRACE("\tcreated %04x\n", ret );
3500 return ret;
3503 if (GetLastError() == WSAEACCES) /* raw socket denied */
3505 if (type == SOCK_RAW)
3506 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3507 else
3508 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3509 SetLastError(WSAESOCKTNOSUPPORT);
3512 WARN("\t\tfailed!\n");
3513 return INVALID_SOCKET;
3517 /***********************************************************************
3518 * __WSAFDIsSet (WINSOCK.151)
3520 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
3522 int i = set->fd_count;
3524 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3526 while (i--)
3527 if (set->fd_array[i] == s) return 1;
3528 return 0;
3531 /***********************************************************************
3532 * __WSAFDIsSet (WS2_32.151)
3534 int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3536 int i = set->fd_count;
3538 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3540 while (i--)
3541 if (set->fd_array[i] == s) return 1;
3542 return 0;
3545 /***********************************************************************
3546 * WSAIsBlocking (WINSOCK.114)
3547 * WSAIsBlocking (WS2_32.114)
3549 BOOL WINAPI WSAIsBlocking(void)
3551 /* By default WinSock should set all its sockets to non-blocking mode
3552 * and poll in PeekMessage loop when processing "blocking" ones. This
3553 * function is supposed to tell if the program is in this loop. Our
3554 * blocking calls are truly blocking so we always return FALSE.
3556 * Note: It is allowed to call this function without prior WSAStartup().
3559 TRACE("\n");
3560 return FALSE;
3563 /***********************************************************************
3564 * WSACancelBlockingCall (WINSOCK.113)
3565 * WSACancelBlockingCall (WS2_32.113)
3567 INT WINAPI WSACancelBlockingCall(void)
3569 TRACE("\n");
3570 return 0;
3574 /***********************************************************************
3575 * WSASetBlockingHook (WINSOCK.109)
3577 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
3579 FARPROC16 prev = (FARPROC16)blocking_hook;
3580 blocking_hook = (FARPROC)lpBlockFunc;
3581 TRACE("hook %p\n", lpBlockFunc);
3582 return prev;
3586 /***********************************************************************
3587 * WSASetBlockingHook (WS2_32.109)
3589 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3591 FARPROC prev = blocking_hook;
3592 blocking_hook = lpBlockFunc;
3593 TRACE("hook %p\n", lpBlockFunc);
3594 return prev;
3598 /***********************************************************************
3599 * WSAUnhookBlockingHook (WINSOCK.110)
3601 INT16 WINAPI WSAUnhookBlockingHook16(void)
3603 blocking_hook = NULL;
3604 return 0;
3608 /***********************************************************************
3609 * WSAUnhookBlockingHook (WS2_32.110)
3611 INT WINAPI WSAUnhookBlockingHook(void)
3613 blocking_hook = NULL;
3614 return 0;
3618 /* ----------------------------------- end of API stuff */
3620 /* ----------------------------------- helper functions -
3622 * TODO: Merge WS_dup_..() stuff into one function that
3623 * would operate with a generic structure containing internal
3624 * pointers (via a template of some kind).
3627 static int list_size(char** l, int item_size)
3629 int i,j = 0;
3630 if(l)
3631 { for(i=0;l[i];i++)
3632 j += (item_size) ? item_size : strlen(l[i]) + 1;
3633 j += (i + 1) * sizeof(char*); }
3634 return j;
3637 static int list_dup(char** l_src, char* ref, char* base, int item_size)
3639 /* base is either either equal to ref or 0 or SEGPTR */
3641 char* p = ref;
3642 char** l_to = (char**)ref;
3643 int i,j,k;
3645 for(j=0;l_src[j];j++) ;
3646 p += (j + 1) * sizeof(char*);
3647 for(i=0;i<j;i++)
3648 { l_to[i] = base + (p - ref);
3649 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3650 memcpy(p, l_src[i], k); p += k; }
3651 l_to[i] = NULL;
3652 return (p - ref);
3655 /* ----- hostent */
3657 static int hostent_size(struct hostent* p_he)
3659 int size = 0;
3660 if( p_he )
3661 { size = sizeof(struct hostent);
3662 size += strlen(p_he->h_name) + 1;
3663 size += list_size(p_he->h_aliases, 0);
3664 size += list_size(p_he->h_addr_list, p_he->h_length ); }
3665 return size;
3668 /* duplicate hostent entry
3669 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3670 * Dito for protoent and servent.
3672 static int WS_dup_he(struct hostent* p_he, int flag)
3674 /* Convert hostent structure into ws_hostent so that the data fits
3675 * into local_buffer. Internal pointers can be linear, SEGPTR, or
3676 * relative to local_buffer depending on "flag" value. Returns size
3677 * of the data copied.
3680 int size = hostent_size(p_he);
3681 if( size )
3683 char *p_name,*p_aliases,*p_addr,*p_base,*p;
3684 char *p_to;
3685 struct ws_hostent16 *p_to16;
3686 struct WS_hostent *p_to32;
3688 check_buffer_he(size);
3689 p_to = he_buffer;
3690 p_to16 = he_buffer;
3691 p_to32 = he_buffer;
3693 p = p_to;
3694 p_base = (flag & WS_DUP_SEGPTR) ? (char*)he_buffer_seg : he_buffer;
3695 p += (flag & WS_DUP_SEGPTR) ?
3696 sizeof(struct ws_hostent16) : sizeof(struct WS_hostent);
3697 p_name = p;
3698 strcpy(p, p_he->h_name); p += strlen(p) + 1;
3699 p_aliases = p;
3700 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3701 p_addr = p;
3702 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
3704 if (flag & WS_DUP_SEGPTR) /* Win16 */
3706 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
3707 p_to16->h_length = (INT16)p_he->h_length;
3708 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3709 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3710 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3711 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3713 else /* Win32 */
3715 p_to32->h_addrtype = p_he->h_addrtype;
3716 p_to32->h_length = p_he->h_length;
3717 p_to32->h_name = (p_base + (p_name - p_to));
3718 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3719 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3720 size += (sizeof(struct WS_hostent) - sizeof(struct hostent));
3723 return size;
3726 /* ----- protoent */
3728 static int protoent_size(struct protoent* p_pe)
3730 int size = 0;
3731 if( p_pe )
3732 { size = sizeof(struct protoent);
3733 size += strlen(p_pe->p_name) + 1;
3734 size += list_size(p_pe->p_aliases, 0); }
3735 return size;
3738 static int WS_dup_pe(struct protoent* p_pe, int flag)
3740 int size = protoent_size(p_pe);
3741 if( size )
3743 char *p_to;
3744 struct ws_protoent16 *p_to16;
3745 struct WS_protoent *p_to32;
3746 char *p_name,*p_aliases,*p_base,*p;
3748 check_buffer_pe(size);
3749 p_to = pe_buffer;
3750 p_to16 = pe_buffer;
3751 p_to32 = pe_buffer;
3752 p = p_to;
3753 p_base = (flag & WS_DUP_SEGPTR) ? (char*)pe_buffer_seg : pe_buffer;
3754 p += (flag & WS_DUP_SEGPTR) ?
3755 sizeof(struct ws_protoent16) : sizeof(struct WS_protoent);
3756 p_name = p;
3757 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3758 p_aliases = p;
3759 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3761 if (flag & WS_DUP_SEGPTR) /* Win16 */
3763 p_to16->p_proto = (INT16)p_pe->p_proto;
3764 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3765 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3766 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3768 else /* Win32 */
3770 p_to32->p_proto = p_pe->p_proto;
3771 p_to32->p_name = (p_base) + (p_name - p_to);
3772 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3773 size += (sizeof(struct WS_protoent) - sizeof(struct protoent));
3776 return size;
3779 /* ----- servent */
3781 static int servent_size(struct servent* p_se)
3783 int size = 0;
3784 if( p_se )
3785 { size += sizeof(struct servent);
3786 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3787 size += list_size(p_se->s_aliases, 0); }
3788 return size;
3791 static int WS_dup_se(struct servent* p_se, int flag)
3793 int size = servent_size(p_se);
3794 if( size )
3796 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3797 char *p_to;
3798 struct ws_servent16 *p_to16;
3799 struct WS_servent *p_to32;
3801 check_buffer_se(size);
3802 p_to = se_buffer;
3803 p_to16 = se_buffer;
3804 p_to32 = se_buffer;
3805 p = p_to;
3806 p_base = (flag & WS_DUP_SEGPTR) ? (char*)se_buffer_seg : se_buffer;
3807 p += (flag & WS_DUP_SEGPTR) ?
3808 sizeof(struct ws_servent16) : sizeof(struct WS_servent);
3809 p_name = p;
3810 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3811 p_proto = p;
3812 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3813 p_aliases = p;
3814 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3816 if (flag & WS_DUP_SEGPTR) /* Win16 */
3818 p_to16->s_port = (INT16)p_se->s_port;
3819 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3820 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3821 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3822 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3824 else /* Win32 */
3826 p_to32->s_port = p_se->s_port;
3827 p_to32->s_name = (p_base + (p_name - p_to));
3828 p_to32->s_proto = (p_base + (p_proto - p_to));
3829 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3830 size += (sizeof(struct WS_servent) - sizeof(struct servent));
3833 return size;
3836 /* ----------------------------------- error handling */
3838 UINT16 wsaErrno(void)
3840 int loc_errno = errno;
3841 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3843 switch(loc_errno)
3845 case EINTR: return WSAEINTR;
3846 case EBADF: return WSAEBADF;
3847 case EPERM:
3848 case EACCES: return WSAEACCES;
3849 case EFAULT: return WSAEFAULT;
3850 case EINVAL: return WSAEINVAL;
3851 case EMFILE: return WSAEMFILE;
3852 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3853 case EINPROGRESS: return WSAEINPROGRESS;
3854 case EALREADY: return WSAEALREADY;
3855 case ENOTSOCK: return WSAENOTSOCK;
3856 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3857 case EMSGSIZE: return WSAEMSGSIZE;
3858 case EPROTOTYPE: return WSAEPROTOTYPE;
3859 case ENOPROTOOPT: return WSAENOPROTOOPT;
3860 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3861 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3862 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3863 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3864 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3865 case EADDRINUSE: return WSAEADDRINUSE;
3866 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3867 case ENETDOWN: return WSAENETDOWN;
3868 case ENETUNREACH: return WSAENETUNREACH;
3869 case ENETRESET: return WSAENETRESET;
3870 case ECONNABORTED: return WSAECONNABORTED;
3871 case EPIPE:
3872 case ECONNRESET: return WSAECONNRESET;
3873 case ENOBUFS: return WSAENOBUFS;
3874 case EISCONN: return WSAEISCONN;
3875 case ENOTCONN: return WSAENOTCONN;
3876 case ESHUTDOWN: return WSAESHUTDOWN;
3877 case ETOOMANYREFS: return WSAETOOMANYREFS;
3878 case ETIMEDOUT: return WSAETIMEDOUT;
3879 case ECONNREFUSED: return WSAECONNREFUSED;
3880 case ELOOP: return WSAELOOP;
3881 case ENAMETOOLONG: return WSAENAMETOOLONG;
3882 case EHOSTDOWN: return WSAEHOSTDOWN;
3883 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3884 case ENOTEMPTY: return WSAENOTEMPTY;
3885 #ifdef EPROCLIM
3886 case EPROCLIM: return WSAEPROCLIM;
3887 #endif
3888 #ifdef EUSERS
3889 case EUSERS: return WSAEUSERS;
3890 #endif
3891 #ifdef EDQUOT
3892 case EDQUOT: return WSAEDQUOT;
3893 #endif
3894 #ifdef ESTALE
3895 case ESTALE: return WSAESTALE;
3896 #endif
3897 #ifdef EREMOTE
3898 case EREMOTE: return WSAEREMOTE;
3899 #endif
3901 /* just in case we ever get here and there are no problems */
3902 case 0: return 0;
3903 default:
3904 WARN("Unknown errno %d!\n", loc_errno);
3905 return WSAEOPNOTSUPP;
3909 UINT16 wsaHerrno(int loc_errno)
3912 WARN("h_errno %d.\n", loc_errno);
3914 switch(loc_errno)
3916 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3917 case TRY_AGAIN: return WSATRY_AGAIN;
3918 case NO_RECOVERY: return WSANO_RECOVERY;
3919 case NO_DATA: return WSANO_DATA;
3920 case ENOBUFS: return WSAENOBUFS;
3922 case 0: return 0;
3923 default:
3924 WARN("Unknown h_errno %d!\n", loc_errno);
3925 return WSAEOPNOTSUPP;
3930 /***********************************************************************
3931 * WSARecv (WS2_32.67)
3933 int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3934 LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3935 LPWSAOVERLAPPED lpOverlapped,
3936 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3938 return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3939 NULL, NULL, lpOverlapped, lpCompletionRoutine);
3942 /***********************************************************************
3943 * WSARecvFrom (WS2_32.69)
3945 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3946 LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3947 LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3948 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3951 int i, n, fd, err = WSAENOTSOCK, flags, ret;
3952 struct iovec* iovec;
3953 struct ws2_async *wsa;
3954 enum fd_type type;
3956 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3957 s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3958 (lpFromlen ? *lpFromlen : -1L),
3959 lpOverlapped, lpCompletionRoutine);
3961 fd = _get_sock_fd_type( s, GENERIC_READ, &type, &flags );
3962 TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
3964 if (fd == -1)
3966 err = WSAGetLastError ();
3967 goto error;
3970 iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3971 if ( !iovec )
3973 err = WSAEFAULT;
3974 goto err_close;
3977 for (i = 0; i < dwBufferCount; i++)
3979 iovec[i].iov_base = lpBuffers[i].buf;
3980 iovec[i].iov_len = lpBuffers[i].len;
3983 if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3985 wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
3986 lpFlags, lpFrom, lpFromlen,
3987 lpOverlapped, lpCompletionRoutine );
3989 if ( !wsa )
3991 err = WSAEFAULT;
3992 goto err_free;
3995 if ( ( ret = register_new_async ( &wsa->async )) )
3997 err = NtStatusToWSAError ( ret );
3999 if ( !lpOverlapped )
4000 HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
4001 HeapFree ( GetProcessHeap(), 0, wsa );
4002 goto err_free;
4005 /* Try immediate completion */
4006 if ( lpOverlapped && !NtResetEvent( lpOverlapped->hEvent, NULL ) )
4008 if ( WSAGetOverlappedResult ( (HANDLE) s, lpOverlapped,
4009 lpNumberOfBytesRecvd, FALSE, lpFlags) )
4010 return 0;
4012 if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
4013 goto error;
4016 WSASetLastError ( WSA_IO_PENDING );
4017 return SOCKET_ERROR;
4020 if ( _is_blocking(s) )
4022 /* block here */
4023 /* FIXME: OOB and exceptfds? */
4024 do_block(fd, 1);
4027 n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
4028 if ( n == -1 )
4030 err = wsaErrno();
4031 goto err_free;
4034 TRACE(" -> %i bytes\n", n);
4035 *lpNumberOfBytesRecvd = n;
4037 HeapFree (GetProcessHeap(), 0, iovec);
4038 close(fd);
4039 _enable_event(s, FD_READ, 0, 0);
4041 return 0;
4043 err_free:
4044 HeapFree (GetProcessHeap(), 0, iovec);
4046 err_close:
4047 close (fd);
4049 error:
4050 WARN(" -> ERROR %d\n", err);
4051 WSASetLastError ( err );
4052 return SOCKET_ERROR;
4055 /***********************************************************************
4056 * WSCInstallProvider (WS2_32.88)
4058 INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
4059 LPCWSTR lpszProviderDllPath,
4060 const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
4061 DWORD dwNumberOfEntries,
4062 LPINT lpErrno )
4064 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
4065 debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
4066 dwNumberOfEntries, lpErrno);
4067 *lpErrno = 0;
4068 return 0;
4072 /***********************************************************************
4073 * WSCDeinstallProvider (WS2_32.83)
4075 INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
4077 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
4078 *lpErrno = 0;
4079 return 0;
4083 /***********************************************************************
4084 * WSAAccept (WS2_32.26)
4086 SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
4087 LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
4090 int ret = 0, size = 0;
4091 WSABUF CallerId, CallerData, CalleeId, CalleeData;
4092 /* QOS SQOS, GQOS; */
4093 GROUP g;
4094 SOCKET cs;
4095 SOCKADDR src_addr, dst_addr;
4097 TRACE("Socket %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
4098 s, addr, addrlen, lpfnCondition, dwCallbackData);
4101 size = sizeof(src_addr);
4102 cs = WS_accept(s, &src_addr, &size);
4104 if (cs == SOCKET_ERROR) return SOCKET_ERROR;
4106 CallerId.buf = (char *)&src_addr;
4107 CallerId.len = sizeof(src_addr);
4109 CallerData.buf = NULL;
4110 CallerData.len = (ULONG)NULL;
4112 WS_getsockname(cs, &dst_addr, &size);
4114 CalleeId.buf = (char *)&dst_addr;
4115 CalleeId.len = sizeof(dst_addr);
4118 ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
4119 &CalleeId, &CalleeData, &g, dwCallbackData);
4121 switch (ret)
4123 case CF_ACCEPT:
4124 if (addr && addrlen)
4125 addr = memcpy(addr, &src_addr, (*addrlen > size) ? size : *addrlen );
4126 return cs;
4127 case CF_DEFER:
4128 SERVER_START_REQ ( set_socket_deferred )
4130 req->handle = s;
4131 req->deferred = cs;
4132 if ( !wine_server_call_err ( req ) )
4134 SetLastError ( WSATRY_AGAIN );
4135 CloseHandle ( cs );
4138 SERVER_END_REQ;
4139 return SOCKET_ERROR;
4140 case CF_REJECT:
4141 WS_closesocket(cs);
4142 SetLastError(WSAECONNREFUSED);
4143 return SOCKET_ERROR;
4144 default:
4145 FIXME("Unknown return type from Condition function\n");
4146 SetLastError(WSAENOTSOCK);
4147 return SOCKET_ERROR;
4150 SetLastError(WSAENOTSOCK);
4151 return SOCKET_ERROR;
4154 /***********************************************************************
4155 * WSAEnumProtocolsA (WS2_32.37)
4157 int WINAPI WSAEnumProtocolsA(LPINT lpiProtocols, LPWSAPROTOCOL_INFOA lpProtocolBuffer, LPDWORD lpdwBufferLength)
4159 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4160 return 0;
4163 /***********************************************************************
4164 * WSAEnumProtocolsW (WS2_32.38)
4166 int WINAPI WSAEnumProtocolsW(LPINT lpiProtocols, LPWSAPROTOCOL_INFOW lpProtocolBuffer, LPDWORD lpdwBufferLength)
4168 FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
4169 return 0;
4172 /***********************************************************************
4173 * WSADuplicateSocketA (WS2_32.32)
4175 int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
4177 HANDLE hProcess;
4179 TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
4180 memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
4181 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
4182 /* I don't know what the real Windoze does next, this is a hack */
4183 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
4184 * the target use the global duplicate, or we could copy a reference to us to the structure
4185 * and let the target duplicate it from us, but let's do it as simple as possible */
4186 hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
4187 DuplicateHandle(GetCurrentProcess(), s,
4188 hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
4189 0, FALSE, DUPLICATE_SAME_ACCESS);
4190 CloseHandle(hProcess);
4191 lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
4192 return 0;