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).
27 #include "wine/port.h"
31 #include <sys/types.h>
35 #ifdef HAVE_SYS_IOCTL_H
36 # include <sys/ioctl.h>
38 #ifdef HAVE_SYS_FILIO_H
39 # include <sys/filio.h>
41 #ifdef HAVE_SYS_SOCKIO_H
42 # include <sys/sockio.h>
46 # include <sys/so_ioctl.h>
49 #ifdef HAVE_SYS_PARAM_H
50 # include <sys/param.h>
56 #ifdef HAVE_SYS_WAIT_H
57 # include <sys/wait.h>
62 #ifdef HAVE_SYS_SOCKET_H
63 #include <sys/socket.h>
65 #ifdef HAVE_NETINET_IN_H
66 # include <netinet/in.h>
68 #ifdef HAVE_NETINET_TCP_H
69 # include <netinet/tcp.h>
71 #ifdef HAVE_ARPA_INET_H
72 # include <arpa/inet.h>
77 #ifdef HAVE_SYS_ERRNO_H
78 #include <sys/errno.h>
87 #ifdef HAVE_ARPA_NAMESER_H
88 # include <arpa/nameser.h>
97 # include <netipx/ipx.h>
100 #ifdef HAVE_IPX_LINUX
101 # include <asm/types.h>
102 # include <linux/ipx.h>
106 #ifdef HAVE_SYS_TIME_H
107 # include <sys/time.h>
110 #include "wine/winbase16.h"
113 #include "winerror.h"
114 #include "winsock2.h"
115 #include "ws2tcpip.h"
117 #include "wine/winsock16.h"
120 #include "iphlpapi.h"
121 #include "wine/server.h"
122 #include "wine/debug.h"
125 # define sipx_network sipx_addr.x_net
126 # define sipx_node sipx_addr.x_host.c_host
127 #endif /* __FreeBSD__ */
129 WINE_DEFAULT_DEBUG_CHANNEL(winsock
);
131 /* critical section to protect some non-rentrant net function */
132 extern CRITICAL_SECTION csWSgetXXXbyYYY
;
134 #define DEBUG_SOCKADDR 0
135 #define dump_sockaddr(a) \
136 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
137 ((struct sockaddr_in *)a)->sin_family, \
138 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
139 ntohs(((struct sockaddr_in *)a)->sin_port))
141 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
142 #define SOCKET2HANDLE(s) ((HANDLE)(s))
143 #define HANDLE2SOCKET(h) ((SOCKET)(h))
145 /****************************************************************
146 * Async IO declarations
147 ****************************************************************/
150 static DWORD
ws2_async_get_status (const struct async_private
*ovp
);
151 static DWORD
ws2_async_get_count (const struct async_private
*ovp
);
152 static void ws2_async_set_status (struct async_private
*ovp
, const DWORD status
);
153 static void CALLBACK
ws2_async_call_completion (ULONG_PTR data
);
154 static void ws2_async_cleanup ( struct async_private
*ovp
);
156 static struct async_ops ws2_async_ops
=
158 ws2_async_get_status
,
159 ws2_async_set_status
,
161 ws2_async_call_completion
,
165 static struct async_ops ws2_nocomp_async_ops
=
167 ws2_async_get_status
,
168 ws2_async_set_status
,
170 NULL
, /* call_completion */
174 typedef struct ws2_async
177 LPWSAOVERLAPPED overlapped
;
178 LPWSAOVERLAPPED user_overlapped
;
179 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func
;
182 struct WS_sockaddr
*addr
;
184 int val
; /* for send operations */
185 int *ptr
; /* for recv operations */
190 /****************************************************************/
192 /* ----------------------------------- internal data */
194 /* ws_... struct conversion flags */
196 #define WS_DUP_LINEAR 0x0001
197 #define WS_DUP_SEGPTR 0x0002 /* internal pointers are SEGPTRs */
198 /* by default, internal pointers are linear */
199 typedef struct /* WSAAsyncSelect() control struct */
201 HANDLE service
, event
, sock
;
207 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
208 #define WS_MAX_UDP_DATAGRAM 1024
210 static void *he_buffer
; /* typecast for Win16/32 ws_hostent */
211 static SEGPTR he_buffer_seg
;
212 static void *se_buffer
; /* typecast for Win16/32 ws_servent */
213 static SEGPTR se_buffer_seg
;
214 static void *pe_buffer
; /* typecast for Win16/32 ws_protoent */
215 static SEGPTR pe_buffer_seg
;
216 static char* local_buffer
;
217 static SEGPTR dbuffer_seg
;
218 static INT num_startup
; /* reference counter */
219 static FARPROC blocking_hook
;
221 /* function prototypes */
222 static int WS_dup_he(struct hostent
* p_he
, int flag
);
223 static int WS_dup_pe(struct protoent
* p_pe
, int flag
);
224 static int WS_dup_se(struct servent
* p_se
, int flag
);
226 typedef void WIN_hostent
;
227 typedef void WIN_protoent
;
228 typedef void WIN_servent
;
230 int WSAIOCTL_GetInterfaceCount(void);
231 int WSAIOCTL_GetInterfaceName(int intNumber
, char *intName
);
233 UINT16
wsaErrno(void);
234 UINT16
wsaHerrno(int errnr
);
236 static HANDLE _WSHeap
= 0;
238 #define WS_ALLOC(size) \
239 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
240 #define WS_FREE(ptr) \
241 HeapFree(_WSHeap, 0, (ptr) )
243 #define MAP_OPTION(opt) { WS_##opt, opt }
245 static const int ws_sock_map
[][2] =
247 MAP_OPTION( SO_DEBUG
),
248 MAP_OPTION( SO_REUSEADDR
),
249 MAP_OPTION( SO_KEEPALIVE
),
250 MAP_OPTION( SO_DONTROUTE
),
251 MAP_OPTION( SO_BROADCAST
),
252 MAP_OPTION( SO_LINGER
),
253 MAP_OPTION( SO_OOBINLINE
),
254 MAP_OPTION( SO_SNDBUF
),
255 MAP_OPTION( SO_RCVBUF
),
256 MAP_OPTION( SO_ERROR
),
257 MAP_OPTION( SO_TYPE
),
259 MAP_OPTION( SO_RCVTIMEO
),
262 MAP_OPTION( SO_SNDTIMEO
),
267 static const int ws_tcp_map
[][2] =
270 MAP_OPTION( TCP_NODELAY
),
275 static const int ws_ip_map
[][2] =
277 MAP_OPTION( IP_MULTICAST_IF
),
278 MAP_OPTION( IP_MULTICAST_TTL
),
279 MAP_OPTION( IP_MULTICAST_LOOP
),
280 MAP_OPTION( IP_ADD_MEMBERSHIP
),
281 MAP_OPTION( IP_DROP_MEMBERSHIP
),
282 MAP_OPTION( IP_OPTIONS
),
283 MAP_OPTION( IP_HDRINCL
),
284 MAP_OPTION( IP_TOS
),
285 MAP_OPTION( IP_TTL
),
289 static DWORD opentype_tls_index
= -1; /* TLS index for SO_OPENTYPE flag */
291 inline static DWORD
NtStatusToWSAError ( const DWORD status
)
293 /* We only need to cover the status codes set by server async request handling */
297 case STATUS_SUCCESS
: wserr
= 0; break;
298 case STATUS_PENDING
: wserr
= WSA_IO_PENDING
; break;
299 case STATUS_INVALID_HANDLE
: wserr
= WSAENOTSOCK
; break; /* WSAEBADF ? */
300 case STATUS_INVALID_PARAMETER
: wserr
= WSAEINVAL
; break;
301 case STATUS_PIPE_DISCONNECTED
: wserr
= WSAESHUTDOWN
; break;
302 case STATUS_CANCELLED
: wserr
= WSA_OPERATION_ABORTED
; break;
303 case STATUS_TIMEOUT
: wserr
= WSAETIMEDOUT
; break;
304 case STATUS_NO_MEMORY
: wserr
= WSAEFAULT
; break;
306 if ( status
>= WSABASEERR
&& status
<= WSABASEERR
+1004 )
307 /* It is not a NT status code but a winsock error */
311 wserr
= RtlNtStatusToDosError( status
);
312 FIXME ( "Status code %08lx converted to DOS error code %lx\n", status
, wserr
);
318 /* set last error code from NT status without mapping WSA errors */
319 inline static unsigned int set_error( unsigned int err
)
323 err
= NtStatusToWSAError ( err
);
329 static char* check_buffer(int size
);
331 inline static int _get_sock_fd(SOCKET s
)
335 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s
), GENERIC_READ
, &fd
, NULL
, NULL
) ))
340 inline static int _get_sock_fd_type( SOCKET s
, DWORD access
, enum fd_type
*type
, int *flags
)
343 if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s
), access
, &fd
, type
, flags
) )) return -1;
344 if ( ( (access
& GENERIC_READ
) && (*flags
& FD_FLAG_RECV_SHUTDOWN
) ) ||
345 ( (access
& GENERIC_WRITE
) && (*flags
& FD_FLAG_SEND_SHUTDOWN
) ) )
348 WSASetLastError ( WSAESHUTDOWN
);
354 static void _enable_event( HANDLE s
, unsigned int event
,
355 unsigned int sstate
, unsigned int cstate
)
357 SERVER_START_REQ( enable_socket_event
)
361 req
->sstate
= sstate
;
362 req
->cstate
= cstate
;
363 wine_server_call( req
);
368 static int _is_blocking(SOCKET s
)
371 SERVER_START_REQ( get_socket_event
)
373 req
->handle
= SOCKET2HANDLE(s
);
374 req
->service
= FALSE
;
376 wine_server_call( req
);
377 ret
= (reply
->state
& FD_WINE_NONBLOCKING
) == 0;
383 static unsigned int _get_sock_mask(SOCKET s
)
386 SERVER_START_REQ( get_socket_event
)
388 req
->handle
= SOCKET2HANDLE(s
);
389 req
->service
= FALSE
;
391 wine_server_call( req
);
398 static void _sync_sock_state(SOCKET s
)
400 /* do a dummy wineserver request in order to let
401 the wineserver run through its select loop once */
402 (void)_is_blocking(s
);
405 static int _get_sock_error(SOCKET s
, unsigned int bit
)
407 int events
[FD_MAX_EVENTS
];
409 SERVER_START_REQ( get_socket_event
)
411 req
->handle
= SOCKET2HANDLE(s
);
412 req
->service
= FALSE
;
414 wine_server_set_reply( req
, events
, sizeof(events
) );
415 wine_server_call( req
);
421 static void WINSOCK_DeleteIData(void)
423 /* delete scratch buffers */
425 UnMapLS( he_buffer_seg
);
426 UnMapLS( se_buffer_seg
);
427 UnMapLS( pe_buffer_seg
);
428 UnMapLS( dbuffer_seg
);
429 if (he_buffer
) HeapFree( GetProcessHeap(), 0, he_buffer
);
430 if (se_buffer
) HeapFree( GetProcessHeap(), 0, se_buffer
);
431 if (pe_buffer
) HeapFree( GetProcessHeap(), 0, pe_buffer
);
432 if (local_buffer
) HeapFree( GetProcessHeap(), 0, local_buffer
);
444 /***********************************************************************
445 * DllMain (WS2_32.init)
447 BOOL WINAPI
DllMain(HINSTANCE hInstDLL
, DWORD fdwReason
, LPVOID fImpLoad
)
449 TRACE("%p 0x%lx %p\n", hInstDLL
, fdwReason
, fImpLoad
);
451 case DLL_PROCESS_ATTACH
:
452 opentype_tls_index
= TlsAlloc();
454 case DLL_PROCESS_DETACH
:
455 TlsFree( opentype_tls_index
);
456 WINSOCK_DeleteIData();
462 /***********************************************************************
465 * Converts socket flags from Windows format.
466 * Return 1 if converted, 0 if not (error).
468 static int convert_sockopt(INT
*level
, INT
*optname
)
475 for(i
=0; ws_sock_map
[i
][0]; i
++)
477 if( ws_sock_map
[i
][0] == *optname
)
479 *optname
= ws_sock_map
[i
][1];
483 FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname
);
486 *level
= IPPROTO_TCP
;
487 for(i
=0; ws_tcp_map
[i
][0]; i
++)
489 if ( ws_tcp_map
[i
][0] == *optname
)
491 *optname
= ws_tcp_map
[i
][1];
495 FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname
);
499 for(i
=0; ws_ip_map
[i
][0]; i
++)
501 if (ws_ip_map
[i
][0] == *optname
)
503 *optname
= ws_ip_map
[i
][1];
507 FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname
);
509 default: FIXME("Unimplemented or unknown socket level\n");
514 /* ----------------------------------- Per-thread info (or per-process?) */
516 static int wsi_strtolo(const char* name
, const char* opt
)
518 /* Stuff a lowercase copy of the string into the local buffer */
520 int i
= strlen(name
) + 2;
521 char* p
= check_buffer(i
+ ((opt
)?strlen(opt
):0));
525 do *p
++ = tolower(*name
); while(*name
++);
526 i
= (p
- local_buffer
);
527 if( opt
) do *p
++ = tolower(*opt
); while(*opt
++);
533 static fd_set
* fd_set_import( fd_set
* fds
, void* wsfds
, int* highfd
, int lfd
[], BOOL b32
)
535 /* translate Winsock fd set into local fd set */
539 #define wsfds16 ((ws_fd_set16*)wsfds)
540 #define wsfds32 ((WS_fd_set*)wsfds)
544 count
= b32
? wsfds32
->fd_count
: wsfds16
->fd_count
;
546 for( i
= 0; i
< count
; i
++ )
548 int s
= (b32
) ? wsfds32
->fd_array
[i
]
549 : wsfds16
->fd_array
[i
];
550 int fd
= _get_sock_fd(s
);
554 if( fd
> *highfd
) *highfd
= fd
;
566 inline static int sock_error_p(int s
)
568 unsigned int optval
, optlen
;
570 optlen
= sizeof(optval
);
571 getsockopt(s
, SOL_SOCKET
, SO_ERROR
, (void *) &optval
, &optlen
);
572 if (optval
) WARN("\t[%i] error: %d\n", s
, optval
);
576 static int fd_set_export( fd_set
* fds
, fd_set
* exceptfds
, void* wsfds
, int lfd
[], BOOL b32
)
580 /* translate local fd set into Winsock fd set, adding
581 * errors to exceptfds (only if app requested it) */
585 #define wsfds16 ((ws_fd_set16*)wsfds)
586 #define wsfds32 ((WS_fd_set*)wsfds)
587 int i
, j
, count
= (b32
) ? wsfds32
->fd_count
: wsfds16
->fd_count
;
589 for( i
= 0, j
= 0; i
< count
; i
++ )
594 if( FD_ISSET(fd
, fds
) )
596 if ( exceptfds
&& sock_error_p(fd
) )
598 FD_SET(fd
, exceptfds
);
602 wsfds32
->fd_array
[j
++] = wsfds32
->fd_array
[i
];
604 wsfds16
->fd_array
[j
++] = wsfds16
->fd_array
[i
];
611 if( b32
) wsfds32
->fd_count
= j
;
612 else wsfds16
->fd_count
= j
;
621 static void fd_set_unimport( void* wsfds
, int lfd
[], BOOL b32
)
625 #define wsfds16 ((ws_fd_set16*)wsfds)
626 #define wsfds32 ((WS_fd_set*)wsfds)
627 int i
, count
= (b32
) ? wsfds32
->fd_count
: wsfds16
->fd_count
;
629 for( i
= 0; i
< count
; i
++ )
639 static int do_block( int fd
, int mask
)
650 i
= select( fd
+1, &fds
[0], &fds
[1], &fds
[2], NULL
);
651 if (i
<= 0) return -1;
654 if (FD_ISSET(fd
, &fds
[i
]))
659 void* __ws_memalloc( int size
)
661 return WS_ALLOC(size
);
664 void __ws_memfree(void* ptr
)
670 /* ----------------------------------- API -----
672 * Init / cleanup / error checking.
675 /***********************************************************************
676 * WSAStartup (WINSOCK.115)
678 * Create socket control struct, attach it to the global list and
679 * update a pointer in the task struct.
681 INT16 WINAPI
WSAStartup16(UINT16 wVersionRequested
, LPWSADATA16 lpWSAData
)
683 static const WSADATA16 data
=
689 #elif defined(__NetBSD__)
693 #elif defined(__FreeBSD__)
695 #elif defined(__OpenBSD__)
700 WS_MAX_SOCKETS_PER_PROCESS
,
705 TRACE("verReq=%x\n", wVersionRequested
);
707 if (LOBYTE(wVersionRequested
) < 1 || (LOBYTE(wVersionRequested
) == 1 &&
708 HIBYTE(wVersionRequested
) < 1)) return WSAVERNOTSUPPORTED
;
710 if (!lpWSAData
) return WSAEINVAL
;
712 /* initialize socket heap */
716 _WSHeap
= HeapCreate(HEAP_ZERO_MEMORY
, 8120, 32768);
719 ERR("Fatal: failed to create WinSock heap\n");
723 if( _WSHeap
== 0 ) return WSASYSNOTREADY
;
727 /* return winsock information */
729 memcpy(lpWSAData
, &data
, sizeof(data
));
731 TRACE("succeeded\n");
735 /***********************************************************************
736 * WSAStartup (WS2_32.115)
738 int WINAPI
WSAStartup(WORD wVersionRequested
, LPWSADATA lpWSAData
)
740 TRACE("verReq=%x\n", wVersionRequested
);
742 if (LOBYTE(wVersionRequested
) < 1)
743 return WSAVERNOTSUPPORTED
;
745 if (!lpWSAData
) return WSAEINVAL
;
747 /* initialize socket heap */
751 _WSHeap
= HeapCreate(HEAP_ZERO_MEMORY
, 8120, 32768);
754 ERR("Fatal: failed to create WinSock heap\n");
758 if( _WSHeap
== 0 ) return WSASYSNOTREADY
;
762 /* that's the whole of the negotiation for now */
763 lpWSAData
->wVersion
= wVersionRequested
;
764 /* return winsock information */
765 lpWSAData
->wHighVersion
= 0x0202;
766 strcpy(lpWSAData
->szDescription
, "WinSock 2.0" );
767 strcpy(lpWSAData
->szSystemStatus
, "Running" );
768 lpWSAData
->iMaxSockets
= WS_MAX_SOCKETS_PER_PROCESS
;
769 lpWSAData
->iMaxUdpDg
= WS_MAX_UDP_DATAGRAM
;
770 /* don't do anything with lpWSAData->lpVendorInfo */
771 /* (some apps don't allocate the space for this field) */
773 TRACE("succeeded\n");
778 /***********************************************************************
779 * WSACleanup (WINSOCK.116)
780 * WSACleanup (WS2_32.116)
782 INT WINAPI
WSACleanup(void)
786 if (--num_startup
> 0) return 0;
787 WINSOCK_DeleteIData();
790 SetLastError(WSANOTINITIALISED
);
795 /***********************************************************************
796 * WSAGetLastError (WINSOCK.111)
797 * WSAGetLastError (WS2_32.111)
799 INT WINAPI
WSAGetLastError(void)
801 return GetLastError();
804 /***********************************************************************
805 * WSASetLastError (WS2_32.112)
807 void WINAPI
WSASetLastError(INT iError
) {
808 SetLastError(iError
);
811 /***********************************************************************
812 * WSASetLastError (WINSOCK.112)
814 void WINAPI
WSASetLastError16(INT16 iError
)
816 WSASetLastError(iError
);
819 static char* check_buffer(int size
)
821 static int local_buflen
;
825 if (local_buflen
>= size
) return local_buffer
;
826 HeapFree( GetProcessHeap(), 0, local_buffer
);
828 local_buffer
= HeapAlloc( GetProcessHeap(), 0, (local_buflen
= size
) );
832 static struct ws_hostent
* check_buffer_he(int size
)
837 if (he_len
>= size
) return he_buffer
;
838 UnMapLS( he_buffer_seg
);
839 HeapFree( GetProcessHeap(), 0, he_buffer
);
841 he_buffer
= HeapAlloc( GetProcessHeap(), 0, (he_len
= size
) );
842 he_buffer_seg
= MapLS( he_buffer
);
846 static void* check_buffer_se(int size
)
851 if (se_len
>= size
) return se_buffer
;
852 UnMapLS( se_buffer_seg
);
853 HeapFree( GetProcessHeap(), 0, se_buffer
);
855 se_buffer
= HeapAlloc( GetProcessHeap(), 0, (se_len
= size
) );
856 se_buffer_seg
= MapLS( se_buffer
);
860 static struct ws_protoent
* check_buffer_pe(int size
)
865 if (pe_len
>= size
) return pe_buffer
;
866 UnMapLS( pe_buffer_seg
);
867 HeapFree( GetProcessHeap(), 0, pe_buffer
);
869 pe_buffer
= HeapAlloc( GetProcessHeap(), 0, (pe_len
= size
) );
870 pe_buffer_seg
= MapLS( he_buffer
);
874 /* ----------------------------------- i/o APIs */
877 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
879 #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
883 /**********************************************************************/
885 /* Returns the converted address if successful, NULL if it was too small to
886 * start with. Note that the returned pointer may be the original pointer
887 * if no conversion is necessary.
889 static const struct sockaddr
* ws_sockaddr_ws2u(const struct WS_sockaddr
* wsaddr
, int wsaddrlen
, int *uaddrlen
)
891 switch (wsaddr
->sa_family
)
896 struct WS_sockaddr_ipx
* wsipx
=(struct WS_sockaddr_ipx
*)wsaddr
;
897 struct sockaddr_ipx
* uipx
;
899 if (wsaddrlen
<sizeof(struct WS_sockaddr_ipx
))
902 *uaddrlen
=sizeof(struct sockaddr_ipx
);
903 uipx
=malloc(*uaddrlen
);
904 uipx
->sipx_family
=AF_IPX
;
905 uipx
->sipx_port
=wsipx
->sa_socket
;
906 /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
909 memcpy(&uipx
->sipx_network
,wsipx
->sa_netnum
,sizeof(uipx
->sipx_network
)+sizeof(uipx
->sipx_node
));
910 #ifdef IPX_FRAME_NONE
911 uipx
->sipx_type
=IPX_FRAME_NONE
;
913 memset(&uipx
->sipx_zero
,0,sizeof uipx
->sipx_zero
);
914 return (const struct sockaddr
*)uipx
;
919 if (wsaddrlen
<sizeof(struct WS_sockaddr
))
922 /* No conversion needed, just return the original address */
924 return (const struct sockaddr
*)wsaddr
;
929 /* Allocates a Unix sockaddr structure to receive the data */
930 inline struct sockaddr
* ws_sockaddr_alloc(const struct WS_sockaddr
* wsaddr
, int* wsaddrlen
, int* uaddrlen
)
934 ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
936 /* This is not strictly the right thing to do. Hope it works however */
945 *uaddrlen
=max(sizeof(struct sockaddr
),*wsaddrlen
);
947 return malloc(*uaddrlen
);
950 /* Returns 0 if successful, -1 if the buffer is too small */
951 static int ws_sockaddr_u2ws(const struct sockaddr
* uaddr
, int uaddrlen
, struct WS_sockaddr
* wsaddr
, int* wsaddrlen
)
955 switch(uaddr
->sa_family
)
960 struct sockaddr_ipx
* uipx
=(struct sockaddr_ipx
*)uaddr
;
961 struct WS_sockaddr_ipx
* wsipx
=(struct WS_sockaddr_ipx
*)wsaddr
;
964 switch (*wsaddrlen
) /* how much can we copy? */
969 wsipx
->sa_socket
=uipx
->sipx_port
;
973 memcpy(wsipx
->sa_nodenum
,uipx
->sipx_node
,sizeof(wsipx
->sa_nodenum
));
981 memcpy(wsipx
->sa_netnum
,&uipx
->sipx_network
,sizeof(wsipx
->sa_netnum
));
987 wsipx
->sa_family
=WS_AF_IPX
;
999 /* No conversion needed */
1000 memcpy(wsaddr
,uaddr
,*wsaddrlen
);
1001 if (*wsaddrlen
<uaddrlen
) {
1004 *wsaddrlen
=uaddrlen
;
1011 /* to be called to free the memory allocated by ws_sockaddr_ws2u or
1014 inline void ws_sockaddr_free(const struct sockaddr
* uaddr
, const struct WS_sockaddr
* wsaddr
)
1016 if (uaddr
!=NULL
&& uaddr
!=(const struct sockaddr
*)wsaddr
)
1020 /**************************************************************************
1021 * Functions for handling overlapped I/O
1022 **************************************************************************/
1024 static DWORD
ws2_async_get_status (const struct async_private
*ovp
)
1026 return ((ws2_async
*) ovp
)->overlapped
->Internal
;
1029 static VOID
ws2_async_set_status (struct async_private
*ovp
, const DWORD status
)
1031 ((ws2_async
*) ovp
)->overlapped
->Internal
= status
;
1034 static DWORD
ws2_async_get_count (const struct async_private
*ovp
)
1036 return ((ws2_async
*) ovp
)->overlapped
->InternalHigh
;
1039 static void ws2_async_cleanup ( struct async_private
*ap
)
1041 struct ws2_async
*as
= (struct ws2_async
*) ap
;
1043 TRACE ( "as: %p uovl %p ovl %p\n", as
, as
->user_overlapped
, as
->overlapped
);
1044 if ( !as
->user_overlapped
)
1046 if ( as
->overlapped
->hEvent
!= INVALID_HANDLE_VALUE
)
1047 WSACloseEvent ( as
->overlapped
->hEvent
);
1048 HeapFree ( GetProcessHeap(), 0, as
->overlapped
);
1052 HeapFree ( GetProcessHeap(), 0, as
->iovec
);
1054 HeapFree ( GetProcessHeap(), 0, as
);
1057 static void CALLBACK
ws2_async_call_completion (ULONG_PTR data
)
1059 ws2_async
* as
= (ws2_async
*) data
;
1061 TRACE ("data: %p\n", as
);
1063 as
->completion_func ( NtStatusToWSAError (as
->overlapped
->Internal
),
1064 as
->overlapped
->InternalHigh
,
1065 as
->user_overlapped
,
1067 ws2_async_cleanup ( &as
->async
);
1070 /***********************************************************************
1071 * WS2_make_async (INTERNAL)
1074 static void WS2_async_recv (async_private
*as
);
1075 static void WS2_async_send (async_private
*as
);
1077 inline static struct ws2_async
*
1078 WS2_make_async (SOCKET s
, int fd
, int type
, struct iovec
*iovec
, DWORD dwBufferCount
,
1079 LPDWORD lpFlags
, struct WS_sockaddr
*addr
,
1080 LPINT addrlen
, LPWSAOVERLAPPED lpOverlapped
,
1081 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
1083 struct ws2_async
*wsa
= HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async
) );
1085 TRACE ( "wsa %p\n", wsa
);
1090 wsa
->async
.ops
= ( lpCompletionRoutine
? &ws2_async_ops
: &ws2_nocomp_async_ops
);
1091 wsa
->async
.handle
= (HANDLE
) s
;
1093 wsa
->async
.type
= type
;
1096 case ASYNC_TYPE_READ
:
1097 wsa
->flags
= *lpFlags
;
1098 wsa
->async
.func
= WS2_async_recv
;
1099 wsa
->addrlen
.ptr
= addrlen
;
1101 case ASYNC_TYPE_WRITE
:
1103 wsa
->async
.func
= WS2_async_send
;
1104 wsa
->addrlen
.val
= *addrlen
;
1107 ERR ("Invalid async type: %d\n", type
);
1109 wsa
->user_overlapped
= lpOverlapped
;
1110 wsa
->completion_func
= lpCompletionRoutine
;
1112 wsa
->n_iovecs
= dwBufferCount
;
1117 wsa
->overlapped
= lpOverlapped
;
1118 wsa
->async
.event
= ( lpCompletionRoutine
? INVALID_HANDLE_VALUE
: lpOverlapped
->hEvent
);
1122 wsa
->overlapped
= HeapAlloc ( GetProcessHeap(), 0,
1123 sizeof (WSAOVERLAPPED
) );
1124 if ( !wsa
->overlapped
)
1126 wsa
->async
.event
= wsa
->overlapped
->hEvent
= INVALID_HANDLE_VALUE
;
1129 wsa
->overlapped
->InternalHigh
= 0;
1130 TRACE ( "wsa %p, ops %p, h %p, ev %p, fd %d, func %p, ov %p, uov %p, cfunc %p\n",
1131 wsa
, wsa
->async
.ops
, wsa
->async
.handle
, wsa
->async
.event
, wsa
->async
.fd
, wsa
->async
.func
,
1132 wsa
->overlapped
, wsa
->user_overlapped
, wsa
->completion_func
);
1138 HeapFree ( GetProcessHeap(), 0, wsa
);
1142 /***********************************************************************
1143 * WS2_recv (INTERNAL)
1145 * Work horse for both synchronous and asynchronous recv() operations.
1147 static int WS2_recv ( int fd
, struct iovec
* iov
, int count
,
1148 struct WS_sockaddr
*lpFrom
, LPINT lpFromlen
,
1153 TRACE ( "fd %d, iovec %p, count %d addr %p, len %p, flags %lx\n",
1154 fd
, iov
, count
, lpFrom
, lpFromlen
, *lpFlags
);
1156 hdr
.msg_name
= NULL
;
1161 dump_sockaddr (lpFrom
);
1164 hdr
.msg_namelen
= *lpFromlen
;
1165 hdr
.msg_name
= ws_sockaddr_alloc ( lpFrom
, lpFromlen
, &hdr
.msg_namelen
);
1166 if ( !hdr
.msg_name
)
1168 WSASetLastError ( WSAEFAULT
);
1174 hdr
.msg_namelen
= 0;
1177 hdr
.msg_iovlen
= count
;
1178 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1179 hdr
.msg_accrights
= NULL
;
1180 hdr
.msg_accrightslen
= 0;
1182 hdr
.msg_control
= NULL
;
1183 hdr
.msg_controllen
= 0;
1187 if ( (n
= recvmsg (fd
, &hdr
, *lpFlags
)) == -1 )
1189 TRACE ( "recvmsg error %d\n", errno
);
1194 ws_sockaddr_u2ws ( hdr
.msg_name
, hdr
.msg_namelen
,
1195 lpFrom
, lpFromlen
) != 0 )
1197 /* The from buffer was too small, but we read the data
1198 * anyway. Is that really bad?
1200 WSASetLastError ( WSAEFAULT
);
1201 WARN ( "Address buffer too small\n" );
1206 ws_sockaddr_free ( hdr
.msg_name
, lpFrom
);
1207 TRACE ("-> %d\n", n
);
1211 /***********************************************************************
1212 * WS2_async_recv (INTERNAL)
1214 * Handler for overlapped recv() operations.
1216 static void WS2_async_recv ( async_private
*as
)
1218 ws2_async
* wsa
= (ws2_async
*) as
;
1221 TRACE ( "async %p\n", wsa
);
1223 if ( wsa
->overlapped
->Internal
!= STATUS_PENDING
)
1225 TRACE ( "status: %ld\n", wsa
->overlapped
->Internal
);
1229 result
= WS2_recv ( wsa
->async
.fd
, wsa
->iovec
, wsa
->n_iovecs
,
1230 wsa
->addr
, wsa
->addrlen
.ptr
, &wsa
->flags
);
1234 wsa
->overlapped
->Internal
= STATUS_SUCCESS
;
1235 wsa
->overlapped
->InternalHigh
= result
;
1236 TRACE ( "received %d bytes\n", result
);
1237 _enable_event ( wsa
->async
.handle
, FD_READ
, 0, 0 );
1242 if ( err
== WSAEINTR
|| err
== WSAEWOULDBLOCK
) /* errno: EINTR / EAGAIN */
1244 wsa
->overlapped
->Internal
= STATUS_PENDING
;
1245 _enable_event ( wsa
->async
.handle
, FD_READ
, 0, 0 );
1246 TRACE ( "still pending\n" );
1250 wsa
->overlapped
->Internal
= err
;
1251 TRACE ( "Error: %x\n", err
);
1255 /***********************************************************************
1256 * WS2_send (INTERNAL)
1258 * Work horse for both synchronous and asynchronous send() operations.
1260 static int WS2_send ( int fd
, struct iovec
* iov
, int count
,
1261 const struct WS_sockaddr
*to
, INT tolen
, DWORD dwFlags
)
1265 TRACE ( "fd %d, iovec %p, count %d addr %p, len %d, flags %lx\n",
1266 fd
, iov
, count
, to
, tolen
, dwFlags
);
1268 hdr
.msg_name
= NULL
;
1275 hdr
.msg_name
= (struct sockaddr
*) ws_sockaddr_ws2u ( to
, tolen
, &hdr
.msg_namelen
);
1276 if ( !hdr
.msg_name
)
1278 WSASetLastError ( WSAEFAULT
);
1283 hdr
.msg_namelen
= 0;
1286 hdr
.msg_iovlen
= count
;
1287 #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1288 hdr
.msg_accrights
= NULL
;
1289 hdr
.msg_accrightslen
= 0;
1291 hdr
.msg_control
= NULL
;
1292 hdr
.msg_controllen
= 0;
1296 n
= sendmsg (fd
, &hdr
, dwFlags
);
1299 ws_sockaddr_free ( hdr
.msg_name
, to
);
1303 /***********************************************************************
1304 * WS2_async_send (INTERNAL)
1306 * Handler for overlapped send() operations.
1308 static void WS2_async_send ( async_private
*as
)
1310 ws2_async
* wsa
= (ws2_async
*) as
;
1313 TRACE ( "async %p\n", wsa
);
1315 if ( wsa
->overlapped
->Internal
!= STATUS_PENDING
)
1317 TRACE ( "status: %ld\n", wsa
->overlapped
->Internal
);
1321 result
= WS2_send ( wsa
->async
.fd
, wsa
->iovec
, wsa
->n_iovecs
,
1322 wsa
->addr
, wsa
->addrlen
.val
, wsa
->flags
);
1326 wsa
->overlapped
->Internal
= STATUS_SUCCESS
;
1327 wsa
->overlapped
->InternalHigh
= result
;
1328 TRACE ( "sent %d bytes\n", result
);
1329 _enable_event ( wsa
->async
.handle
, FD_WRITE
, 0, 0 );
1334 if ( err
== WSAEINTR
)
1336 wsa
->overlapped
->Internal
= STATUS_PENDING
;
1337 _enable_event ( wsa
->async
.handle
, FD_WRITE
, 0, 0 );
1338 TRACE ( "still pending\n" );
1342 /* We set the status to a winsock error code and check for that
1343 later in NtStatusToWSAError () */
1344 wsa
->overlapped
->Internal
= err
;
1345 TRACE ( "Error: %x\n", err
);
1349 /***********************************************************************
1350 * WS2_async_shutdown (INTERNAL)
1352 * Handler for shutdown() operations on overlapped sockets.
1354 static void WS2_async_shutdown ( async_private
*as
)
1356 ws2_async
* wsa
= (ws2_async
*) as
;
1359 TRACE ( "async %p %d\n", wsa
, wsa
->async
.type
);
1360 switch ( wsa
->async
.type
)
1362 case ASYNC_TYPE_READ
:
1363 err
= shutdown ( wsa
->async
.fd
, 0 );
1365 case ASYNC_TYPE_WRITE
:
1366 err
= shutdown ( wsa
->async
.fd
, 1 );
1369 ERR ("invalid type: %d\n", wsa
->async
.type
);
1373 wsa
->overlapped
->Internal
= wsaErrno ();
1375 wsa
->overlapped
->Internal
= STATUS_SUCCESS
;
1378 /***********************************************************************
1379 * WS2_register_async_shutdown (INTERNAL)
1381 * Helper function for WS_shutdown() on overlapped sockets.
1383 static int WS2_register_async_shutdown ( SOCKET s
, int fd
, int type
)
1385 struct ws2_async
*wsa
;
1386 int ret
, err
= WSAEFAULT
;
1389 LPWSAOVERLAPPED ovl
= HeapAlloc (GetProcessHeap(), 0, sizeof ( WSAOVERLAPPED
));
1391 TRACE ("s %d fd %d type %d\n", s
, fd
, type
);
1395 ovl
->hEvent
= WSACreateEvent ();
1396 if ( ovl
->hEvent
== WSA_INVALID_EVENT
)
1399 wsa
= WS2_make_async ( s
, fd
, type
, NULL
, 0,
1400 &dwflags
, NULL
, &len
, ovl
, NULL
);
1404 /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
1405 wsa
->user_overlapped
= NULL
;
1406 wsa
->async
.func
= WS2_async_shutdown
;
1407 if ( (ret
= register_new_async ( &wsa
->async
)) )
1409 err
= NtStatusToWSAError ( ret
);
1412 /* Try immediate completion */
1413 while ( WaitForSingleObjectEx ( ovl
->hEvent
, 0, TRUE
) == STATUS_USER_APC
);
1417 WSACloseEvent ( ovl
->hEvent
);
1419 HeapFree ( GetProcessHeap(), 0, ovl
);
1424 /***********************************************************************
1427 SOCKET WINAPI
WS_accept(SOCKET s
, struct WS_sockaddr
*addr
,
1430 int fd
= _get_sock_fd(s
);
1432 TRACE("socket %04x\n", (UINT16
)s
);
1436 if (_is_blocking(s
))
1440 _sync_sock_state(s
); /* let wineserver notice connection */
1441 /* retrieve any error codes from it */
1442 SetLastError(_get_sock_error(s
, FD_ACCEPT_BIT
));
1443 /* FIXME: care about the error? */
1446 SERVER_START_REQ( accept_socket
)
1448 req
->lhandle
= SOCKET2HANDLE(s
);
1449 req
->access
= GENERIC_READ
|GENERIC_WRITE
|SYNCHRONIZE
;
1450 req
->inherit
= TRUE
;
1451 set_error( wine_server_call( req
) );
1452 as
= HANDLE2SOCKET( reply
->handle
);
1458 WS_getpeername(as
, addr
, addrlen32
);
1464 SetLastError(WSAENOTSOCK
);
1466 return INVALID_SOCKET
;
1469 /***********************************************************************
1470 * accept (WINSOCK.1)
1472 SOCKET16 WINAPI
WINSOCK_accept16(SOCKET16 s
, struct WS_sockaddr
* addr
,
1475 INT addrlen32
= addrlen16
? *addrlen16
: 0;
1476 SOCKET retSocket
= WS_accept( s
, addr
, &addrlen32
);
1477 if( addrlen16
) *addrlen16
= (INT16
)addrlen32
;
1478 return (SOCKET16
)retSocket
;
1481 /***********************************************************************
1484 int WINAPI
WS_bind(SOCKET s
, const struct WS_sockaddr
* name
, int namelen
)
1486 int fd
= _get_sock_fd(s
);
1489 TRACE("socket %04x, ptr %p, length %d\n", s
, name
, namelen
);
1491 dump_sockaddr(name
);
1497 if (!name
|| !SUPPORTED_PF(name
->sa_family
))
1499 SetLastError(WSAEAFNOSUPPORT
);
1503 const struct sockaddr
* uaddr
;
1506 uaddr
=ws_sockaddr_ws2u(name
,namelen
,&uaddrlen
);
1509 SetLastError(WSAEFAULT
);
1514 /* The game GrandPrixLegends binds more than one time, but does
1515 * not do a SO_REUSEADDR - Stevens says this is ok */
1516 TRACE( "Setting WS_SO_REUSEADDR on socket before we bind it\n");
1517 WS_setsockopt( s
, WS_SOL_SOCKET
, WS_SO_REUSEADDR
, (char*)&on
, sizeof(on
) );
1519 if (bind(fd
, uaddr
, uaddrlen
) < 0)
1521 int loc_errno
= errno
;
1522 WARN("\tfailure - errno = %i\n", errno
);
1527 SetLastError(WSAENOTSOCK
);
1530 SetLastError(WSAEINVAL
);
1533 SetLastError(wsaErrno());
1539 res
=0; /* success */
1541 ws_sockaddr_free(uaddr
,name
);
1548 SetLastError(WSAENOTSOCK
);
1553 /***********************************************************************
1556 INT16 WINAPI
WINSOCK_bind16(SOCKET16 s
, struct WS_sockaddr
*name
, INT16 namelen
)
1558 return (INT16
)WS_bind( s
, name
, namelen
);
1561 /***********************************************************************
1562 * closesocket (WS2_32.3)
1564 int WINAPI
WS_closesocket(SOCKET s
)
1566 TRACE("socket %08x\n", s
);
1567 if (CloseHandle(SOCKET2HANDLE(s
))) return 0;
1568 return SOCKET_ERROR
;
1571 /***********************************************************************
1572 * closesocket (WINSOCK.3)
1574 INT16 WINAPI
WINSOCK_closesocket16(SOCKET16 s
)
1576 return (INT16
)WS_closesocket(s
);
1579 /***********************************************************************
1580 * connect (WS2_32.4)
1582 int WINAPI
WS_connect(SOCKET s
, const struct WS_sockaddr
* name
, int namelen
)
1584 int fd
= _get_sock_fd(s
);
1586 TRACE("socket %04x, ptr %p, length %d\n", s
, name
, namelen
);
1588 dump_sockaddr(name
);
1593 const struct sockaddr
* uaddr
;
1596 uaddr
=ws_sockaddr_ws2u(name
,namelen
,&uaddrlen
);
1599 SetLastError(WSAEFAULT
);
1605 rc
=connect(fd
, uaddr
, uaddrlen
);
1606 ws_sockaddr_free(uaddr
,name
);
1608 goto connect_success
;
1611 if (errno
== EINPROGRESS
)
1613 /* tell wineserver that a connection is in progress */
1614 _enable_event(SOCKET2HANDLE(s
), FD_CONNECT
|FD_READ
|FD_WRITE
,
1615 FD_CONNECT
|FD_READ
|FD_WRITE
,
1616 FD_WINE_CONNECTED
|FD_WINE_LISTENING
);
1617 if (_is_blocking(s
))
1622 _sync_sock_state(s
); /* let wineserver notice connection */
1623 /* retrieve any error codes from it */
1624 result
= _get_sock_error(s
, FD_CONNECT_BIT
);
1626 SetLastError(result
);
1629 goto connect_success
;
1634 SetLastError(WSAEWOULDBLOCK
);
1639 SetLastError(wsaErrno());
1645 SetLastError(WSAENOTSOCK
);
1647 return SOCKET_ERROR
;
1651 _enable_event(SOCKET2HANDLE(s
), FD_CONNECT
|FD_READ
|FD_WRITE
,
1652 FD_WINE_CONNECTED
|FD_READ
|FD_WRITE
,
1653 FD_CONNECT
|FD_WINE_LISTENING
);
1657 /***********************************************************************
1658 * connect (WINSOCK.4)
1660 INT16 WINAPI
WINSOCK_connect16(SOCKET16 s
, struct WS_sockaddr
*name
, INT16 namelen
)
1662 return (INT16
)WS_connect( s
, name
, namelen
);
1665 /***********************************************************************
1666 * WSAConnect (WS2_32.30)
1668 int WINAPI
WSAConnect ( SOCKET s
, const struct WS_sockaddr
* name
, int namelen
,
1669 LPWSABUF lpCallerData
, LPWSABUF lpCalleeData
,
1670 LPQOS lpSQOS
, LPQOS lpGQOS
)
1672 if ( lpCallerData
|| lpCalleeData
|| lpSQOS
|| lpGQOS
)
1673 FIXME ("unsupported parameters!\n");
1674 return WS_connect ( s
, name
, namelen
);
1678 /***********************************************************************
1679 * getpeername (WS2_32.5)
1681 int WINAPI
WS_getpeername(SOCKET s
, struct WS_sockaddr
*name
, int *namelen
)
1686 TRACE("socket: %04x, ptr %p, len %8x\n", s
, name
, *namelen
);
1688 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1689 if( (name
== NULL
) || (namelen
== NULL
) )
1691 SetLastError( WSAEFAULT
);
1692 return SOCKET_ERROR
;
1695 fd
= _get_sock_fd(s
);
1700 struct sockaddr
* uaddr
;
1703 uaddr
=ws_sockaddr_alloc(name
,namelen
,&uaddrlen
);
1704 if (getpeername(fd
, uaddr
, &uaddrlen
) != 0)
1706 SetLastError(wsaErrno());
1708 else if (ws_sockaddr_u2ws(uaddr
,uaddrlen
,name
,namelen
) != 0)
1710 /* The buffer was too small */
1711 SetLastError(WSAEFAULT
);
1717 ws_sockaddr_free(uaddr
,name
);
1722 SetLastError(WSAENOTSOCK
);
1727 /***********************************************************************
1728 * getpeername (WINSOCK.5)
1730 INT16 WINAPI
WINSOCK_getpeername16(SOCKET16 s
, struct WS_sockaddr
*name
,
1733 INT namelen32
= *namelen16
;
1734 INT retVal
= WS_getpeername( s
, name
, &namelen32
);
1737 dump_sockaddr(name
);
1740 *namelen16
= namelen32
;
1741 return (INT16
)retVal
;
1744 /***********************************************************************
1745 * getsockname (WS2_32.6)
1747 int WINAPI
WS_getsockname(SOCKET s
, struct WS_sockaddr
*name
, int *namelen
)
1752 TRACE("socket: %04x, ptr %p, len %8x\n", s
, name
, *namelen
);
1754 /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1755 if( (name
== NULL
) || (namelen
== NULL
) )
1757 SetLastError( WSAEFAULT
);
1758 return SOCKET_ERROR
;
1761 fd
= _get_sock_fd(s
);
1766 struct sockaddr
* uaddr
;
1769 uaddr
=ws_sockaddr_alloc(name
,namelen
,&uaddrlen
);
1770 if (getsockname(fd
, uaddr
, &uaddrlen
) != 0)
1772 SetLastError(wsaErrno());
1774 else if (ws_sockaddr_u2ws(uaddr
,uaddrlen
,name
,namelen
) != 0)
1776 /* The buffer was too small */
1777 SetLastError(WSAEFAULT
);
1787 SetLastError(WSAENOTSOCK
);
1792 /***********************************************************************
1793 * getsockname (WINSOCK.6)
1795 INT16 WINAPI
WINSOCK_getsockname16(SOCKET16 s
, struct WS_sockaddr
*name
,
1802 INT namelen32
= *namelen16
;
1803 retVal
= WS_getsockname( s
, name
, &namelen32
);
1804 *namelen16
= namelen32
;
1807 dump_sockaddr(name
);
1811 else retVal
= SOCKET_ERROR
;
1812 return (INT16
)retVal
;
1816 /***********************************************************************
1817 * getsockopt (WS2_32.7)
1819 INT WINAPI
WS_getsockopt(SOCKET s
, INT level
,
1820 INT optname
, char *optval
, INT
*optlen
)
1824 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s
, level
,
1825 (int) optname
, (int) optval
, (int) *optlen
);
1826 /* SO_OPENTYPE does not require a valid socket handle. */
1827 if (level
== WS_SOL_SOCKET
&& optname
== WS_SO_OPENTYPE
)
1829 if (!optlen
|| *optlen
< sizeof(int) || !optval
)
1831 SetLastError(WSAEFAULT
);
1832 return SOCKET_ERROR
;
1834 *(int *)optval
= (int)TlsGetValue( opentype_tls_index
);
1835 *optlen
= sizeof(int);
1836 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval
) );
1840 fd
= _get_sock_fd(s
);
1843 if (!convert_sockopt(&level
, &optname
)) {
1844 SetLastError(WSAENOPROTOOPT
); /* Unknown option */
1846 if (getsockopt(fd
, (int) level
, optname
, optval
, optlen
) == 0 )
1851 SetLastError((errno
== EBADF
) ? WSAENOTSOCK
: wsaErrno());
1855 return SOCKET_ERROR
;
1859 /***********************************************************************
1860 * getsockopt (WINSOCK.7)
1862 INT16 WINAPI
WINSOCK_getsockopt16(SOCKET16 s
, INT16 level
,
1863 INT16 optname
, char *optval
, INT16
*optlen
)
1868 if( optlen
) optlen32
= *optlen
; else p
= NULL
;
1869 retVal
= WS_getsockopt( s
, (UINT16
)level
, optname
, optval
, p
);
1870 if( optlen
) *optlen
= optlen32
;
1871 return (INT16
)retVal
;
1875 /***********************************************************************
1879 u_long WINAPI
WS_htonl(u_long hostlong
)
1881 return htonl(hostlong
);
1885 /***********************************************************************
1889 u_short WINAPI
WS_htons(u_short hostshort
)
1891 return htons(hostshort
);
1895 /***********************************************************************
1896 * inet_addr (WINSOCK.10)
1897 * inet_addr (WS2_32.11)
1899 u_long WINAPI
WS_inet_addr(const char *cp
)
1901 return inet_addr(cp
);
1905 /***********************************************************************
1906 * ntohl (WINSOCK.14)
1909 u_long WINAPI
WS_ntohl(u_long netlong
)
1911 return ntohl(netlong
);
1915 /***********************************************************************
1916 * ntohs (WINSOCK.15)
1919 u_short WINAPI
WS_ntohs(u_short netshort
)
1921 return ntohs(netshort
);
1925 /***********************************************************************
1926 * inet_ntoa (WS2_32.12)
1928 char* WINAPI
WS_inet_ntoa(struct WS_in_addr in
)
1930 /* use "buffer for dummies" here because some applications have
1931 * propensity to decode addresses in ws_hostent structure without
1932 * saving them first...
1934 static char dbuffer
[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1936 char* s
= inet_ntoa(*((struct in_addr
*)&in
));
1942 SetLastError(wsaErrno());
1946 /***********************************************************************
1947 * inet_ntoa (WINSOCK.11)
1949 SEGPTR WINAPI
WINSOCK_inet_ntoa16(struct in_addr in
)
1952 if (!(retVal
= WS_inet_ntoa(*((struct WS_in_addr
*)&in
)))) return 0;
1953 if (!dbuffer_seg
) dbuffer_seg
= MapLS( retVal
);
1958 /**********************************************************************
1959 * WSAIoctl (WS2_32.50)
1962 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1964 INT WINAPI
WSAIoctl (SOCKET s
,
1965 DWORD dwIoControlCode
,
1968 LPVOID lpbOutBuffer
,
1970 LPDWORD lpcbBytesReturned
,
1971 LPWSAOVERLAPPED lpOverlapped
,
1972 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
1974 int fd
= _get_sock_fd(s
);
1978 switch( dwIoControlCode
)
1980 case SIO_GET_INTERFACE_LIST
:
1982 INTERFACE_INFO
* intArray
= (INTERFACE_INFO
*)lpbOutBuffer
;
1983 DWORD size
, numInt
, apiReturn
;
1985 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1986 /* FIXME: length of output buffer not checked */
1988 apiReturn
= GetAdaptersInfo(NULL
, &size
);
1989 if (apiReturn
== ERROR_NO_DATA
)
1993 else if (apiReturn
== ERROR_BUFFER_OVERFLOW
)
1995 PIP_ADAPTER_INFO table
= (PIP_ADAPTER_INFO
)HeapAlloc(GetProcessHeap(),0,size
);
1999 if (GetAdaptersInfo(table
, &size
) == NO_ERROR
)
2001 PIP_ADAPTER_INFO ptr
;
2003 for (ptr
= table
, numInt
= 0; ptr
;
2004 ptr
= ptr
->Next
, intArray
++, numInt
++)
2006 unsigned int addr
, mask
, bcast
;
2007 struct ifreq ifInfo
;
2009 /* Socket Status Flags */
2010 strncpy(ifInfo
.ifr_name
, ptr
->AdapterName
, IFNAMSIZ
);
2011 ifInfo
.ifr_name
[IFNAMSIZ
-1] = '\0';
2012 if (ioctl(fd
, SIOCGIFFLAGS
, &ifInfo
) < 0)
2014 ERR ("Error obtaining status flags for socket!\n");
2015 HeapFree(GetProcessHeap(),0,table
);
2017 WSASetLastError(WSAEINVAL
);
2018 return (SOCKET_ERROR
);
2022 /* set flags; the values of IFF_* are not the same
2023 under Linux and Windows, therefore must generate
2025 intArray
->iiFlags
= 0;
2026 if (ifInfo
.ifr_flags
& IFF_BROADCAST
)
2027 intArray
->iiFlags
|= WS_IFF_BROADCAST
;
2028 if (ifInfo
.ifr_flags
& IFF_POINTOPOINT
)
2029 intArray
->iiFlags
|= WS_IFF_POINTTOPOINT
;
2030 if (ifInfo
.ifr_flags
& IFF_LOOPBACK
)
2031 intArray
->iiFlags
|= WS_IFF_LOOPBACK
;
2032 if (ifInfo
.ifr_flags
& IFF_UP
)
2033 intArray
->iiFlags
|= WS_IFF_UP
;
2036 addr
= inet_addr(ptr
->IpAddressList
.IpAddress
.String
);
2037 mask
= inet_addr(ptr
->IpAddressList
.IpMask
.String
);
2038 bcast
= addr
| (addr
& !mask
);
2039 intArray
->iiAddress
.AddressIn
.sin_family
= AF_INET
;
2040 intArray
->iiAddress
.AddressIn
.sin_port
= 0;
2041 intArray
->iiAddress
.AddressIn
.sin_addr
.WS_s_addr
=
2043 intArray
->iiNetmask
.AddressIn
.sin_family
= AF_INET
;
2044 intArray
->iiNetmask
.AddressIn
.sin_port
= 0;
2045 intArray
->iiNetmask
.AddressIn
.sin_addr
.WS_s_addr
=
2047 intArray
->iiBroadcastAddress
.AddressIn
.sin_family
=
2049 intArray
->iiBroadcastAddress
.AddressIn
.sin_port
= 0;
2050 intArray
->iiBroadcastAddress
.AddressIn
.sin_addr
.
2053 HeapFree(GetProcessHeap(),0,table
);
2057 ERR ("Unable to get interface table!\n");
2059 HeapFree(GetProcessHeap(),0,table
);
2060 WSASetLastError(WSAEINVAL
);
2061 return (SOCKET_ERROR
);
2067 WSASetLastError(WSAEINVAL
);
2068 return (SOCKET_ERROR
);
2073 ERR ("Unable to get interface table!\n");
2075 WSASetLastError(WSAEINVAL
);
2076 return (SOCKET_ERROR
);
2078 /* Calculate the size of the array being returned */
2079 *lpcbBytesReturned
= sizeof(INTERFACE_INFO
) * numInt
;
2085 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode
);
2087 WSASetLastError(WSAEOPNOTSUPP
);
2088 return (SOCKET_ERROR
);
2092 /* Function executed with no errors */
2098 WSASetLastError(WSAENOTSOCK
);
2099 return (SOCKET_ERROR
);
2104 /***********************************************************************
2105 * ioctlsocket (WS2_32.10)
2107 int WINAPI
WS_ioctlsocket(SOCKET s
, long cmd
, u_long
*argp
)
2109 int fd
= _get_sock_fd(s
);
2111 TRACE("socket %04x, cmd %08lx, ptr %8x\n", s
, cmd
, (unsigned) argp
);
2124 if( _get_sock_mask(s
) )
2126 /* AsyncSelect()'ed sockets are always nonblocking */
2131 SetLastError(WSAEINVAL
);
2133 return SOCKET_ERROR
;
2137 _enable_event(SOCKET2HANDLE(s
), 0, FD_WINE_NONBLOCKING
, 0);
2139 _enable_event(SOCKET2HANDLE(s
), 0, 0, FD_WINE_NONBLOCKING
);
2146 case WS__IOW('f',125,u_long
):
2147 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2148 SetLastError(WSAEINVAL
);
2149 return SOCKET_ERROR
;
2151 case SIOCGIFBRDADDR
:
2152 case SIOCGIFNETMASK
:
2154 /* These don't need any special handling. They are used by
2155 WsControl, and are here to suppress an unecessary warning. */
2160 /* Netscape tries hard to use bogus ioctl 0x667e */
2161 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd
);
2163 if( ioctl(fd
, newcmd
, (char*)argp
) == 0 )
2168 SetLastError((errno
== EBADF
) ? WSAENOTSOCK
: wsaErrno());
2171 return SOCKET_ERROR
;
2174 /***********************************************************************
2175 * ioctlsocket (WINSOCK.12)
2177 INT16 WINAPI
WINSOCK_ioctlsocket16(SOCKET16 s
, LONG cmd
, ULONG
*argp
)
2179 return (INT16
)WS_ioctlsocket( s
, cmd
, argp
);
2183 /***********************************************************************
2184 * listen (WS2_32.13)
2186 int WINAPI
WS_listen(SOCKET s
, int backlog
)
2188 int fd
= _get_sock_fd(s
);
2190 TRACE("socket %04x, backlog %d\n", s
, backlog
);
2193 if (listen(fd
, backlog
) == 0)
2196 _enable_event(SOCKET2HANDLE(s
), FD_ACCEPT
,
2198 FD_CONNECT
|FD_WINE_CONNECTED
);
2201 SetLastError(wsaErrno());
2203 else SetLastError(WSAENOTSOCK
);
2204 return SOCKET_ERROR
;
2207 /***********************************************************************
2208 * listen (WINSOCK.13)
2210 INT16 WINAPI
WINSOCK_listen16(SOCKET16 s
, INT16 backlog
)
2212 return (INT16
)WS_listen( s
, backlog
);
2216 /***********************************************************************
2219 int WINAPI
WS_recv(SOCKET s
, char *buf
, int len
, int flags
)
2221 DWORD n
, dwFlags
= flags
;
2227 if ( WSARecvFrom (s
, &wsabuf
, 1, &n
, &dwFlags
, NULL
, NULL
, NULL
, NULL
) == SOCKET_ERROR
)
2228 return SOCKET_ERROR
;
2233 /***********************************************************************
2236 INT16 WINAPI
WINSOCK_recv16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
)
2238 return (INT16
)WS_recv( s
, buf
, len
, flags
);
2242 /***********************************************************************
2243 * recvfrom (WS2_32.17)
2245 int WINAPI
WS_recvfrom(SOCKET s
, char *buf
, INT len
, int flags
,
2246 struct WS_sockaddr
*from
, int *fromlen
)
2248 DWORD n
, dwFlags
= flags
;
2254 if ( WSARecvFrom (s
, &wsabuf
, 1, &n
, &dwFlags
, from
, fromlen
, NULL
, NULL
) == SOCKET_ERROR
)
2255 return SOCKET_ERROR
;
2260 /***********************************************************************
2261 * recvfrom (WINSOCK.17)
2263 INT16 WINAPI
WINSOCK_recvfrom16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
,
2264 struct WS_sockaddr
*from
, INT16
*fromlen16
)
2267 INT
*p
= &fromlen32
;
2270 if( fromlen16
) fromlen32
= *fromlen16
; else p
= NULL
;
2271 retVal
= WS_recvfrom( s
, buf
, len
, flags
, from
, p
);
2272 if( fromlen16
) *fromlen16
= fromlen32
;
2273 return (INT16
)retVal
;
2276 /***********************************************************************
2279 static int __ws_select(BOOL b32
,
2280 void *ws_readfds
, void *ws_writefds
, void *ws_exceptfds
,
2281 const struct WS_timeval
*ws_timeout
)
2284 fd_set readfds
, writefds
, exceptfds
;
2285 fd_set
*p_read
, *p_write
, *p_except
;
2286 int readfd
[FD_SETSIZE
], writefd
[FD_SETSIZE
], exceptfd
[FD_SETSIZE
];
2287 struct timeval timeout
, *timeoutaddr
= NULL
;
2289 TRACE("read %p, write %p, excp %p timeout %p\n",
2290 ws_readfds
, ws_writefds
, ws_exceptfds
, ws_timeout
);
2292 p_read
= fd_set_import(&readfds
, ws_readfds
, &highfd
, readfd
, b32
);
2293 p_write
= fd_set_import(&writefds
, ws_writefds
, &highfd
, writefd
, b32
);
2294 p_except
= fd_set_import(&exceptfds
, ws_exceptfds
, &highfd
, exceptfd
, b32
);
2297 timeoutaddr
= &timeout
;
2298 timeout
.tv_sec
=ws_timeout
->tv_sec
;
2299 timeout
.tv_usec
=ws_timeout
->tv_usec
;
2302 if( (highfd
= select(highfd
+ 1, p_read
, p_write
, p_except
, timeoutaddr
)) > 0 )
2304 fd_set_export(&readfds
, p_except
, ws_readfds
, readfd
, b32
);
2305 fd_set_export(&writefds
, p_except
, ws_writefds
, writefd
, b32
);
2307 if (p_except
&& ws_exceptfds
)
2309 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
2310 #define wsfds32 ((WS_fd_set*)ws_exceptfds)
2311 int i
, j
, count
= (b32
) ? wsfds32
->fd_count
: wsfds16
->fd_count
;
2313 for (i
= j
= 0; i
< count
; i
++)
2315 int fd
= exceptfd
[i
];
2316 if( fd
>= 0 && FD_ISSET(fd
, &exceptfds
) )
2319 wsfds32
->fd_array
[j
++] = wsfds32
->fd_array
[i
];
2321 wsfds16
->fd_array
[j
++] = wsfds16
->fd_array
[i
];
2323 if( fd
>= 0 ) close(fd
);
2327 wsfds32
->fd_count
= j
;
2329 wsfds16
->fd_count
= j
;
2335 fd_set_unimport(ws_readfds
, readfd
, b32
);
2336 fd_set_unimport(ws_writefds
, writefd
, b32
);
2337 fd_set_unimport(ws_exceptfds
, exceptfd
, b32
);
2338 if( ws_readfds
) ((WS_fd_set
*)ws_readfds
)->fd_count
= 0;
2339 if( ws_writefds
) ((WS_fd_set
*)ws_writefds
)->fd_count
= 0;
2340 if( ws_exceptfds
) ((WS_fd_set
*)ws_exceptfds
)->fd_count
= 0;
2342 if( highfd
== 0 ) return 0;
2343 SetLastError(wsaErrno());
2344 return SOCKET_ERROR
;
2347 /***********************************************************************
2348 * select (WINSOCK.18)
2350 INT16 WINAPI
WINSOCK_select16(INT16 nfds
, ws_fd_set16
*ws_readfds
,
2351 ws_fd_set16
*ws_writefds
, ws_fd_set16
*ws_exceptfds
,
2352 struct WS_timeval
* timeout
)
2354 return (INT16
)__ws_select( FALSE
, ws_readfds
, ws_writefds
, ws_exceptfds
, timeout
);
2357 /***********************************************************************
2358 * select (WS2_32.18)
2360 int WINAPI
WS_select(int nfds
, WS_fd_set
*ws_readfds
,
2361 WS_fd_set
*ws_writefds
, WS_fd_set
*ws_exceptfds
,
2362 const struct WS_timeval
* timeout
)
2364 /* struct timeval is the same for both 32- and 16-bit code */
2365 return (INT
)__ws_select( TRUE
, ws_readfds
, ws_writefds
, ws_exceptfds
, timeout
);
2369 /***********************************************************************
2372 int WINAPI
WS_send(SOCKET s
, const char *buf
, int len
, int flags
)
2378 wsabuf
.buf
= (char*) buf
;
2380 if ( WSASendTo ( s
, &wsabuf
, 1, &n
, flags
, NULL
, 0, NULL
, NULL
) == SOCKET_ERROR
)
2381 return SOCKET_ERROR
;
2386 /***********************************************************************
2387 * WSASend (WS2_32.72)
2389 INT WINAPI
WSASend( SOCKET s
, LPWSABUF lpBuffers
, DWORD dwBufferCount
,
2390 LPDWORD lpNumberOfBytesSent
, DWORD dwFlags
,
2391 LPWSAOVERLAPPED lpOverlapped
,
2392 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
2394 return WSASendTo ( s
, lpBuffers
, dwBufferCount
, lpNumberOfBytesSent
, dwFlags
,
2395 NULL
, 0, lpOverlapped
, lpCompletionRoutine
);
2398 /***********************************************************************
2399 * WSASendDisconnect (WS2_32.73)
2401 INT WINAPI
WSASendDisconnect( SOCKET s
, LPWSABUF lpBuffers
)
2403 return WS_shutdown ( s
, SD_SEND
);
2407 /***********************************************************************
2408 * WSASendTo (WS2_32.74)
2410 INT WINAPI
WSASendTo( SOCKET s
, LPWSABUF lpBuffers
, DWORD dwBufferCount
,
2411 LPDWORD lpNumberOfBytesSent
, DWORD dwFlags
,
2412 const struct WS_sockaddr
*to
, int tolen
,
2413 LPWSAOVERLAPPED lpOverlapped
,
2414 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
2416 int i
, n
, fd
, err
= WSAENOTSOCK
, flags
, ret
;
2417 struct iovec
* iovec
;
2418 struct ws2_async
*wsa
;
2421 TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2422 s
, lpBuffers
, dwBufferCount
, dwFlags
,
2423 to
, tolen
, lpOverlapped
, lpCompletionRoutine
);
2425 fd
= _get_sock_fd_type( s
, GENERIC_WRITE
, &type
, &flags
);
2426 TRACE ( "fd=%d, type=%d, flags=%x\n", fd
, type
, flags
);
2430 err
= WSAGetLastError ();
2434 iovec
= HeapAlloc (GetProcessHeap(), 0, dwBufferCount
* sizeof (struct iovec
) );
2442 for ( i
= 0; i
< dwBufferCount
; i
++ )
2444 iovec
[i
].iov_base
= lpBuffers
[i
].buf
;
2445 iovec
[i
].iov_len
= lpBuffers
[i
].len
;
2448 if ( (lpOverlapped
|| lpCompletionRoutine
) && flags
& FD_FLAG_OVERLAPPED
)
2450 wsa
= WS2_make_async ( s
, fd
, ASYNC_TYPE_WRITE
, iovec
, dwBufferCount
,
2451 &dwFlags
, (struct WS_sockaddr
*) to
, &tolen
,
2452 lpOverlapped
, lpCompletionRoutine
);
2459 if ( ( ret
= register_new_async ( &wsa
->async
)) )
2461 err
= NtStatusToWSAError ( ret
);
2463 if ( !lpOverlapped
)
2464 HeapFree ( GetProcessHeap(), 0, wsa
->overlapped
);
2465 HeapFree ( GetProcessHeap(), 0, wsa
);
2469 /* Try immediate completion */
2470 if ( lpOverlapped
&& !NtResetEvent( lpOverlapped
->hEvent
, NULL
) )
2472 if ( WSAGetOverlappedResult ( s
, lpOverlapped
,
2473 lpNumberOfBytesSent
, FALSE
, &dwFlags
) )
2476 if ( (err
= WSAGetLastError ()) != WSA_IO_INCOMPLETE
)
2480 WSASetLastError ( WSA_IO_PENDING
);
2481 return SOCKET_ERROR
;
2484 if (_is_blocking(s
))
2486 /* FIXME: exceptfds? */
2490 n
= WS2_send ( fd
, iovec
, dwBufferCount
, to
, tolen
, dwFlags
);
2494 if ( err
== WSAEWOULDBLOCK
)
2495 _enable_event (SOCKET2HANDLE(s
), FD_WRITE
, 0, 0);
2499 TRACE(" -> %i bytes\n", n
);
2500 *lpNumberOfBytesSent
= n
;
2502 HeapFree ( GetProcessHeap(), 0, iovec
);
2507 HeapFree ( GetProcessHeap(), 0, iovec
);
2513 WARN (" -> ERROR %d\n", err
);
2514 WSASetLastError (err
);
2515 return SOCKET_ERROR
;
2518 /***********************************************************************
2521 INT16 WINAPI
WINSOCK_send16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
)
2523 return WS_send( s
, buf
, len
, flags
);
2526 /***********************************************************************
2527 * sendto (WS2_32.20)
2529 int WINAPI
WS_sendto(SOCKET s
, const char *buf
, int len
, int flags
,
2530 const struct WS_sockaddr
*to
, int tolen
)
2536 wsabuf
.buf
= (char*) buf
;
2538 if ( WSASendTo (s
, &wsabuf
, 1, &n
, flags
, to
, tolen
, NULL
, NULL
) == SOCKET_ERROR
)
2539 return SOCKET_ERROR
;
2544 /***********************************************************************
2545 * sendto (WINSOCK.20)
2547 INT16 WINAPI
WINSOCK_sendto16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
,
2548 struct WS_sockaddr
*to
, INT16 tolen
)
2550 return (INT16
)WS_sendto( s
, buf
, len
, flags
, to
, tolen
);
2553 /***********************************************************************
2554 * setsockopt (WS2_32.21)
2556 int WINAPI
WS_setsockopt(SOCKET s
, int level
, int optname
,
2557 const char *optval
, int optlen
)
2561 TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s
, level
,
2562 (int) optname
, (int) optval
, optlen
);
2563 /* SO_OPENTYPE does not require a valid socket handle. */
2564 if (level
== WS_SOL_SOCKET
&& optname
== WS_SO_OPENTYPE
)
2566 if (optlen
< sizeof(int) || !optval
)
2568 SetLastError(WSAEFAULT
);
2569 return SOCKET_ERROR
;
2571 TlsSetValue( opentype_tls_index
, (LPVOID
)*(int *)optval
);
2572 TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval
);
2576 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2577 * socket. This will either not happen under windows or it is ignored in
2578 * windows (but it works in linux and therefor prevents the game to find
2579 * games outsite the current network) */
2580 if ( level
==WS_SOL_SOCKET
&& optname
==WS_SO_DONTROUTE
)
2582 FIXME("Does windows ignore SO_DONTROUTE?\n");
2587 fd
= _get_sock_fd(s
);
2590 struct linger linger
;
2592 struct timeval tval
;
2594 /* Is a privileged and useless operation, so we don't. */
2595 if ((optname
== WS_SO_DEBUG
) && (level
== WS_SOL_SOCKET
)) {
2596 FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s
,optval
,*(DWORD
*)optval
);
2600 if(optname
== WS_SO_DONTLINGER
&& level
== WS_SOL_SOCKET
) {
2601 /* This is unique to WinSock and takes special conversion */
2602 linger
.l_onoff
= *((int*)optval
) ? 0: 1;
2603 linger
.l_linger
= 0;
2605 optval
= (char*)&linger
;
2606 optlen
= sizeof(struct linger
);
2609 if (!convert_sockopt(&level
, &optname
)) {
2610 ERR("Invalid level (%d) or optname (%d)\n", level
, optname
);
2611 SetLastError(WSAENOPROTOOPT
);
2613 return SOCKET_ERROR
;
2615 if (optname
== SO_LINGER
&& optval
) {
2616 /* yes, uses unsigned short in both win16/win32 */
2617 linger
.l_onoff
= ((UINT16
*)optval
)[0];
2618 linger
.l_linger
= ((UINT16
*)optval
)[1];
2619 /* FIXME: what is documented behavior if SO_LINGER optval
2621 optval
= (char*)&linger
;
2622 optlen
= sizeof(struct linger
);
2623 } else if (optval
&& optlen
< sizeof(int)){
2624 woptval
= *((INT16
*) optval
);
2625 optval
= (char*) &woptval
;
2629 if (level
== SOL_SOCKET
&& optname
== SO_RCVTIMEO
) {
2630 if (optlen
== sizeof(UINT32
)) {
2631 /* WinSock passes miliseconds instead of struct timeval */
2632 tval
.tv_usec
= *(PUINT32
)optval
% 1000;
2633 tval
.tv_sec
= *(PUINT32
)optval
/ 1000;
2634 /* min of 500 milisec */
2635 if (tval
.tv_sec
== 0 && tval
.tv_usec
< 500) tval
.tv_usec
= 500;
2636 optlen
= sizeof(struct timeval
);
2637 optval
= (char*)&tval
;
2638 } else if (optlen
== sizeof(struct timeval
)) {
2639 WARN("SO_RCVTIMEO for %d bytes: assuming unixism\n", optlen
);
2641 WARN("SO_RCVTIMEO for %d bytes is weird: ignored\n", optlen
);
2648 if (level
== SOL_SOCKET
&& optname
== SO_SNDTIMEO
) {
2649 if (optlen
== sizeof(UINT32
)) {
2650 /* WinSock passes miliseconds instead of struct timeval */
2651 tval
.tv_usec
= *(PUINT32
)optval
% 1000;
2652 tval
.tv_sec
= *(PUINT32
)optval
/ 1000;
2653 /* min of 500 milisec */
2654 if (tval
.tv_sec
== 0 && tval
.tv_usec
< 500) tval
.tv_usec
= 500;
2655 optlen
= sizeof(struct timeval
);
2656 optval
= (char*)&tval
;
2657 } else if (optlen
== sizeof(struct timeval
)) {
2658 WARN("SO_SNDTIMEO for %d bytes: assuming unixism\n", optlen
);
2660 WARN("SO_SNDTIMEO for %d bytes is weird: ignored\n", optlen
);
2667 if(optname
== SO_RCVBUF
&& *(int*)optval
< 2048) {
2668 WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval
);
2673 if (setsockopt(fd
, level
, optname
, optval
, optlen
) == 0)
2678 TRACE("Setting socket error, %d\n", wsaErrno());
2679 SetLastError(wsaErrno());
2682 else SetLastError(WSAENOTSOCK
);
2683 return SOCKET_ERROR
;
2686 /***********************************************************************
2687 * setsockopt (WINSOCK.21)
2689 INT16 WINAPI
WINSOCK_setsockopt16(SOCKET16 s
, INT16 level
, INT16 optname
,
2690 char *optval
, INT16 optlen
)
2692 if( !optval
) return SOCKET_ERROR
;
2693 return (INT16
)WS_setsockopt( s
, (UINT16
)level
, optname
, optval
, optlen
);
2697 /***********************************************************************
2698 * shutdown (WS2_32.22)
2700 int WINAPI
WS_shutdown(SOCKET s
, int how
)
2702 int fd
, fd0
= -1, fd1
= -1, flags
, err
= WSAENOTSOCK
;
2704 unsigned int clear_flags
= 0;
2706 fd
= _get_sock_fd_type ( s
, 0, &type
, &flags
);
2707 TRACE("socket %04x, how %i %d %d \n", s
, how
, type
, flags
);
2710 return SOCKET_ERROR
;
2714 case 0: /* drop receives */
2715 clear_flags
|= FD_READ
;
2717 case 1: /* drop sends */
2718 clear_flags
|= FD_WRITE
;
2720 case 2: /* drop all */
2721 clear_flags
|= FD_READ
|FD_WRITE
;
2723 clear_flags
|= FD_WINE_LISTENING
;
2726 if ( flags
& FD_FLAG_OVERLAPPED
) {
2739 fd1
= _get_sock_fd ( s
);
2744 err
= WS2_register_async_shutdown ( s
, fd0
, ASYNC_TYPE_READ
);
2753 err
= WS2_register_async_shutdown ( s
, fd1
, ASYNC_TYPE_WRITE
);
2761 else /* non-overlapped mode */
2763 if ( shutdown( fd
, how
) )
2772 _enable_event( SOCKET2HANDLE(s
), 0, 0, clear_flags
);
2773 if ( how
> 1) WSAAsyncSelect( s
, 0, 0, 0 );
2777 _enable_event( SOCKET2HANDLE(s
), 0, 0, clear_flags
);
2778 WSASetLastError ( err
);
2779 return SOCKET_ERROR
;
2782 /***********************************************************************
2783 * shutdown (WINSOCK.22)
2785 INT16 WINAPI
WINSOCK_shutdown16(SOCKET16 s
, INT16 how
)
2787 return (INT16
)WS_shutdown( s
, how
);
2791 /***********************************************************************
2792 * socket (WS2_32.23)
2794 SOCKET WINAPI
WS_socket(int af
, int type
, int protocol
)
2796 TRACE("af=%d type=%d protocol=%d\n", af
, type
, protocol
);
2798 return WSASocketA ( af
, type
, protocol
, NULL
, 0,
2799 (TlsGetValue(opentype_tls_index
) ? 0 : WSA_FLAG_OVERLAPPED
) );
2802 /***********************************************************************
2803 * socket (WINSOCK.23)
2805 SOCKET16 WINAPI
WINSOCK_socket16(INT16 af
, INT16 type
, INT16 protocol
)
2807 return (SOCKET16
)WS_socket( af
, type
, protocol
);
2811 /* ----------------------------------- DNS services
2813 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2814 * Also, we have to use wsock32 stubs to convert structures and
2815 * error codes from Unix to WSA, hence there is no direct mapping in
2816 * the relay32/wsock32.spec.
2820 /***********************************************************************
2821 * __ws_gethostbyaddr
2823 static WIN_hostent
* __ws_gethostbyaddr(const char *addr
, int len
, int type
, int dup_flag
)
2825 WIN_hostent
*retval
= NULL
;
2827 struct hostent
* host
;
2828 #if HAVE_LINUX_GETHOSTBYNAME_R_6
2831 struct hostent hostentry
;
2834 extrabuf
=HeapAlloc(GetProcessHeap(),0,ebufsize
) ;
2836 int res
= gethostbyaddr_r(addr
, len
, type
,
2837 &hostentry
, extrabuf
, ebufsize
, &host
, &locerr
);
2838 if( res
!= ERANGE
) break;
2840 extrabuf
=HeapReAlloc(GetProcessHeap(),0,extrabuf
,ebufsize
) ;
2842 if (!host
) SetLastError((locerr
< 0) ? wsaErrno() : wsaHerrno(locerr
));
2844 EnterCriticalSection( &csWSgetXXXbyYYY
);
2845 host
= gethostbyaddr(addr
, len
, type
);
2846 if (!host
) SetLastError((h_errno
< 0) ? wsaErrno() : wsaHerrno(h_errno
));
2850 if( WS_dup_he(host
, dup_flag
) )
2853 SetLastError(WSAENOBUFS
);
2855 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2856 HeapFree(GetProcessHeap(),0,extrabuf
);
2858 LeaveCriticalSection( &csWSgetXXXbyYYY
);
2863 /***********************************************************************
2864 * gethostbyaddr (WINSOCK.51)
2866 SEGPTR WINAPI
WINSOCK_gethostbyaddr16(const char *addr
, INT16 len
, INT16 type
)
2868 TRACE("ptr %p, len %d, type %d\n", addr
, len
, type
);
2869 if (!__ws_gethostbyaddr( addr
, len
, type
, WS_DUP_SEGPTR
)) return 0;
2870 return he_buffer_seg
;
2873 /***********************************************************************
2874 * gethostbyaddr (WS2_32.51)
2876 struct WS_hostent
* WINAPI
WS_gethostbyaddr(const char *addr
, int len
,
2879 TRACE("ptr %08x, len %d, type %d\n",
2880 (unsigned) addr
, len
, type
);
2881 return __ws_gethostbyaddr(addr
, len
, type
, WS_DUP_LINEAR
);
2884 /***********************************************************************
2885 * __ws_gethostbyname
2887 static WIN_hostent
* __ws_gethostbyname(const char *name
, int dup_flag
)
2889 WIN_hostent
*retval
= NULL
;
2890 struct hostent
* host
;
2891 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2894 struct hostent hostentry
;
2895 int locerr
= ENOBUFS
;
2897 extrabuf
=HeapAlloc(GetProcessHeap(),0,ebufsize
) ;
2899 int res
= gethostbyname_r(name
, &hostentry
, extrabuf
, ebufsize
, &host
, &locerr
);
2900 if( res
!= ERANGE
) break;
2902 extrabuf
=HeapReAlloc(GetProcessHeap(),0,extrabuf
,ebufsize
) ;
2904 if (!host
) SetLastError((locerr
< 0) ? wsaErrno() : wsaHerrno(locerr
));
2906 EnterCriticalSection( &csWSgetXXXbyYYY
);
2907 host
= gethostbyname(name
);
2908 if (!host
) SetLastError((h_errno
< 0) ? wsaErrno() : wsaHerrno(h_errno
));
2912 if( WS_dup_he(host
, dup_flag
) )
2914 else SetLastError(WSAENOBUFS
);
2916 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2917 HeapFree(GetProcessHeap(),0,extrabuf
);
2919 LeaveCriticalSection( &csWSgetXXXbyYYY
);
2924 /***********************************************************************
2925 * gethostbyname (WINSOCK.52)
2927 SEGPTR WINAPI
WINSOCK_gethostbyname16(const char *name
)
2929 TRACE( "%s\n", debugstr_a(name
) );
2930 if (!__ws_gethostbyname( name
, WS_DUP_SEGPTR
)) return 0;
2931 return he_buffer_seg
;
2934 /***********************************************************************
2935 * gethostbyname (WS2_32.52)
2937 struct WS_hostent
* WINAPI
WS_gethostbyname(const char* name
)
2939 TRACE( "%s\n", debugstr_a(name
) );
2940 return __ws_gethostbyname( name
, WS_DUP_LINEAR
);
2944 /***********************************************************************
2945 * __ws_getprotobyname
2947 static WIN_protoent
* __ws_getprotobyname(const char *name
, int dup_flag
)
2949 WIN_protoent
* retval
= NULL
;
2950 #ifdef HAVE_GETPROTOBYNAME
2951 struct protoent
* proto
;
2952 EnterCriticalSection( &csWSgetXXXbyYYY
);
2953 if( (proto
= getprotobyname(name
)) != NULL
)
2955 if( WS_dup_pe(proto
, dup_flag
) )
2957 else SetLastError(WSAENOBUFS
);
2960 MESSAGE("protocol %s not found; You might want to add "
2961 "this to /etc/protocols\n", debugstr_a(name
) );
2962 SetLastError(WSANO_DATA
);
2964 LeaveCriticalSection( &csWSgetXXXbyYYY
);
2969 /***********************************************************************
2970 * getprotobyname (WINSOCK.53)
2972 SEGPTR WINAPI
WINSOCK_getprotobyname16(const char *name
)
2974 TRACE( "%s\n", debugstr_a(name
) );
2975 if (!__ws_getprotobyname(name
, WS_DUP_SEGPTR
)) return 0;
2976 return pe_buffer_seg
;
2979 /***********************************************************************
2980 * getprotobyname (WS2_32.53)
2982 struct WS_protoent
* WINAPI
WS_getprotobyname(const char* name
)
2984 TRACE( "%s\n", debugstr_a(name
) );
2985 return __ws_getprotobyname(name
, WS_DUP_LINEAR
);
2989 /***********************************************************************
2990 * __ws_getprotobynumber
2992 static WIN_protoent
* __ws_getprotobynumber(int number
, int dup_flag
)
2994 WIN_protoent
* retval
= NULL
;
2995 #ifdef HAVE_GETPROTOBYNUMBER
2996 struct protoent
* proto
;
2997 EnterCriticalSection( &csWSgetXXXbyYYY
);
2998 if( (proto
= getprotobynumber(number
)) != NULL
)
3000 if( WS_dup_pe(proto
, dup_flag
) )
3002 else SetLastError(WSAENOBUFS
);
3005 MESSAGE("protocol number %d not found; You might want to add "
3006 "this to /etc/protocols\n", number
);
3007 SetLastError(WSANO_DATA
);
3009 LeaveCriticalSection( &csWSgetXXXbyYYY
);
3014 /***********************************************************************
3015 * getprotobynumber (WINSOCK.54)
3017 SEGPTR WINAPI
WINSOCK_getprotobynumber16(INT16 number
)
3019 TRACE("%i\n", number
);
3020 if (!__ws_getprotobynumber(number
, WS_DUP_SEGPTR
)) return 0;
3021 return pe_buffer_seg
;
3024 /***********************************************************************
3025 * getprotobynumber (WS2_32.54)
3027 struct WS_protoent
* WINAPI
WS_getprotobynumber(int number
)
3029 TRACE("%i\n", number
);
3030 return __ws_getprotobynumber(number
, WS_DUP_LINEAR
);
3034 /***********************************************************************
3035 * __ws_getservbyname
3037 static WIN_servent
* __ws_getservbyname(const char *name
, const char *proto
, int dup_flag
)
3039 WIN_servent
* retval
= NULL
;
3040 struct servent
* serv
;
3041 int i
= wsi_strtolo( name
, proto
);
3044 EnterCriticalSection( &csWSgetXXXbyYYY
);
3045 serv
= getservbyname(local_buffer
,
3046 proto
&& *proto
? (local_buffer
+ i
) : NULL
);
3049 if( WS_dup_se(serv
, dup_flag
) )
3051 else SetLastError(WSAENOBUFS
);
3054 MESSAGE("service %s protocol %s not found; You might want to add "
3055 "this to /etc/services\n", debugstr_a(local_buffer
),
3056 proto
? debugstr_a(local_buffer
+i
):"*");
3057 SetLastError(WSANO_DATA
);
3059 LeaveCriticalSection( &csWSgetXXXbyYYY
);
3061 else SetLastError(WSAENOBUFS
);
3065 /***********************************************************************
3066 * getservbyname (WINSOCK.55)
3068 SEGPTR WINAPI
WINSOCK_getservbyname16(const char *name
, const char *proto
)
3070 TRACE( "%s, %s\n", debugstr_a(name
), debugstr_a(proto
) );
3071 if (!__ws_getservbyname(name
, proto
, WS_DUP_SEGPTR
)) return 0;
3072 return se_buffer_seg
;
3075 /***********************************************************************
3076 * getservbyname (WS2_32.55)
3078 struct WS_servent
* WINAPI
WS_getservbyname(const char *name
, const char *proto
)
3080 TRACE( "%s, %s\n", debugstr_a(name
), debugstr_a(proto
) );
3081 return __ws_getservbyname(name
, proto
, WS_DUP_LINEAR
);
3085 /***********************************************************************
3086 * __ws_getservbyport
3088 static WIN_servent
* __ws_getservbyport(int port
, const char* proto
, int dup_flag
)
3090 WIN_servent
* retval
= NULL
;
3091 #ifdef HAVE_GETSERVBYPORT
3092 struct servent
* serv
;
3093 if (!proto
|| wsi_strtolo( proto
, NULL
)) {
3094 EnterCriticalSection( &csWSgetXXXbyYYY
);
3095 if( (serv
= getservbyport(port
, proto
&& *proto
? local_buffer
:
3097 if( WS_dup_se(serv
, dup_flag
) )
3099 else SetLastError(WSAENOBUFS
);
3102 MESSAGE("service on port %lu protocol %s not found; You might want to add "
3103 "this to /etc/services\n", (unsigned long)ntohl(port
),
3104 proto
? debugstr_a(local_buffer
) : "*");
3105 SetLastError(WSANO_DATA
);
3107 LeaveCriticalSection( &csWSgetXXXbyYYY
);
3109 else SetLastError(WSAENOBUFS
);
3114 /***********************************************************************
3115 * getservbyport (WINSOCK.56)
3117 SEGPTR WINAPI
WINSOCK_getservbyport16(INT16 port
, const char *proto
)
3119 TRACE("%d (i.e. port %d), %s\n", (int)port
, (int)ntohl(port
), debugstr_a(proto
));
3120 if (!__ws_getservbyport(port
, proto
, WS_DUP_SEGPTR
)) return 0;
3121 return se_buffer_seg
;
3124 /***********************************************************************
3125 * getservbyport (WS2_32.56)
3127 struct WS_servent
* WINAPI
WS_getservbyport(int port
, const char *proto
)
3129 TRACE("%d (i.e. port %d), %s\n", (int)port
, (int)ntohl(port
), debugstr_a(proto
));
3130 return __ws_getservbyport(port
, proto
, WS_DUP_LINEAR
);
3134 /***********************************************************************
3135 * gethostname (WS2_32.57)
3137 int WINAPI
WS_gethostname(char *name
, int namelen
)
3139 TRACE("name %p, len %d\n", name
, namelen
);
3141 if (gethostname(name
, namelen
) == 0)
3143 TRACE("<- '%s'\n", name
);
3146 SetLastError((errno
== EINVAL
) ? WSAEFAULT
: wsaErrno());
3147 TRACE("<- ERROR !\n");
3148 return SOCKET_ERROR
;
3151 /***********************************************************************
3152 * gethostname (WINSOCK.57)
3154 INT16 WINAPI
WINSOCK_gethostname16(char *name
, INT16 namelen
)
3156 return (INT16
)WS_gethostname(name
, namelen
);
3160 /* ------------------------------------- Windows sockets extensions -- *
3162 * ------------------------------------------------------------------- */
3164 /***********************************************************************
3165 * WSAEnumNetworkEvents (WS2_32.36)
3167 int WINAPI
WSAEnumNetworkEvents(SOCKET s
, WSAEVENT hEvent
, LPWSANETWORKEVENTS lpEvent
)
3171 TRACE("%08x, hEvent %p, lpEvent %08x\n", s
, hEvent
, (unsigned)lpEvent
);
3173 SERVER_START_REQ( get_socket_event
)
3175 req
->handle
= SOCKET2HANDLE(s
);
3176 req
->service
= TRUE
;
3177 req
->c_event
= hEvent
;
3178 wine_server_set_reply( req
, lpEvent
->iErrorCode
, sizeof(lpEvent
->iErrorCode
) );
3179 if (!(ret
= wine_server_call(req
))) lpEvent
->lNetworkEvents
= reply
->pmask
& reply
->mask
;
3183 SetLastError(WSAEINVAL
);
3184 return SOCKET_ERROR
;
3187 /***********************************************************************
3188 * WSAEventSelect (WS2_32.39)
3190 int WINAPI
WSAEventSelect(SOCKET s
, WSAEVENT hEvent
, LONG lEvent
)
3194 TRACE("%08x, hEvent %p, event %08x\n", s
, hEvent
, (unsigned)lEvent
);
3196 SERVER_START_REQ( set_socket_event
)
3198 req
->handle
= SOCKET2HANDLE(s
);
3200 req
->event
= hEvent
;
3203 ret
= wine_server_call( req
);
3207 SetLastError(WSAEINVAL
);
3208 return SOCKET_ERROR
;
3211 /**********************************************************************
3212 * WSAGetOverlappedResult (WS2_32.40)
3214 BOOL WINAPI
WSAGetOverlappedResult ( SOCKET s
, LPWSAOVERLAPPED lpOverlapped
,
3215 LPDWORD lpcbTransfer
, BOOL fWait
,
3220 TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
3221 s
, lpOverlapped
, lpcbTransfer
, fWait
, lpdwFlags
);
3223 if ( !(lpOverlapped
&& lpOverlapped
->hEvent
) )
3225 ERR ( "Invalid pointer\n" );
3226 WSASetLastError (WSA_INVALID_PARAMETER
);
3232 while ( WaitForSingleObjectEx (lpOverlapped
->hEvent
, INFINITE
, TRUE
) == STATUS_USER_APC
);
3234 else if ( lpOverlapped
->Internal
== STATUS_PENDING
)
3236 /* Wait in order to give APCs a chance to run. */
3237 /* This is cheating, so we must set the event again in case of success -
3238 it may be a non-manual reset event. */
3239 while ( (r
= WaitForSingleObjectEx (lpOverlapped
->hEvent
, 0, TRUE
)) == STATUS_USER_APC
);
3240 if ( r
== WAIT_OBJECT_0
)
3241 NtSetEvent ( lpOverlapped
->hEvent
, NULL
);
3245 *lpcbTransfer
= lpOverlapped
->InternalHigh
;
3248 *lpdwFlags
= lpOverlapped
->Offset
;
3250 switch ( lpOverlapped
->Internal
)
3252 case STATUS_SUCCESS
:
3254 case STATUS_PENDING
:
3255 WSASetLastError ( WSA_IO_INCOMPLETE
);
3256 if (fWait
) ERR ("PENDING status after waiting!\n");
3259 WSASetLastError ( NtStatusToWSAError ( lpOverlapped
->Internal
));
3265 /***********************************************************************
3266 * WSAAsyncSelect (WS2_32.101)
3268 INT WINAPI
WSAAsyncSelect(SOCKET s
, HWND hWnd
, UINT uMsg
, LONG lEvent
)
3272 TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s
, hWnd
, uMsg
, lEvent
);
3274 SERVER_START_REQ( set_socket_event
)
3276 req
->handle
= SOCKET2HANDLE(s
);
3281 ret
= wine_server_call( req
);
3285 SetLastError(WSAEINVAL
);
3286 return SOCKET_ERROR
;
3289 /***********************************************************************
3290 * WSAAsyncSelect (WINSOCK.101)
3292 INT16 WINAPI
WSAAsyncSelect16(SOCKET16 s
, HWND16 hWnd
, UINT16 wMsg
, LONG lEvent
)
3294 return (INT16
)WSAAsyncSelect( s
, HWND_32(hWnd
), wMsg
, lEvent
);
3297 /***********************************************************************
3298 * WSARecvEx (WINSOCK.1107)
3300 * See description for WSARecvEx()
3302 INT16 WINAPI
WSARecvEx16(SOCKET16 s
, char *buf
, INT16 len
, INT16
*flags
)
3304 FIXME("(WSARecvEx16) partial packet return value not set \n");
3306 return WINSOCK_recv16(s
, buf
, len
, *flags
);
3310 /***********************************************************************
3311 * WSACreateEvent (WS2_32.31)
3314 WSAEVENT WINAPI
WSACreateEvent(void)
3316 /* Create a manual-reset event, with initial state: unsignealed */
3319 return CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3322 /***********************************************************************
3323 * WSACloseEvent (WS2_32.29)
3326 BOOL WINAPI
WSACloseEvent(WSAEVENT event
)
3328 TRACE ("event=%p\n", event
);
3330 return CloseHandle(event
);
3333 /***********************************************************************
3334 * WSASocketA (WS2_32.78)
3337 SOCKET WINAPI
WSASocketA(int af
, int type
, int protocol
,
3338 LPWSAPROTOCOL_INFOA lpProtocolInfo
,
3339 GROUP g
, DWORD dwFlags
)
3344 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
3345 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3348 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3349 af
, type
, protocol
, lpProtocolInfo
, g
, dwFlags
);
3351 /* hack for WSADuplicateSocket */
3352 if (lpProtocolInfo
&& lpProtocolInfo
->dwServiceFlags4
== 0xff00ff00) {
3353 ret
= lpProtocolInfo
->dwCatalogEntryId
;
3354 TRACE("\tgot duplicate %04x\n", ret
);
3358 /* check the socket family */
3362 case WS_AF_IPX
: af
= AF_IPX
;
3368 SetLastError(WSAEAFNOSUPPORT
);
3369 return INVALID_SOCKET
;
3372 /* check the socket type */
3375 case WS_SOCK_STREAM
:
3385 SetLastError(WSAESOCKTNOSUPPORT
);
3386 return INVALID_SOCKET
;
3389 /* check the protocol type */
3390 if ( protocol
< 0 ) /* don't support negative values */
3392 SetLastError(WSAEPROTONOSUPPORT
);
3393 return INVALID_SOCKET
;
3396 if ( af
== AF_UNSPEC
) /* did they not specify the address family? */
3400 if (type
== SOCK_STREAM
) { af
= AF_INET
; break; }
3402 if (type
== SOCK_DGRAM
) { af
= AF_INET
; break; }
3403 default: SetLastError(WSAEPROTOTYPE
); return INVALID_SOCKET
;
3406 SERVER_START_REQ( create_socket
)
3410 req
->protocol
= protocol
;
3411 req
->access
= GENERIC_READ
|GENERIC_WRITE
|SYNCHRONIZE
;
3412 req
->flags
= dwFlags
;
3413 req
->inherit
= TRUE
;
3414 set_error( wine_server_call( req
) );
3415 ret
= HANDLE2SOCKET( reply
->handle
);
3420 TRACE("\tcreated %04x\n", ret
);
3424 if (GetLastError() == WSAEACCES
) /* raw socket denied */
3426 if (type
== SOCK_RAW
)
3427 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3429 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3430 SetLastError(WSAESOCKTNOSUPPORT
);
3433 WARN("\t\tfailed!\n");
3434 return INVALID_SOCKET
;
3438 /***********************************************************************
3439 * __WSAFDIsSet (WINSOCK.151)
3441 INT16 WINAPI
__WSAFDIsSet16(SOCKET16 s
, ws_fd_set16
*set
)
3443 int i
= set
->fd_count
;
3445 TRACE("(%d,%8lx(%i))\n", s
,(unsigned long)set
, i
);
3448 if (set
->fd_array
[i
] == s
) return 1;
3452 /***********************************************************************
3453 * __WSAFDIsSet (WS2_32.151)
3455 int WINAPI
__WSAFDIsSet(SOCKET s
, WS_fd_set
*set
)
3457 int i
= set
->fd_count
;
3459 TRACE("(%d,%8lx(%i))\n", s
,(unsigned long)set
, i
);
3462 if (set
->fd_array
[i
] == s
) return 1;
3466 /***********************************************************************
3467 * WSAIsBlocking (WINSOCK.114)
3468 * WSAIsBlocking (WS2_32.114)
3470 BOOL WINAPI
WSAIsBlocking(void)
3472 /* By default WinSock should set all its sockets to non-blocking mode
3473 * and poll in PeekMessage loop when processing "blocking" ones. This
3474 * function is supposed to tell if the program is in this loop. Our
3475 * blocking calls are truly blocking so we always return FALSE.
3477 * Note: It is allowed to call this function without prior WSAStartup().
3484 /***********************************************************************
3485 * WSACancelBlockingCall (WINSOCK.113)
3486 * WSACancelBlockingCall (WS2_32.113)
3488 INT WINAPI
WSACancelBlockingCall(void)
3495 /***********************************************************************
3496 * WSASetBlockingHook (WINSOCK.109)
3498 FARPROC16 WINAPI
WSASetBlockingHook16(FARPROC16 lpBlockFunc
)
3500 FARPROC16 prev
= (FARPROC16
)blocking_hook
;
3501 blocking_hook
= (FARPROC
)lpBlockFunc
;
3502 TRACE("hook %p\n", lpBlockFunc
);
3507 /***********************************************************************
3508 * WSASetBlockingHook (WS2_32.109)
3510 FARPROC WINAPI
WSASetBlockingHook(FARPROC lpBlockFunc
)
3512 FARPROC prev
= blocking_hook
;
3513 blocking_hook
= lpBlockFunc
;
3514 TRACE("hook %p\n", lpBlockFunc
);
3519 /***********************************************************************
3520 * WSAUnhookBlockingHook (WINSOCK.110)
3522 INT16 WINAPI
WSAUnhookBlockingHook16(void)
3524 blocking_hook
= NULL
;
3529 /***********************************************************************
3530 * WSAUnhookBlockingHook (WS2_32.110)
3532 INT WINAPI
WSAUnhookBlockingHook(void)
3534 blocking_hook
= NULL
;
3539 /* ----------------------------------- end of API stuff */
3541 /* ----------------------------------- helper functions -
3543 * TODO: Merge WS_dup_..() stuff into one function that
3544 * would operate with a generic structure containing internal
3545 * pointers (via a template of some kind).
3548 static int list_size(char** l
, int item_size
)
3553 j
+= (item_size
) ? item_size
: strlen(l
[i
]) + 1;
3554 j
+= (i
+ 1) * sizeof(char*); }
3558 static int list_dup(char** l_src
, char* ref
, char* base
, int item_size
)
3560 /* base is either either equal to ref or 0 or SEGPTR */
3563 char** l_to
= (char**)ref
;
3566 for(j
=0;l_src
[j
];j
++) ;
3567 p
+= (j
+ 1) * sizeof(char*);
3569 { l_to
[i
] = base
+ (p
- ref
);
3570 k
= ( item_size
) ? item_size
: strlen(l_src
[i
]) + 1;
3571 memcpy(p
, l_src
[i
], k
); p
+= k
; }
3578 static int hostent_size(struct hostent
* p_he
)
3582 { size
= sizeof(struct hostent
);
3583 size
+= strlen(p_he
->h_name
) + 1;
3584 size
+= list_size(p_he
->h_aliases
, 0);
3585 size
+= list_size(p_he
->h_addr_list
, p_he
->h_length
); }
3589 /* duplicate hostent entry
3590 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3591 * Dito for protoent and servent.
3593 static int WS_dup_he(struct hostent
* p_he
, int flag
)
3595 /* Convert hostent structure into ws_hostent so that the data fits
3596 * into local_buffer. Internal pointers can be linear, SEGPTR, or
3597 * relative to local_buffer depending on "flag" value. Returns size
3598 * of the data copied.
3601 int size
= hostent_size(p_he
);
3604 char *p_name
,*p_aliases
,*p_addr
,*p_base
,*p
;
3606 struct ws_hostent16
*p_to16
;
3607 struct WS_hostent
*p_to32
;
3609 check_buffer_he(size
);
3615 p_base
= (flag
& WS_DUP_SEGPTR
) ? (char*)he_buffer_seg
: he_buffer
;
3616 p
+= (flag
& WS_DUP_SEGPTR
) ?
3617 sizeof(struct ws_hostent16
) : sizeof(struct WS_hostent
);
3619 strcpy(p
, p_he
->h_name
); p
+= strlen(p
) + 1;
3621 p
+= list_dup(p_he
->h_aliases
, p
, p_base
+ (p
- p_to
), 0);
3623 list_dup(p_he
->h_addr_list
, p
, p_base
+ (p
- p_to
), p_he
->h_length
);
3625 if (flag
& WS_DUP_SEGPTR
) /* Win16 */
3627 p_to16
->h_addrtype
= (INT16
)p_he
->h_addrtype
;
3628 p_to16
->h_length
= (INT16
)p_he
->h_length
;
3629 p_to16
->h_name
= (SEGPTR
)(p_base
+ (p_name
- p_to
));
3630 p_to16
->h_aliases
= (SEGPTR
)(p_base
+ (p_aliases
- p_to
));
3631 p_to16
->h_addr_list
= (SEGPTR
)(p_base
+ (p_addr
- p_to
));
3632 size
+= (sizeof(struct ws_hostent16
) - sizeof(struct hostent
));
3636 p_to32
->h_addrtype
= p_he
->h_addrtype
;
3637 p_to32
->h_length
= p_he
->h_length
;
3638 p_to32
->h_name
= (p_base
+ (p_name
- p_to
));
3639 p_to32
->h_aliases
= (char **)(p_base
+ (p_aliases
- p_to
));
3640 p_to32
->h_addr_list
= (char **)(p_base
+ (p_addr
- p_to
));
3641 size
+= (sizeof(struct WS_hostent
) - sizeof(struct hostent
));
3647 /* ----- protoent */
3649 static int protoent_size(struct protoent
* p_pe
)
3653 { size
= sizeof(struct protoent
);
3654 size
+= strlen(p_pe
->p_name
) + 1;
3655 size
+= list_size(p_pe
->p_aliases
, 0); }
3659 static int WS_dup_pe(struct protoent
* p_pe
, int flag
)
3661 int size
= protoent_size(p_pe
);
3665 struct ws_protoent16
*p_to16
;
3666 struct WS_protoent
*p_to32
;
3667 char *p_name
,*p_aliases
,*p_base
,*p
;
3669 check_buffer_pe(size
);
3674 p_base
= (flag
& WS_DUP_SEGPTR
) ? (char*)pe_buffer_seg
: pe_buffer
;
3675 p
+= (flag
& WS_DUP_SEGPTR
) ?
3676 sizeof(struct ws_protoent16
) : sizeof(struct WS_protoent
);
3678 strcpy(p
, p_pe
->p_name
); p
+= strlen(p
) + 1;
3680 list_dup(p_pe
->p_aliases
, p
, p_base
+ (p
- p_to
), 0);
3682 if (flag
& WS_DUP_SEGPTR
) /* Win16 */
3684 p_to16
->p_proto
= (INT16
)p_pe
->p_proto
;
3685 p_to16
->p_name
= (SEGPTR
)(p_base
) + (p_name
- p_to
);
3686 p_to16
->p_aliases
= (SEGPTR
)((p_base
) + (p_aliases
- p_to
));
3687 size
+= (sizeof(struct ws_protoent16
) - sizeof(struct protoent
));
3691 p_to32
->p_proto
= p_pe
->p_proto
;
3692 p_to32
->p_name
= (p_base
) + (p_name
- p_to
);
3693 p_to32
->p_aliases
= (char **)((p_base
) + (p_aliases
- p_to
));
3694 size
+= (sizeof(struct WS_protoent
) - sizeof(struct protoent
));
3702 static int servent_size(struct servent
* p_se
)
3706 { size
+= sizeof(struct servent
);
3707 size
+= strlen(p_se
->s_proto
) + strlen(p_se
->s_name
) + 2;
3708 size
+= list_size(p_se
->s_aliases
, 0); }
3712 static int WS_dup_se(struct servent
* p_se
, int flag
)
3714 int size
= servent_size(p_se
);
3717 char *p_name
,*p_aliases
,*p_proto
,*p_base
,*p
;
3719 struct ws_servent16
*p_to16
;
3720 struct WS_servent
*p_to32
;
3722 check_buffer_se(size
);
3727 p_base
= (flag
& WS_DUP_SEGPTR
) ? (char*)se_buffer_seg
: se_buffer
;
3728 p
+= (flag
& WS_DUP_SEGPTR
) ?
3729 sizeof(struct ws_servent16
) : sizeof(struct WS_servent
);
3731 strcpy(p
, p_se
->s_name
); p
+= strlen(p
) + 1;
3733 strcpy(p
, p_se
->s_proto
); p
+= strlen(p
) + 1;
3735 list_dup(p_se
->s_aliases
, p
, p_base
+ (p
- p_to
), 0);
3737 if (flag
& WS_DUP_SEGPTR
) /* Win16 */
3739 p_to16
->s_port
= (INT16
)p_se
->s_port
;
3740 p_to16
->s_name
= (SEGPTR
)(p_base
+ (p_name
- p_to
));
3741 p_to16
->s_proto
= (SEGPTR
)(p_base
+ (p_proto
- p_to
));
3742 p_to16
->s_aliases
= (SEGPTR
)(p_base
+ (p_aliases
- p_to
));
3743 size
+= (sizeof(struct ws_servent16
) - sizeof(struct servent
));
3747 p_to32
->s_port
= p_se
->s_port
;
3748 p_to32
->s_name
= (p_base
+ (p_name
- p_to
));
3749 p_to32
->s_proto
= (p_base
+ (p_proto
- p_to
));
3750 p_to32
->s_aliases
= (char **)(p_base
+ (p_aliases
- p_to
));
3751 size
+= (sizeof(struct WS_servent
) - sizeof(struct servent
));
3757 /* ----------------------------------- error handling */
3759 UINT16
wsaErrno(void)
3761 int loc_errno
= errno
;
3762 WARN("errno %d, (%s).\n", loc_errno
, strerror(loc_errno
));
3766 case EINTR
: return WSAEINTR
;
3767 case EBADF
: return WSAEBADF
;
3769 case EACCES
: return WSAEACCES
;
3770 case EFAULT
: return WSAEFAULT
;
3771 case EINVAL
: return WSAEINVAL
;
3772 case EMFILE
: return WSAEMFILE
;
3773 case EWOULDBLOCK
: return WSAEWOULDBLOCK
;
3774 case EINPROGRESS
: return WSAEINPROGRESS
;
3775 case EALREADY
: return WSAEALREADY
;
3776 case ENOTSOCK
: return WSAENOTSOCK
;
3777 case EDESTADDRREQ
: return WSAEDESTADDRREQ
;
3778 case EMSGSIZE
: return WSAEMSGSIZE
;
3779 case EPROTOTYPE
: return WSAEPROTOTYPE
;
3780 case ENOPROTOOPT
: return WSAENOPROTOOPT
;
3781 case EPROTONOSUPPORT
: return WSAEPROTONOSUPPORT
;
3782 case ESOCKTNOSUPPORT
: return WSAESOCKTNOSUPPORT
;
3783 case EOPNOTSUPP
: return WSAEOPNOTSUPP
;
3784 case EPFNOSUPPORT
: return WSAEPFNOSUPPORT
;
3785 case EAFNOSUPPORT
: return WSAEAFNOSUPPORT
;
3786 case EADDRINUSE
: return WSAEADDRINUSE
;
3787 case EADDRNOTAVAIL
: return WSAEADDRNOTAVAIL
;
3788 case ENETDOWN
: return WSAENETDOWN
;
3789 case ENETUNREACH
: return WSAENETUNREACH
;
3790 case ENETRESET
: return WSAENETRESET
;
3791 case ECONNABORTED
: return WSAECONNABORTED
;
3793 case ECONNRESET
: return WSAECONNRESET
;
3794 case ENOBUFS
: return WSAENOBUFS
;
3795 case EISCONN
: return WSAEISCONN
;
3796 case ENOTCONN
: return WSAENOTCONN
;
3797 case ESHUTDOWN
: return WSAESHUTDOWN
;
3798 case ETOOMANYREFS
: return WSAETOOMANYREFS
;
3799 case ETIMEDOUT
: return WSAETIMEDOUT
;
3800 case ECONNREFUSED
: return WSAECONNREFUSED
;
3801 case ELOOP
: return WSAELOOP
;
3802 case ENAMETOOLONG
: return WSAENAMETOOLONG
;
3803 case EHOSTDOWN
: return WSAEHOSTDOWN
;
3804 case EHOSTUNREACH
: return WSAEHOSTUNREACH
;
3805 case ENOTEMPTY
: return WSAENOTEMPTY
;
3807 case EPROCLIM
: return WSAEPROCLIM
;
3810 case EUSERS
: return WSAEUSERS
;
3813 case EDQUOT
: return WSAEDQUOT
;
3816 case ESTALE
: return WSAESTALE
;
3819 case EREMOTE
: return WSAEREMOTE
;
3822 /* just in case we ever get here and there are no problems */
3825 WARN("Unknown errno %d!\n", loc_errno
);
3826 return WSAEOPNOTSUPP
;
3830 UINT16
wsaHerrno(int loc_errno
)
3833 WARN("h_errno %d.\n", loc_errno
);
3837 case HOST_NOT_FOUND
: return WSAHOST_NOT_FOUND
;
3838 case TRY_AGAIN
: return WSATRY_AGAIN
;
3839 case NO_RECOVERY
: return WSANO_RECOVERY
;
3840 case NO_DATA
: return WSANO_DATA
;
3841 case ENOBUFS
: return WSAENOBUFS
;
3845 WARN("Unknown h_errno %d!\n", loc_errno
);
3846 return WSAEOPNOTSUPP
;
3851 /***********************************************************************
3852 * WSARecv (WS2_32.67)
3854 int WINAPI
WSARecv (SOCKET s
, LPWSABUF lpBuffers
, DWORD dwBufferCount
,
3855 LPDWORD NumberOfBytesReceived
, LPDWORD lpFlags
,
3856 LPWSAOVERLAPPED lpOverlapped
,
3857 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
3859 return WSARecvFrom (s
, lpBuffers
, dwBufferCount
, NumberOfBytesReceived
, lpFlags
,
3860 NULL
, NULL
, lpOverlapped
, lpCompletionRoutine
);
3863 /***********************************************************************
3864 * WSARecvFrom (WS2_32.69)
3866 INT WINAPI
WSARecvFrom( SOCKET s
, LPWSABUF lpBuffers
, DWORD dwBufferCount
,
3867 LPDWORD lpNumberOfBytesRecvd
, LPDWORD lpFlags
, struct WS_sockaddr
*lpFrom
,
3868 LPINT lpFromlen
, LPWSAOVERLAPPED lpOverlapped
,
3869 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
3872 int i
, n
, fd
, err
= WSAENOTSOCK
, flags
, ret
;
3873 struct iovec
* iovec
;
3874 struct ws2_async
*wsa
;
3877 TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3878 s
, lpBuffers
, dwBufferCount
, *lpFlags
, lpFrom
,
3879 (lpFromlen
? *lpFromlen
: -1L),
3880 lpOverlapped
, lpCompletionRoutine
);
3882 fd
= _get_sock_fd_type( s
, GENERIC_READ
, &type
, &flags
);
3883 TRACE ( "fd=%d, type=%d, flags=%x\n", fd
, type
, flags
);
3887 err
= WSAGetLastError ();
3891 iovec
= HeapAlloc ( GetProcessHeap(), 0, dwBufferCount
* sizeof (struct iovec
) );
3898 for (i
= 0; i
< dwBufferCount
; i
++)
3900 iovec
[i
].iov_base
= lpBuffers
[i
].buf
;
3901 iovec
[i
].iov_len
= lpBuffers
[i
].len
;
3904 if ( (lpOverlapped
|| lpCompletionRoutine
) && flags
& FD_FLAG_OVERLAPPED
)
3906 wsa
= WS2_make_async ( s
, fd
, ASYNC_TYPE_READ
, iovec
, dwBufferCount
,
3907 lpFlags
, lpFrom
, lpFromlen
,
3908 lpOverlapped
, lpCompletionRoutine
);
3916 if ( ( ret
= register_new_async ( &wsa
->async
)) )
3918 err
= NtStatusToWSAError ( ret
);
3920 if ( !lpOverlapped
)
3921 HeapFree ( GetProcessHeap(), 0, wsa
->overlapped
);
3922 HeapFree ( GetProcessHeap(), 0, wsa
);
3926 /* Try immediate completion */
3927 if ( lpOverlapped
&& !NtResetEvent( lpOverlapped
->hEvent
, NULL
) )
3929 if ( WSAGetOverlappedResult ( s
, lpOverlapped
,
3930 lpNumberOfBytesRecvd
, FALSE
, lpFlags
) )
3933 if ( (err
= WSAGetLastError ()) != WSA_IO_INCOMPLETE
)
3937 WSASetLastError ( WSA_IO_PENDING
);
3938 return SOCKET_ERROR
;
3941 if ( _is_blocking(s
) )
3944 /* FIXME: OOB and exceptfds? */
3948 n
= WS2_recv ( fd
, iovec
, dwBufferCount
, lpFrom
, lpFromlen
, lpFlags
);
3955 TRACE(" -> %i bytes\n", n
);
3956 *lpNumberOfBytesRecvd
= n
;
3958 HeapFree (GetProcessHeap(), 0, iovec
);
3960 _enable_event(SOCKET2HANDLE(s
), FD_READ
, 0, 0);
3965 HeapFree (GetProcessHeap(), 0, iovec
);
3971 WARN(" -> ERROR %d\n", err
);
3972 WSASetLastError ( err
);
3973 return SOCKET_ERROR
;
3976 /***********************************************************************
3977 * WSCInstallProvider (WS2_32.88)
3979 INT WINAPI
WSCInstallProvider( const LPGUID lpProviderId
,
3980 LPCWSTR lpszProviderDllPath
,
3981 const LPWSAPROTOCOL_INFOW lpProtocolInfoList
,
3982 DWORD dwNumberOfEntries
,
3985 FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId
),
3986 debugstr_w(lpszProviderDllPath
), lpProtocolInfoList
,
3987 dwNumberOfEntries
, lpErrno
);
3993 /***********************************************************************
3994 * WSCDeinstallProvider (WS2_32.83)
3996 INT WINAPI
WSCDeinstallProvider(LPGUID lpProviderId
, LPINT lpErrno
)
3998 FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId
), lpErrno
);
4004 /***********************************************************************
4005 * WSAAccept (WS2_32.26)
4007 SOCKET WINAPI
WSAAccept( SOCKET s
, struct WS_sockaddr
*addr
, LPINT addrlen
,
4008 LPCONDITIONPROC lpfnCondition
, DWORD dwCallbackData
)
4011 int ret
= 0, size
= 0;
4012 WSABUF CallerId
, CallerData
, CalleeId
, CalleeData
;
4013 /* QOS SQOS, GQOS; */
4016 SOCKADDR src_addr
, dst_addr
;
4018 TRACE("Socket %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
4019 s
, addr
, addrlen
, lpfnCondition
, dwCallbackData
);
4022 size
= sizeof(src_addr
);
4023 cs
= WS_accept(s
, &src_addr
, &size
);
4025 if (cs
== SOCKET_ERROR
) return SOCKET_ERROR
;
4027 CallerId
.buf
= (char *)&src_addr
;
4028 CallerId
.len
= sizeof(src_addr
);
4030 CallerData
.buf
= NULL
;
4031 CallerData
.len
= (ULONG
)NULL
;
4033 WS_getsockname(cs
, &dst_addr
, &size
);
4035 CalleeId
.buf
= (char *)&dst_addr
;
4036 CalleeId
.len
= sizeof(dst_addr
);
4039 ret
= (*lpfnCondition
)(&CallerId
, &CallerData
, NULL
, NULL
,
4040 &CalleeId
, &CalleeData
, &g
, dwCallbackData
);
4045 if (addr
&& addrlen
)
4046 addr
= memcpy(addr
, &src_addr
, (*addrlen
> size
) ? size
: *addrlen
);
4049 SERVER_START_REQ ( set_socket_deferred
)
4051 req
->handle
= SOCKET2HANDLE (s
);
4052 req
->deferred
= SOCKET2HANDLE (cs
);
4053 if ( !wine_server_call_err ( req
) )
4055 SetLastError ( WSATRY_AGAIN
);
4056 WS_closesocket ( cs
);
4060 return SOCKET_ERROR
;
4063 SetLastError(WSAECONNREFUSED
);
4064 return SOCKET_ERROR
;
4066 FIXME("Unknown return type from Condition function\n");
4067 SetLastError(WSAENOTSOCK
);
4068 return SOCKET_ERROR
;
4072 /***********************************************************************
4073 * WSAEnumProtocolsA (WS2_32.37)
4075 int WINAPI
WSAEnumProtocolsA(LPINT lpiProtocols
, LPWSAPROTOCOL_INFOA lpProtocolBuffer
, LPDWORD lpdwBufferLength
)
4077 FIXME("(%p,%p,%p): stub\n", lpiProtocols
,lpProtocolBuffer
, lpdwBufferLength
);
4081 /***********************************************************************
4082 * WSAEnumProtocolsW (WS2_32.38)
4084 int WINAPI
WSAEnumProtocolsW(LPINT lpiProtocols
, LPWSAPROTOCOL_INFOW lpProtocolBuffer
, LPDWORD lpdwBufferLength
)
4086 FIXME("(%p,%p,%p): stub\n", lpiProtocols
,lpProtocolBuffer
, lpdwBufferLength
);
4090 /***********************************************************************
4091 * WSADuplicateSocketA (WS2_32.32)
4093 int WINAPI
WSADuplicateSocketA( SOCKET s
, DWORD dwProcessId
, LPWSAPROTOCOL_INFOA lpProtocolInfo
)
4097 TRACE("(%d,%lx,%p)\n", s
, dwProcessId
, lpProtocolInfo
);
4098 memset(lpProtocolInfo
, 0, sizeof(*lpProtocolInfo
));
4099 /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
4100 /* I don't know what the real Windoze does next, this is a hack */
4101 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
4102 * the target use the global duplicate, or we could copy a reference to us to the structure
4103 * and let the target duplicate it from us, but let's do it as simple as possible */
4104 hProcess
= OpenProcess(PROCESS_DUP_HANDLE
, FALSE
, dwProcessId
);
4105 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s
),
4106 hProcess
, (LPHANDLE
)&lpProtocolInfo
->dwCatalogEntryId
,
4107 0, FALSE
, DUPLICATE_SAME_ACCESS
);
4108 CloseHandle(hProcess
);
4109 lpProtocolInfo
->dwServiceFlags4
= 0xff00ff00; /* magic */
4113 /***********************************************************************
4114 * WSAInstallServiceClassA (WS2_32.48)
4116 int WINAPI
WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info
)
4118 FIXME("Request to install service %s\n",debugstr_a(info
->lpszServiceClassName
));
4119 WSASetLastError(WSAEACCES
);
4120 return SOCKET_ERROR
;
4123 /***********************************************************************
4124 * WSAInstallServiceClassW (WS2_32.49)
4126 int WINAPI
WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info
)
4128 FIXME("Request to install service %s\n",debugstr_w(info
->lpszServiceClassName
));
4129 WSASetLastError(WSAEACCES
);
4130 return SOCKET_ERROR
;
4133 /***********************************************************************
4134 * WSARemoveServiceClass (WS2_32.70)
4136 int WINAPI
WSARemoveServiceClass(LPGUID info
)
4138 FIXME("Request to remove service %p\n",info
);
4139 WSASetLastError(WSATYPE_NOT_FOUND
);
4140 return SOCKET_ERROR
;