2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
5 * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
7 * NOTE: If you make any changes to fix a particular app, make sure
8 * they don't break something else like Netscape or telnet and ftp
9 * clients and servers (www.winsite.com got a lot of those).
16 #include <sys/types.h>
20 #include <sys/ioctl.h>
21 #ifdef HAVE_SYS_FILIO_H
22 # include <sys/filio.h>
24 #if defined(__svr4__) || defined(__sun)
25 #include <sys/ioccom.h>
26 #ifdef HAVE_SYS_SOCKIO_H
27 # include <sys/sockio.h>
32 # include <sys/so_ioctl.h>
35 #ifdef HAVE_SYS_PARAM_H
36 # include <sys/param.h>
42 #ifdef HAVE_SYS_WAIT_H
43 # include <sys/wait.h>
45 #ifdef HAVE_SYS_SOCKET_H
46 #include <sys/socket.h>
48 #ifdef HAVE_NETINET_IN_H
49 # include <netinet/in.h>
51 #ifdef HAVE_NETINET_TCP_H
52 # include <netinet/tcp.h>
54 #ifdef HAVE_ARPA_INET_H
55 # include <arpa/inet.h>
60 #ifdef HAVE_SYS_ERRNO_H
61 #include <sys/errno.h>
66 #ifdef HAVE_ARPA_NAMESER_H
67 # include <arpa/nameser.h>
73 #include "wine/winbase16.h"
82 #include "wine/port.h"
85 #include "debugtools.h"
87 DEFAULT_DEBUG_CHANNEL(winsock
)
89 #define DEBUG_SOCKADDR 0
90 #define dump_sockaddr(a) \
91 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
92 ((struct sockaddr_in *)a)->sin_family, \
93 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
94 ntohs(((struct sockaddr_in *)a)->sin_port))
96 /* ----------------------------------- internal data */
98 /* ws_... struct conversion flags */
100 #define WS_DUP_LINEAR 0x0001
101 #define WS_DUP_NATIVE 0x0000 /* not used anymore */
102 #define WS_DUP_OFFSET 0x0002 /* internal pointers are offsets */
103 #define WS_DUP_SEGPTR 0x0004 /* internal pointers are SEGPTRs */
104 /* by default, internal pointers are linear */
105 typedef struct /* WSAAsyncSelect() control struct */
107 HANDLE service
, event
, sock
;
111 struct _WSINFO
*pwsi
;
114 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
115 #define WS_MAX_UDP_DATAGRAM 1024
117 #define WS_ACCEPT_QUEUE 6
119 #define WSI_BLOCKINGCALL 0x00000001 /* per-thread info flags */
120 #define WSI_BLOCKINGHOOK 0x00000002 /* 32-bit callback */
122 typedef struct _WSINFO
125 struct _WSINFO
*lpNextIData
;
128 INT16 num_startup
; /* reference counter */
130 INT16 last_free
; /* entry in the socket table */
132 char* buffer
; /* allocated from SEGPTR heap */
133 struct ws_hostent
*he
;
135 struct ws_servent
*se
;
137 struct ws_protoent
*pe
;
139 char* dbuffer
; /* buffer for dummies (32 bytes) */
143 volatile HANDLE accept_old
[WS_ACCEPT_QUEUE
], accept_new
[WS_ACCEPT_QUEUE
];
146 /* function prototypes */
147 int WS_dup_he(LPWSINFO pwsi
, struct hostent
* p_he
, int flag
);
148 int WS_dup_pe(LPWSINFO pwsi
, struct protoent
* p_pe
, int flag
);
149 int WS_dup_se(LPWSINFO pwsi
, struct servent
* p_se
, int flag
);
151 UINT16
wsaErrno(void);
152 UINT16
wsaHerrno(void);
154 static HANDLE _WSHeap
= 0;
156 #define WS_ALLOC(size) \
157 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
158 #define WS_FREE(ptr) \
159 HeapFree(_WSHeap, 0, (ptr) )
161 static INT _ws_sock_ops
[] =
162 { WS_SO_DEBUG
, WS_SO_REUSEADDR
, WS_SO_KEEPALIVE
, WS_SO_DONTROUTE
,
163 WS_SO_BROADCAST
, WS_SO_LINGER
, WS_SO_OOBINLINE
, WS_SO_SNDBUF
,
164 WS_SO_RCVBUF
, WS_SO_ERROR
, WS_SO_TYPE
, WS_SO_DONTLINGER
,
169 static int _px_sock_ops
[] =
170 { SO_DEBUG
, SO_REUSEADDR
, SO_KEEPALIVE
, SO_DONTROUTE
, SO_BROADCAST
,
171 SO_LINGER
, SO_OOBINLINE
, SO_SNDBUF
, SO_RCVBUF
, SO_ERROR
, SO_TYPE
,
172 WS_SO_DONTLINGER
, /* no unix equivalent */
178 static INT _ws_tcp_ops
[] = {
184 static int _px_tcp_ops
[] = {
191 /* we need a special routine to handle WSA* errors */
192 static inline int sock_server_call( enum request req
)
194 unsigned int res
= server_call_noerr( req
);
197 /* do not map WSA errors */
198 if ((res
< WSABASEERR
) || (res
>= 0x10000000)) res
= RtlNtStatusToDosError(res
);
204 static int _check_ws(LPWSINFO pwsi
, SOCKET s
);
205 static char* _check_buffer(LPWSINFO pwsi
, int size
);
207 static int _get_sock_fd(SOCKET s
)
209 struct get_read_fd_request
*req
= get_req_buffer();
213 server_call_fd( REQ_GET_READ_FD
, -1, &fd
);
215 FIXME("handle %d is not a socket (GLE %ld)\n",s
,GetLastError());
219 static void _enable_event(SOCKET s
, unsigned int event
,
220 unsigned int sstate
, unsigned int cstate
)
222 struct enable_socket_event_request
*req
= get_req_buffer();
226 req
->sstate
= sstate
;
227 req
->cstate
= cstate
;
228 sock_server_call( REQ_ENABLE_SOCKET_EVENT
);
231 static int _is_blocking(SOCKET s
)
233 struct get_socket_event_request
*req
= get_req_buffer();
236 req
->service
= FALSE
;
239 sock_server_call( REQ_GET_SOCKET_EVENT
);
240 return (req
->state
& WS_FD_NONBLOCKING
) == 0;
243 static unsigned int _get_sock_mask(SOCKET s
)
245 struct get_socket_event_request
*req
= get_req_buffer();
248 req
->service
= FALSE
;
251 sock_server_call( REQ_GET_SOCKET_EVENT
);
255 static void _sync_sock_state(SOCKET s
)
257 /* do a dummy wineserver request in order to let
258 the wineserver run through its select loop once */
259 (void)_is_blocking(s
);
262 static int _get_sock_error(SOCKET s
, unsigned int bit
)
264 struct get_socket_event_request
*req
= get_req_buffer();
267 req
->service
= FALSE
;
270 sock_server_call( REQ_GET_SOCKET_EVENT
);
271 return req
->errors
[bit
];
274 static LPWSINFO lpFirstIData
= NULL
;
276 static LPWSINFO
WINSOCK_GetIData(void)
278 DWORD pid
= GetCurrentProcessId();
281 for (iData
= lpFirstIData
; iData
; iData
= iData
->lpNextIData
) {
282 if (iData
->dwThisProcess
== pid
)
288 static BOOL
WINSOCK_CreateIData(void)
292 iData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WSINFO
));
295 iData
->dwThisProcess
= GetCurrentProcessId();
296 iData
->lpNextIData
= lpFirstIData
;
297 lpFirstIData
= iData
;
301 static void WINSOCK_DeleteIData(void)
303 LPWSINFO iData
= WINSOCK_GetIData();
306 for (ppid
= &lpFirstIData
; *ppid
; ppid
= &(*ppid
)->lpNextIData
) {
307 if (*ppid
== iData
) {
308 *ppid
= iData
->lpNextIData
;
313 if( iData
->flags
& WSI_BLOCKINGCALL
)
314 TRACE("\tinside blocking call!\n");
316 /* delete scratch buffers */
318 if( iData
->buffer
) SEGPTR_FREE(iData
->buffer
);
319 if( iData
->dbuffer
) SEGPTR_FREE(iData
->dbuffer
);
321 HeapFree(GetProcessHeap(), 0, iData
);
325 /***********************************************************************
326 * WSOCK32_LibMain (WSOCK32.init)
328 BOOL WINAPI
WSOCK32_LibMain(HINSTANCE hInstDLL
, DWORD fdwReason
, LPVOID fImpLoad
)
330 TRACE("0x%x 0x%lx %p\n", hInstDLL
, fdwReason
, fImpLoad
);
332 case DLL_PROCESS_DETACH
:
333 WINSOCK_DeleteIData();
339 /***********************************************************************
340 * WINSOCK_LibMain (WINSOCK.init)
342 BOOL WINAPI
WINSOCK_LibMain(DWORD fdwReason
, HINSTANCE hInstDLL
, WORD ds
,
343 WORD wHeapSize
, DWORD dwReserved1
, WORD wReserved2
)
345 TRACE("0x%x 0x%lx\n", hInstDLL
, fdwReason
);
347 case DLL_PROCESS_DETACH
:
348 WINSOCK_DeleteIData();
354 /***********************************************************************
357 * Converts socket flags from Windows format.
359 static void convert_sockopt(INT
*level
, INT
*optname
)
366 for(i
=0; _ws_sock_ops
[i
]; i
++)
367 if( _ws_sock_ops
[i
] == *optname
) break;
368 if( _ws_sock_ops
[i
] ) *optname
= _px_sock_ops
[i
];
369 else FIXME("Unknown SOL_SOCKET optname %d\n", *optname
);
372 *level
= IPPROTO_TCP
;
373 for(i
=0; _ws_tcp_ops
[i
]; i
++)
374 if ( _ws_tcp_ops
[i
] == *optname
) break;
375 if( _ws_tcp_ops
[i
] ) *optname
= _px_tcp_ops
[i
];
376 else FIXME("Unknown IPPROTO_TCP optname %d\n", *optname
);
381 /* ----------------------------------- Per-thread info (or per-process?) */
383 static int wsi_strtolo(LPWSINFO pwsi
, const char* name
, const char* opt
)
385 /* Stuff a lowercase copy of the string into the local buffer */
387 int i
= strlen(name
) + 2;
388 char* p
= _check_buffer(pwsi
, i
+ ((opt
)?strlen(opt
):0));
392 do *p
++ = tolower(*name
); while(*name
++);
393 i
= (p
- (char*)(pwsi
->buffer
));
394 if( opt
) do *p
++ = tolower(*opt
); while(*opt
++);
400 static fd_set
* fd_set_import( fd_set
* fds
, LPWSINFO pwsi
, void* wsfds
, int* highfd
, int lfd
[], BOOL b32
)
402 /* translate Winsock fd set into local fd set */
406 #define wsfds16 ((ws_fd_set16*)wsfds)
407 #define wsfds32 ((ws_fd_set32*)wsfds)
411 count
= b32
? wsfds32
->fd_count
: wsfds16
->fd_count
;
413 for( i
= 0; i
< count
; i
++ )
415 int s
= (b32
) ? wsfds32
->fd_array
[i
]
416 : wsfds16
->fd_array
[i
];
417 if( _check_ws(pwsi
, s
) )
419 int fd
= _get_sock_fd(s
);
421 if( fd
> *highfd
) *highfd
= fd
;
433 inline static int sock_error_p(int s
)
435 unsigned int optval
, optlen
;
437 optlen
= sizeof(optval
);
438 getsockopt(s
, SOL_SOCKET
, SO_ERROR
, (void *) &optval
, &optlen
);
439 if (optval
) WARN("\t[%i] error: %d\n", s
, optval
);
443 static int fd_set_export( LPWSINFO pwsi
, fd_set
* fds
, fd_set
* exceptfds
, void* wsfds
, int lfd
[], BOOL b32
)
447 /* translate local fd set into Winsock fd set, adding
448 * errors to exceptfds (only if app requested it) */
452 #define wsfds16 ((ws_fd_set16*)wsfds)
453 #define wsfds32 ((ws_fd_set32*)wsfds)
454 int i
, j
, count
= (b32
) ? wsfds32
->fd_count
: wsfds16
->fd_count
;
456 for( i
= 0, j
= 0; i
< count
; i
++ )
461 if( FD_ISSET(fd
, fds
) )
463 if ( exceptfds
&& sock_error_p(fd
) )
465 FD_SET(fd
, exceptfds
);
469 wsfds32
->fd_array
[j
++] = wsfds32
->fd_array
[i
];
471 wsfds16
->fd_array
[j
++] = wsfds16
->fd_array
[i
];
478 if( b32
) wsfds32
->fd_count
= j
;
479 else wsfds16
->fd_count
= j
;
488 static void fd_set_unimport( void* wsfds
, int lfd
[], BOOL b32
)
492 #define wsfds16 ((ws_fd_set16*)wsfds)
493 #define wsfds32 ((ws_fd_set32*)wsfds)
494 int i
, count
= (b32
) ? wsfds32
->fd_count
: wsfds16
->fd_count
;
496 for( i
= 0; i
< count
; i
++ )
506 static int do_block( int fd
, int mask
)
517 i
= select( fd
+1, &fds
[0], &fds
[1], &fds
[2], NULL
);
518 if (i
<= 0) return -1;
521 if (FD_ISSET(fd
, &fds
[i
]))
526 void* __ws_memalloc( int size
)
528 return WS_ALLOC(size
);
531 void __ws_memfree(void* ptr
)
537 /* ----------------------------------- API -----
539 * Init / cleanup / error checking.
542 /***********************************************************************
543 * WSAStartup16() (WINSOCK.115)
545 * Create socket control struct, attach it to the global list and
546 * update a pointer in the task struct.
548 INT16 WINAPI
WSAStartup16(UINT16 wVersionRequested
, LPWSADATA lpWSAData
)
550 WSADATA WINSOCK_data
= { 0x0101, 0x0101,
554 #elif defined(__NetBSD__)
558 #elif defined(__FreeBSD__)
560 #elif defined(__OpenBSD__)
565 WS_MAX_SOCKETS_PER_PROCESS
,
566 WS_MAX_UDP_DATAGRAM
, (SEGPTR
)NULL
};
569 TRACE("verReq=%x\n", wVersionRequested
);
571 if (LOBYTE(wVersionRequested
) < 1 || (LOBYTE(wVersionRequested
) == 1 &&
572 HIBYTE(wVersionRequested
) < 1)) return WSAVERNOTSUPPORTED
;
574 if (!lpWSAData
) return WSAEINVAL
;
576 /* initialize socket heap */
580 _WSHeap
= HeapCreate(HEAP_ZERO_MEMORY
, 8120, 32768);
583 ERR("Fatal: failed to create WinSock heap\n");
587 if( _WSHeap
== 0 ) return WSASYSNOTREADY
;
589 pwsi
= WINSOCK_GetIData();
592 WINSOCK_CreateIData();
593 pwsi
= WINSOCK_GetIData();
594 if (!pwsi
) return WSASYSNOTREADY
;
598 /* return winsock information */
600 memcpy(lpWSAData
, &WINSOCK_data
, sizeof(WINSOCK_data
));
602 TRACE("succeeded\n");
606 /***********************************************************************
607 * WSAStartup() (WS2_32.115)
609 INT WINAPI
WSAStartup(UINT wVersionRequested
, LPWSADATA lpWSAData
)
611 WSADATA WINSOCK_data
= { 0x0202, 0x0202,
615 #elif defined(__NetBSD__)
619 #elif defined(__FreeBSD__)
621 #elif defined(__OpenBSD__)
626 WS_MAX_SOCKETS_PER_PROCESS
,
627 WS_MAX_UDP_DATAGRAM
, (SEGPTR
)NULL
};
630 TRACE("verReq=%x\n", wVersionRequested
);
632 if (LOBYTE(wVersionRequested
) < 1)
633 return WSAVERNOTSUPPORTED
;
635 if (!lpWSAData
) return WSAEINVAL
;
637 /* initialize socket heap */
641 _WSHeap
= HeapCreate(HEAP_ZERO_MEMORY
, 8120, 32768);
644 ERR("Fatal: failed to create WinSock heap\n");
648 if( _WSHeap
== 0 ) return WSASYSNOTREADY
;
650 pwsi
= WINSOCK_GetIData();
653 WINSOCK_CreateIData();
654 pwsi
= WINSOCK_GetIData();
655 if (!pwsi
) return WSASYSNOTREADY
;
659 /* return winsock information */
660 memcpy(lpWSAData
, &WINSOCK_data
, sizeof(WINSOCK_data
));
662 /* that's the whole of the negotiation for now */
663 lpWSAData
->wVersion
= wVersionRequested
;
665 TRACE("succeeded\n");
670 /***********************************************************************
671 * WSACleanup() (WINSOCK.116)
673 INT WINAPI
WSACleanup(void)
675 LPWSINFO pwsi
= WINSOCK_GetIData();
677 if( --pwsi
->num_startup
> 0 ) return 0;
679 WINSOCK_DeleteIData();
682 SetLastError(WSANOTINITIALISED
);
687 /***********************************************************************
688 * WSAGetLastError() (WSOCK32.111)(WINSOCK.111)
690 INT WINAPI
WSAGetLastError(void)
692 return GetLastError();
695 /***********************************************************************
696 * WSASetLastError() (WSOCK32.112)
698 void WINAPI
WSASetLastError(INT iError
) {
699 SetLastError(iError
);
702 /***********************************************************************
703 * WSASetLastError16() (WINSOCK.112)
705 void WINAPI
WSASetLastError16(INT16 iError
)
707 WSASetLastError(iError
);
710 int _check_ws(LPWSINFO pwsi
, SOCKET s
)
715 if( pwsi
->flags
& WSI_BLOCKINGCALL
) SetLastError(WSAEINPROGRESS
);
716 if ( (fd
= _get_sock_fd(s
)) < 0 ) {
717 SetLastError(WSAENOTSOCK
);
720 /* FIXME: maybe check whether fd is really a socket? */
727 char* _check_buffer(LPWSINFO pwsi
, int size
)
729 if( pwsi
->buffer
&& pwsi
->buflen
>= size
) return pwsi
->buffer
;
730 else SEGPTR_FREE(pwsi
->buffer
);
732 pwsi
->buffer
= (char*)SEGPTR_ALLOC((pwsi
->buflen
= size
));
736 struct ws_hostent
* _check_buffer_he(LPWSINFO pwsi
, int size
)
738 if( pwsi
->he
&& pwsi
->helen
>= size
) return pwsi
->he
;
739 else SEGPTR_FREE(pwsi
->he
);
741 pwsi
->he
= (struct ws_hostent
*)SEGPTR_ALLOC((pwsi
->helen
= size
));
745 struct ws_servent
* _check_buffer_se(LPWSINFO pwsi
, int size
)
747 if( pwsi
->se
&& pwsi
->selen
>= size
) return pwsi
->se
;
748 else SEGPTR_FREE(pwsi
->se
);
750 pwsi
->se
= (struct ws_servent
*)SEGPTR_ALLOC((pwsi
->selen
= size
));
754 struct ws_protoent
* _check_buffer_pe(LPWSINFO pwsi
, int size
)
756 if( pwsi
->pe
&& pwsi
->pelen
>= size
) return pwsi
->pe
;
757 else SEGPTR_FREE(pwsi
->pe
);
759 pwsi
->pe
= (struct ws_protoent
*)SEGPTR_ALLOC((pwsi
->pelen
= size
));
763 /* ----------------------------------- i/o APIs */
765 /***********************************************************************
766 * accept() (WSOCK32.1)
768 static void WSOCK32_async_accept(LPWSINFO pwsi
, SOCKET s
, SOCKET as
)
771 /* queue socket for WSAAsyncSelect */
772 for (q
=0; q
<WS_ACCEPT_QUEUE
; q
++)
773 if (InterlockedCompareExchange((PVOID
*)&pwsi
->accept_old
[q
], (PVOID
)s
, (PVOID
)0) == (PVOID
)0)
775 if (q
<WS_ACCEPT_QUEUE
)
776 pwsi
->accept_new
[q
] = as
;
778 ERR("accept queue too small\n");
779 /* now signal our AsyncSelect handler */
780 _enable_event(s
, WS_FD_SERVEVENT
, 0, 0);
783 SOCKET WINAPI
WSOCK32_accept(SOCKET s
, struct sockaddr
*addr
,
786 LPWSINFO pwsi
= WINSOCK_GetIData();
788 struct ws_sockaddr_ipx
* addr2
= (struct ws_sockaddr_ipx
*)addr
;
790 struct accept_socket_request
*req
= get_req_buffer();
792 TRACE("(%08x): socket %04x\n",
793 (unsigned)pwsi
, (UINT16
)s
);
794 if( _check_ws(pwsi
, s
) )
799 int fd
= _get_sock_fd(s
);
802 _sync_sock_state(s
); /* let wineserver notice connection */
803 /* retrieve any error codes from it */
804 SetLastError(_get_sock_error(s
, FD_ACCEPT_BIT
));
805 /* FIXME: care about the error? */
808 req
->access
= GENERIC_READ
|GENERIC_WRITE
|SYNCHRONIZE
;
810 sock_server_call( REQ_ACCEPT_SOCKET
);
811 if( req
->handle
>= 0 )
813 SOCKET as
= req
->handle
;
814 unsigned omask
= _get_sock_mask( s
);
815 int fd
= _get_sock_fd( as
);
816 if( getpeername(fd
, addr
, addrlen32
) != -1 )
819 if (addr
&& ((struct sockaddr_ipx
*)addr
)->sipx_family
== AF_IPX
) {
820 addr
= (struct sockaddr
*)
821 malloc(addrlen32
? *addrlen32
: sizeof(*addr2
));
823 addrlen32
? *addrlen32
: sizeof(*addr2
));
824 addr2
->sipx_family
= WS_AF_IPX
;
825 addr2
->sipx_network
= ((struct sockaddr_ipx
*)addr
)->sipx_network
;
826 addr2
->sipx_port
= ((struct sockaddr_ipx
*)addr
)->sipx_port
;
827 memcpy(addr2
->sipx_node
,
828 ((struct sockaddr_ipx
*)addr
)->sipx_node
, IPX_NODE_LEN
);
832 } else SetLastError(wsaErrno());
834 if (omask
& WS_FD_SERVEVENT
)
835 WSOCK32_async_accept(pwsi
, s
, as
);
839 return INVALID_SOCKET
;
842 /***********************************************************************
843 * accept() (WINSOCK.1)
845 SOCKET16 WINAPI
WINSOCK_accept16(SOCKET16 s
, struct sockaddr
* addr
,
848 INT addrlen32
= addrlen16
? *addrlen16
: 0;
849 SOCKET retSocket
= WSOCK32_accept( s
, addr
, &addrlen32
);
850 if( addrlen16
) *addrlen16
= (INT16
)addrlen32
;
851 return (SOCKET16
)retSocket
;
854 /***********************************************************************
857 INT WINAPI
WSOCK32_bind(SOCKET s
, struct sockaddr
*name
, INT namelen
)
859 LPWSINFO pwsi
= WINSOCK_GetIData();
861 struct ws_sockaddr_ipx
* name2
= (struct ws_sockaddr_ipx
*)name
;
864 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
865 (unsigned)pwsi
, s
, (int) name
, namelen
);
870 if ( _check_ws(pwsi
, s
) )
872 int fd
= _get_sock_fd(s
);
873 /* FIXME: what family does this really map to on the Unix side? */
874 if (name
&& ((struct ws_sockaddr_ipx
*)name
)->sipx_family
== WS_AF_PUP
)
875 ((struct ws_sockaddr_ipx
*)name
)->sipx_family
= AF_UNSPEC
;
878 ((struct ws_sockaddr_ipx
*)name
)->sipx_family
== WS_AF_IPX
)
880 name
= (struct sockaddr
*) malloc(sizeof(struct sockaddr_ipx
));
881 memset(name
, '\0', sizeof(struct sockaddr_ipx
));
882 ((struct sockaddr_ipx
*)name
)->sipx_family
= AF_IPX
;
883 ((struct sockaddr_ipx
*)name
)->sipx_port
= name2
->sipx_port
;
884 ((struct sockaddr_ipx
*)name
)->sipx_network
= name2
->sipx_network
;
885 memcpy(((struct sockaddr_ipx
*)name
)->sipx_node
,
886 name2
->sipx_node
, IPX_NODE_LEN
);
887 namelen
= sizeof(struct sockaddr_ipx
);
890 if ( namelen
>= sizeof(*name
) )
892 if ( name
&& (((struct ws_sockaddr_in
*)name
)->sin_family
== AF_INET
894 || ((struct sockaddr_ipx
*)name
)->sipx_family
== AF_IPX
898 if ( bind(fd
, name
, namelen
) < 0 )
900 int loc_errno
= errno
;
901 WARN("\tfailure - errno = %i\n", errno
);
905 case EBADF
: SetLastError(WSAENOTSOCK
); break;
906 case EADDRNOTAVAIL
: SetLastError(WSAEINVAL
); break;
907 default: SetLastError(wsaErrno());break;
912 if (((struct sockaddr_ipx
*)name
)->sipx_family
== AF_IPX
)
916 return 0; /* success */
918 } else SetLastError(WSAEAFNOSUPPORT
);
919 } else SetLastError(WSAEFAULT
);
921 if (name
&& ((struct sockaddr_ipx
*)name
)->sipx_family
== AF_IPX
)
929 /***********************************************************************
932 INT16 WINAPI
WINSOCK_bind16(SOCKET16 s
, struct sockaddr
*name
, INT16 namelen
)
934 return (INT16
)WSOCK32_bind( s
, name
, namelen
);
937 /***********************************************************************
938 * closesocket() (WSOCK32.3)
940 INT WINAPI
WSOCK32_closesocket(SOCKET s
)
942 LPWSINFO pwsi
= WINSOCK_GetIData();
944 TRACE("(%08x): socket %08x\n", (unsigned)pwsi
, s
);
946 if( _check_ws(pwsi
, s
) )
954 /***********************************************************************
955 * closesocket() (WINSOCK.3)
957 INT16 WINAPI
WINSOCK_closesocket16(SOCKET16 s
)
959 return (INT16
)WSOCK32_closesocket(s
);
962 /***********************************************************************
963 * connect() (WSOCK32.4)
965 INT WINAPI
WSOCK32_connect(SOCKET s
, struct sockaddr
*name
, INT namelen
)
967 LPWSINFO pwsi
= WINSOCK_GetIData();
969 struct ws_sockaddr_ipx
* name2
= (struct ws_sockaddr_ipx
*)name
;
972 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
973 (unsigned)pwsi
, s
, (int) name
, namelen
);
978 if( _check_ws(pwsi
, s
) )
980 int fd
= _get_sock_fd(s
);
981 if (name
&& ((struct ws_sockaddr_ipx
*)name
)->sipx_family
== WS_AF_PUP
)
982 ((struct ws_sockaddr_ipx
*)name
)->sipx_family
= AF_UNSPEC
;
984 else if (name
&& ((struct ws_sockaddr_ipx
*)name
)->sipx_family
== WS_AF_IPX
)
986 name
= (struct sockaddr
*) malloc(sizeof(struct sockaddr_ipx
));
987 memset(name
, '\0', sizeof(struct sockaddr_ipx
));
988 ((struct sockaddr_ipx
*)name
)->sipx_family
= AF_IPX
;
989 ((struct sockaddr_ipx
*)name
)->sipx_port
= name2
->sipx_port
;
990 ((struct sockaddr_ipx
*)name
)->sipx_network
= name2
->sipx_network
;
991 memcpy(((struct sockaddr_ipx
*)name
)->sipx_node
,
992 name2
->sipx_node
, IPX_NODE_LEN
);
993 namelen
= sizeof(struct sockaddr_ipx
);
996 if (connect(fd
, name
, namelen
) == 0) {
998 goto connect_success
;
1000 if (errno
== EINPROGRESS
)
1002 /* tell wineserver that a connection is in progress */
1003 _enable_event(s
, FD_CONNECT
|FD_READ
|FD_WRITE
,
1004 WS_FD_CONNECT
|WS_FD_READ
|WS_FD_WRITE
,
1005 WS_FD_CONNECTED
|WS_FD_LISTENING
);
1006 if (_is_blocking(s
))
1011 _sync_sock_state(s
); /* let wineserver notice connection */
1012 /* retrieve any error codes from it */
1013 result
= _get_sock_error(s
, FD_CONNECT_BIT
);
1015 SetLastError(result
);
1018 goto connect_success
;
1021 else SetLastError(WSAEWOULDBLOCK
);
1026 SetLastError(wsaErrno());
1031 if (name
&& ((struct sockaddr_ipx
*)name
)->sipx_family
== AF_IPX
)
1034 return SOCKET_ERROR
;
1037 if (((struct sockaddr_ipx
*)name
)->sipx_family
== AF_IPX
)
1040 _enable_event(s
, FD_CONNECT
|FD_READ
|FD_WRITE
,
1041 WS_FD_CONNECTED
|WS_FD_READ
|WS_FD_WRITE
,
1042 WS_FD_CONNECT
|WS_FD_LISTENING
);
1046 /***********************************************************************
1047 * connect() (WINSOCK.4)
1049 INT16 WINAPI
WINSOCK_connect16(SOCKET16 s
, struct sockaddr
*name
, INT16 namelen
)
1051 return (INT16
)WSOCK32_connect( s
, name
, namelen
);
1054 /***********************************************************************
1055 * getpeername() (WSOCK32.5)
1057 INT WINAPI
WSOCK32_getpeername(SOCKET s
, struct sockaddr
*name
,
1060 LPWSINFO pwsi
= WINSOCK_GetIData();
1062 struct ws_sockaddr_ipx
* name2
= (struct ws_sockaddr_ipx
*)name
;
1065 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1066 (unsigned)pwsi
, s
, (int) name
, *namelen
);
1067 if( _check_ws(pwsi
, s
) )
1069 int fd
= _get_sock_fd(s
);
1070 if (getpeername(fd
, name
, namelen
) == 0) {
1072 if (((struct ws_sockaddr_ipx
*)name
)->sipx_family
== AF_IPX
) {
1073 name
= (struct sockaddr
*)
1074 malloc(namelen
? *namelen
: sizeof(*name2
));
1075 memcpy(name
, name2
, namelen
? *namelen
: sizeof(*name2
));
1076 name2
->sipx_family
= WS_AF_IPX
;
1077 name2
->sipx_network
= ((struct sockaddr_ipx
*)name
)->sipx_network
;
1078 name2
->sipx_port
= ((struct sockaddr_ipx
*)name
)->sipx_port
;
1079 memcpy(name2
->sipx_node
,
1080 ((struct sockaddr_ipx
*)name
)->sipx_node
, IPX_NODE_LEN
);
1087 SetLastError(wsaErrno());
1090 return SOCKET_ERROR
;
1093 /***********************************************************************
1094 * getpeername() (WINSOCK.5)
1096 INT16 WINAPI
WINSOCK_getpeername16(SOCKET16 s
, struct sockaddr
*name
,
1099 INT namelen32
= *namelen16
;
1100 INT retVal
= WSOCK32_getpeername( s
, name
, &namelen32
);
1103 dump_sockaddr(name
);
1106 *namelen16
= namelen32
;
1107 return (INT16
)retVal
;
1110 /***********************************************************************
1111 * getsockname() (WSOCK32.6)
1113 INT WINAPI
WSOCK32_getsockname(SOCKET s
, struct sockaddr
*name
,
1116 LPWSINFO pwsi
= WINSOCK_GetIData();
1118 struct ws_sockaddr_ipx
* name2
= (struct ws_sockaddr_ipx
*)name
;
1121 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1122 (unsigned)pwsi
, s
, (int) name
, (int) *namelen
);
1123 if( _check_ws(pwsi
, s
) )
1125 int fd
= _get_sock_fd(s
);
1126 if (getsockname(fd
, name
, namelen
) == 0) {
1128 if (((struct sockaddr_ipx
*)name
)->sipx_family
== AF_IPX
) {
1129 name
= (struct sockaddr
*)
1130 malloc(namelen
? *namelen
: sizeof(*name2
));
1131 memcpy(name
, name2
, namelen
? *namelen
: sizeof(*name2
));
1132 name2
->sipx_family
= WS_AF_IPX
;
1133 name2
->sipx_network
= ((struct sockaddr_ipx
*)name
)->sipx_network
;
1134 name2
->sipx_port
= ((struct sockaddr_ipx
*)name
)->sipx_port
;
1135 memcpy(name2
->sipx_node
,
1136 ((struct sockaddr_ipx
*)name
)->sipx_node
, IPX_NODE_LEN
);
1143 SetLastError(wsaErrno());
1146 return SOCKET_ERROR
;
1149 /***********************************************************************
1150 * getsockname() (WINSOCK.6)
1152 INT16 WINAPI
WINSOCK_getsockname16(SOCKET16 s
, struct sockaddr
*name
,
1159 INT namelen32
= *namelen16
;
1160 retVal
= WSOCK32_getsockname( s
, name
, &namelen32
);
1161 *namelen16
= namelen32
;
1164 dump_sockaddr(name
);
1168 else retVal
= SOCKET_ERROR
;
1169 return (INT16
)retVal
;
1173 /***********************************************************************
1174 * getsockopt() (WSOCK32.7)
1176 INT WINAPI
WSOCK32_getsockopt(SOCKET s
, INT level
,
1177 INT optname
, char *optval
, INT
*optlen
)
1179 LPWSINFO pwsi
= WINSOCK_GetIData();
1181 TRACE("(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n",
1182 (unsigned)pwsi
, s
, level
, (int) optval
, (int) *optlen
);
1183 if( _check_ws(pwsi
, s
) )
1185 int fd
= _get_sock_fd(s
);
1186 convert_sockopt(&level
, &optname
);
1187 if (getsockopt(fd
, (int) level
, optname
, optval
, optlen
) == 0 )
1192 SetLastError((errno
== EBADF
) ? WSAENOTSOCK
: wsaErrno());
1195 return SOCKET_ERROR
;
1198 /***********************************************************************
1199 * getsockopt() (WINSOCK.7)
1201 INT16 WINAPI
WINSOCK_getsockopt16(SOCKET16 s
, INT16 level
,
1202 INT16 optname
, char *optval
, INT16
*optlen
)
1207 if( optlen
) optlen32
= *optlen
; else p
= NULL
;
1208 retVal
= WSOCK32_getsockopt( s
, (UINT16
)level
, optname
, optval
, p
);
1209 if( optlen
) *optlen
= optlen32
;
1210 return (INT16
)retVal
;
1213 /***********************************************************************
1214 * htonl() (WINSOCK.8)(WSOCK32.8)
1216 u_long WINAPI
WINSOCK_htonl(u_long hostlong
) { return( htonl(hostlong
) ); }
1217 /***********************************************************************
1218 * htons() (WINSOCK.9)(WSOCK32.9)
1220 u_short WINAPI
WINSOCK_htons(u_short hostshort
) { return( htons(hostshort
) ); }
1221 /***********************************************************************
1222 * inet_addr() (WINSOCK.10)(WSOCK32.10)
1224 u_long WINAPI
WINSOCK_inet_addr(char *cp
) { return( inet_addr(cp
) ); }
1225 /***********************************************************************
1226 * ntohl() (WINSOCK.14)(WSOCK32.14)
1228 u_long WINAPI
WINSOCK_ntohl(u_long netlong
) { return( ntohl(netlong
) ); }
1229 /***********************************************************************
1230 * ntohs() (WINSOCK.15)(WSOCK32.15)
1232 u_short WINAPI
WINSOCK_ntohs(u_short netshort
) { return( ntohs(netshort
) ); }
1234 /***********************************************************************
1235 * inet_ntoa() (WINSOCK.11)(WSOCK32.11)
1237 char* WINAPI
WSOCK32_inet_ntoa(struct in_addr in
)
1239 /* use "buffer for dummies" here because some applications have
1240 * propensity to decode addresses in ws_hostent structure without
1241 * saving them first...
1244 LPWSINFO pwsi
= WINSOCK_GetIData();
1248 char* s
= inet_ntoa(in
);
1251 if( pwsi
->dbuffer
== NULL
) {
1252 /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1253 if((pwsi
->dbuffer
= (char*) SEGPTR_ALLOC(16)) == NULL
)
1255 SetLastError(WSAENOBUFS
);
1259 strcpy(pwsi
->dbuffer
, s
);
1260 return pwsi
->dbuffer
;
1262 SetLastError(wsaErrno());
1267 SEGPTR WINAPI
WINSOCK_inet_ntoa16(struct in_addr in
)
1269 char* retVal
= WSOCK32_inet_ntoa(in
);
1270 return retVal
? SEGPTR_GET(retVal
) : (SEGPTR
)NULL
;
1273 /***********************************************************************
1274 * ioctlsocket() (WSOCK32.12)
1276 INT WINAPI
WSOCK32_ioctlsocket(SOCKET s
, LONG cmd
, ULONG
*argp
)
1278 LPWSINFO pwsi
= WINSOCK_GetIData();
1280 TRACE("(%08x): socket %04x, cmd %08lx, ptr %8x\n",
1281 (unsigned)pwsi
, s
, cmd
, (unsigned) argp
);
1282 if( _check_ws(pwsi
, s
) )
1284 int fd
= _get_sock_fd(s
);
1295 if( _get_sock_mask(s
) )
1297 /* AsyncSelect()'ed sockets are always nonblocking */
1302 SetLastError(WSAEINVAL
);
1304 return SOCKET_ERROR
;
1308 _enable_event(s
, 0, WS_FD_NONBLOCKING
, 0);
1310 _enable_event(s
, 0, 0, WS_FD_NONBLOCKING
);
1317 case WS_IOW('f',125,u_long
):
1318 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1319 SetLastError(WSAEINVAL
);
1320 return SOCKET_ERROR
;
1323 /* Netscape tries hard to use bogus ioctl 0x667e */
1324 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd
);
1326 if( ioctl(fd
, newcmd
, (char*)argp
) == 0 )
1331 SetLastError((errno
== EBADF
) ? WSAENOTSOCK
: wsaErrno());
1334 return SOCKET_ERROR
;
1337 /***********************************************************************
1338 * ioctlsocket() (WINSOCK.12)
1340 INT16 WINAPI
WINSOCK_ioctlsocket16(SOCKET16 s
, LONG cmd
, ULONG
*argp
)
1342 return (INT16
)WSOCK32_ioctlsocket( s
, cmd
, argp
);
1346 /***********************************************************************
1347 * listen() (WSOCK32.13)
1349 INT WINAPI
WSOCK32_listen(SOCKET s
, INT backlog
)
1351 LPWSINFO pwsi
= WINSOCK_GetIData();
1353 TRACE("(%08x): socket %04x, backlog %d\n",
1354 (unsigned)pwsi
, s
, backlog
);
1355 if( _check_ws(pwsi
, s
) )
1357 int fd
= _get_sock_fd(s
);
1358 if (listen(fd
, backlog
) == 0)
1361 _enable_event(s
, FD_ACCEPT
,
1363 WS_FD_CONNECT
|WS_FD_CONNECTED
);
1366 SetLastError(wsaErrno());
1368 else SetLastError(WSAENOTSOCK
);
1369 return SOCKET_ERROR
;
1372 /***********************************************************************
1373 * listen() (WINSOCK.13)
1375 INT16 WINAPI
WINSOCK_listen16(SOCKET16 s
, INT16 backlog
)
1377 return (INT16
)WSOCK32_listen( s
, backlog
);
1381 /***********************************************************************
1382 * recv() (WSOCK32.16)
1384 INT WINAPI
WSOCK32_recv(SOCKET s
, char *buf
, INT len
, INT flags
)
1386 LPWSINFO pwsi
= WINSOCK_GetIData();
1388 TRACE("(%08x): socket %04x, buf %8x, len %d, "
1389 "flags %d\n", (unsigned)pwsi
, s
, (unsigned)buf
,
1391 if( _check_ws(pwsi
, s
) )
1393 int fd
= _get_sock_fd(s
);
1396 if (_is_blocking(s
))
1399 /* FIXME: OOB and exceptfds? */
1402 if ((length
= recv(fd
, buf
, len
, flags
)) >= 0)
1404 TRACE(" -> %i bytes\n", length
);
1407 _enable_event(s
, FD_READ
, 0, 0);
1410 SetLastError(wsaErrno());
1413 else SetLastError(WSAENOTSOCK
);
1414 WARN(" -> ERROR\n");
1415 return SOCKET_ERROR
;
1418 /***********************************************************************
1419 * recv() (WINSOCK.16)
1421 INT16 WINAPI
WINSOCK_recv16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
)
1423 return (INT16
)WSOCK32_recv( s
, buf
, len
, flags
);
1427 /***********************************************************************
1428 * recvfrom() (WSOCK32.17)
1430 INT WINAPI
WSOCK32_recvfrom(SOCKET s
, char *buf
, INT len
, INT flags
,
1431 struct sockaddr
*from
, INT
*fromlen32
)
1433 LPWSINFO pwsi
= WINSOCK_GetIData();
1435 struct ws_sockaddr_ipx
* from2
= (struct ws_sockaddr_ipx
*)from
;
1438 TRACE("(%08x): socket %04x, ptr %08x, "
1439 "len %d, flags %d\n", (unsigned)pwsi
, s
, (unsigned)buf
,
1442 if( from
) dump_sockaddr(from
);
1443 else DPRINTF("from = NULL\n");
1446 if( _check_ws(pwsi
, s
) )
1448 int fd
= _get_sock_fd(s
);
1451 if (_is_blocking(s
))
1454 /* FIXME: OOB and exceptfds */
1457 if ((length
= recvfrom(fd
, buf
, len
, flags
, from
, fromlen32
)) >= 0)
1459 TRACE(" -> %i bytes\n", length
);
1462 if (from
&& ((struct sockaddr_ipx
*)from
)->sipx_family
== AF_IPX
) {
1463 from
= (struct sockaddr
*)
1464 malloc(fromlen32
? *fromlen32
: sizeof(*from2
));
1465 memcpy(from
, from2
, fromlen32
? *fromlen32
: sizeof(*from2
));
1466 from2
->sipx_family
= WS_AF_IPX
;
1467 from2
->sipx_network
= ((struct sockaddr_ipx
*)from
)->sipx_network
;
1468 from2
->sipx_port
= ((struct sockaddr_ipx
*)from
)->sipx_port
;
1469 memcpy(from2
->sipx_node
,
1470 ((struct sockaddr_ipx
*)from
)->sipx_node
, IPX_NODE_LEN
);
1475 _enable_event(s
, FD_READ
, 0, 0);
1476 return (INT16
)length
;
1478 SetLastError(wsaErrno());
1481 else SetLastError(WSAENOTSOCK
);
1482 WARN(" -> ERROR\n");
1484 if (from
&& ((struct sockaddr_ipx
*)from
)->sipx_family
== AF_IPX
) {
1485 from
= (struct sockaddr
*)
1486 malloc(fromlen32
? *fromlen32
: sizeof(*from2
));
1487 memcpy(from
, from2
, fromlen32
? *fromlen32
: sizeof(*from2
));
1488 from2
->sipx_family
= WS_AF_IPX
;
1489 from2
->sipx_network
= ((struct sockaddr_ipx
*)from
)->sipx_network
;
1490 from2
->sipx_port
= ((struct sockaddr_ipx
*)from
)->sipx_port
;
1491 memcpy(from2
->sipx_node
,
1492 ((struct sockaddr_ipx
*)from
)->sipx_node
, IPX_NODE_LEN
);
1496 return SOCKET_ERROR
;
1499 /***********************************************************************
1500 * recvfrom() (WINSOCK.17)
1502 INT16 WINAPI
WINSOCK_recvfrom16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
,
1503 struct sockaddr
*from
, INT16
*fromlen16
)
1506 INT
*p
= &fromlen32
;
1509 if( fromlen16
) fromlen32
= *fromlen16
; else p
= NULL
;
1510 retVal
= WSOCK32_recvfrom( s
, buf
, len
, flags
, from
, p
);
1511 if( fromlen16
) *fromlen16
= fromlen32
;
1512 return (INT16
)retVal
;
1515 /***********************************************************************
1516 * select() (WINSOCK.18)(WSOCK32.18)
1518 static INT
__ws_select( BOOL b32
, void *ws_readfds
, void *ws_writefds
, void *ws_exceptfds
,
1519 struct timeval
*timeout
)
1521 LPWSINFO pwsi
= WINSOCK_GetIData();
1523 TRACE("(%08x): read %8x, write %8x, excp %8x\n",
1524 (unsigned) pwsi
, (unsigned) ws_readfds
, (unsigned) ws_writefds
, (unsigned) ws_exceptfds
);
1529 fd_set readfds
, writefds
, exceptfds
;
1530 fd_set
*p_read
, *p_write
, *p_except
;
1531 int readfd
[FD_SETSIZE
], writefd
[FD_SETSIZE
], exceptfd
[FD_SETSIZE
];
1533 p_read
= fd_set_import(&readfds
, pwsi
, ws_readfds
, &highfd
, readfd
, b32
);
1534 p_write
= fd_set_import(&writefds
, pwsi
, ws_writefds
, &highfd
, writefd
, b32
);
1535 p_except
= fd_set_import(&exceptfds
, pwsi
, ws_exceptfds
, &highfd
, exceptfd
, b32
);
1537 if( (highfd
= select(highfd
+ 1, p_read
, p_write
, p_except
, timeout
)) > 0 )
1539 fd_set_export(pwsi
, &readfds
, p_except
, ws_readfds
, readfd
, b32
);
1540 fd_set_export(pwsi
, &writefds
, p_except
, ws_writefds
, writefd
, b32
);
1542 if (p_except
&& ws_exceptfds
)
1544 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1545 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1546 int i
, j
, count
= (b32
) ? wsfds32
->fd_count
: wsfds16
->fd_count
;
1548 for (i
= j
= 0; i
< count
; i
++)
1550 int fd
= exceptfd
[i
];
1551 if( fd
>= 0 && FD_ISSET(fd
, &exceptfds
) )
1554 wsfds32
->fd_array
[j
++] = wsfds32
->fd_array
[i
];
1556 wsfds16
->fd_array
[j
++] = wsfds16
->fd_array
[i
];
1558 if( fd
>= 0 ) close(fd
);
1562 wsfds32
->fd_count
= j
;
1564 wsfds16
->fd_count
= j
;
1570 fd_set_unimport(ws_readfds
, readfd
, b32
);
1571 fd_set_unimport(ws_writefds
, writefd
, b32
);
1572 fd_set_unimport(ws_exceptfds
, exceptfd
, b32
);
1573 if( ws_readfds
) ((ws_fd_set32
*)ws_readfds
)->fd_count
= 0;
1574 if( ws_writefds
) ((ws_fd_set32
*)ws_writefds
)->fd_count
= 0;
1575 if( ws_exceptfds
) ((ws_fd_set32
*)ws_exceptfds
)->fd_count
= 0;
1577 if( highfd
== 0 ) return 0;
1578 SetLastError(wsaErrno());
1580 return SOCKET_ERROR
;
1583 INT16 WINAPI
WINSOCK_select16(INT16 nfds
, ws_fd_set16
*ws_readfds
,
1584 ws_fd_set16
*ws_writefds
, ws_fd_set16
*ws_exceptfds
,
1585 struct timeval
*timeout
)
1587 return (INT16
)__ws_select( FALSE
, ws_readfds
, ws_writefds
, ws_exceptfds
, timeout
);
1590 INT WINAPI
WSOCK32_select(INT nfds
, ws_fd_set32
*ws_readfds
,
1591 ws_fd_set32
*ws_writefds
, ws_fd_set32
*ws_exceptfds
,
1592 struct timeval
*timeout
)
1594 /* struct timeval is the same for both 32- and 16-bit code */
1595 return (INT
)__ws_select( TRUE
, ws_readfds
, ws_writefds
, ws_exceptfds
, timeout
);
1599 /***********************************************************************
1600 * send() (WSOCK32.19)
1602 INT WINAPI
WSOCK32_send(SOCKET s
, char *buf
, INT len
, INT flags
)
1604 LPWSINFO pwsi
= WINSOCK_GetIData();
1606 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1607 (unsigned)pwsi
, s
, (unsigned) buf
, len
, flags
);
1608 if( _check_ws(pwsi
, s
) )
1610 int fd
= _get_sock_fd(s
);
1613 if (_is_blocking(s
))
1616 /* FIXME: exceptfds */
1619 if ((length
= send(fd
, buf
, len
, flags
)) < 0 )
1621 SetLastError(wsaErrno());
1622 if( GetLastError() == WSAEWOULDBLOCK
)
1623 _enable_event(s
, FD_WRITE
, 0, 0);
1628 return (INT16
)length
;
1632 else SetLastError(WSAENOTSOCK
);
1633 return SOCKET_ERROR
;
1636 /***********************************************************************
1637 * send() (WINSOCK.19)
1639 INT16 WINAPI
WINSOCK_send16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
)
1641 return WSOCK32_send( s
, buf
, len
, flags
);
1644 /***********************************************************************
1645 * sendto() (WSOCK32.20)
1647 INT WINAPI
WSOCK32_sendto(SOCKET s
, char *buf
, INT len
, INT flags
,
1648 struct sockaddr
*to
, INT tolen
)
1650 LPWSINFO pwsi
= WINSOCK_GetIData();
1652 struct ws_sockaddr_ipx
* to2
= (struct ws_sockaddr_ipx
*)to
;
1655 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1656 (unsigned)pwsi
, s
, (unsigned) buf
, len
, flags
);
1657 if( _check_ws(pwsi
, s
) )
1659 int fd
= _get_sock_fd(s
);
1662 if (to
&& ((struct ws_sockaddr_ipx
*)to
)->sipx_family
== WS_AF_PUP
)
1663 ((struct ws_sockaddr_ipx
*)to
)->sipx_family
= AF_UNSPEC
;
1666 ((struct ws_sockaddr_ipx
*)to
)->sipx_family
== WS_AF_IPX
)
1668 to
= (struct sockaddr
*) malloc(sizeof(struct sockaddr_ipx
));
1669 memset(to
, '\0', sizeof(struct sockaddr_ipx
));
1670 ((struct sockaddr_ipx
*)to
)->sipx_family
= AF_IPX
;
1671 ((struct sockaddr_ipx
*)to
)->sipx_port
= to2
->sipx_port
;
1672 ((struct sockaddr_ipx
*)to
)->sipx_network
= to2
->sipx_network
;
1673 memcpy(((struct sockaddr_ipx
*)to
)->sipx_node
,
1674 to2
->sipx_node
, IPX_NODE_LEN
);
1675 tolen
= sizeof(struct sockaddr_ipx
);
1678 if (_is_blocking(s
))
1681 /* FIXME: exceptfds */
1684 if ((length
= sendto(fd
, buf
, len
, flags
, to
, tolen
)) < 0 )
1686 SetLastError(wsaErrno());
1687 if( GetLastError() == WSAEWOULDBLOCK
)
1688 _enable_event(s
, FD_WRITE
, 0, 0);
1692 if (to
&& ((struct sockaddr_ipx
*)to
)->sipx_family
== AF_IPX
) {
1701 else SetLastError(WSAENOTSOCK
);
1703 if (to
&& ((struct sockaddr_ipx
*)to
)->sipx_family
== AF_IPX
) {
1707 return SOCKET_ERROR
;
1710 /***********************************************************************
1711 * sendto() (WINSOCK.20)
1713 INT16 WINAPI
WINSOCK_sendto16(SOCKET16 s
, char *buf
, INT16 len
, INT16 flags
,
1714 struct sockaddr
*to
, INT16 tolen
)
1716 return (INT16
)WSOCK32_sendto( s
, buf
, len
, flags
, to
, tolen
);
1719 /***********************************************************************
1720 * setsockopt() (WSOCK32.21)
1722 INT WINAPI
WSOCK32_setsockopt(SOCKET16 s
, INT level
, INT optname
,
1723 char *optval
, INT optlen
)
1725 LPWSINFO pwsi
= WINSOCK_GetIData();
1727 TRACE("(%08x): socket %04x, lev %d, opt %d, ptr %08x, len %d\n",
1728 (unsigned)pwsi
, s
, level
, optname
, (int) optval
, optlen
);
1729 if( _check_ws(pwsi
, s
) )
1731 struct linger linger
;
1732 int fd
= _get_sock_fd(s
);
1735 convert_sockopt(&level
, &optname
);
1736 if(optname
== WS_SO_DONTLINGER
) {
1737 linger
.l_onoff
= *((int*)optval
) ? 0: 1;
1738 linger
.l_linger
= 0;
1740 optval
= (char*)&linger
;
1741 optlen
= sizeof(struct linger
);
1743 if (optname
== SO_LINGER
&& optval
) {
1744 /* yes, uses unsigned short in both win16/win32 */
1745 linger
.l_onoff
= ((UINT16
*)optval
)[0];
1746 linger
.l_linger
= ((UINT16
*)optval
)[1];
1747 /* FIXME: what is documented behavior if SO_LINGER optval
1749 optval
= (char*)&linger
;
1750 optlen
= sizeof(struct linger
);
1751 } else if (optlen
< sizeof(int)){
1752 woptval
= *((INT16
*) optval
);
1753 optval
= (char*) &woptval
;
1757 if (setsockopt(fd
, level
, optname
, optval
, optlen
) == 0)
1762 SetLastError(wsaErrno());
1765 else SetLastError(WSAENOTSOCK
);
1766 return SOCKET_ERROR
;
1769 /***********************************************************************
1770 * setsockopt() (WINSOCK.21)
1772 INT16 WINAPI
WINSOCK_setsockopt16(SOCKET16 s
, INT16 level
, INT16 optname
,
1773 char *optval
, INT16 optlen
)
1775 if( !optval
) return SOCKET_ERROR
;
1776 return (INT16
)WSOCK32_setsockopt( s
, (UINT16
)level
, optname
, optval
, optlen
);
1780 /***********************************************************************
1781 * shutdown() (WSOCK32.22)
1783 INT WINAPI
WSOCK32_shutdown(SOCKET s
, INT how
)
1785 LPWSINFO pwsi
= WINSOCK_GetIData();
1787 TRACE("(%08x): socket %04x, how %i\n",
1788 (unsigned)pwsi
, s
, how
);
1789 if( _check_ws(pwsi
, s
) )
1791 int fd
= _get_sock_fd(s
);
1794 case 0: /* drop receives */
1795 _enable_event(s
, 0, 0, WS_FD_READ
);
1801 case 1: /* drop sends */
1802 _enable_event(s
, 0, 0, WS_FD_WRITE
);
1808 case 2: /* drop all */
1813 WSAAsyncSelect( s
, 0, 0, 0 );
1817 if (shutdown(fd
, how
) == 0)
1821 _enable_event(s
, 0, 0, WS_FD_CONNECTED
|WS_FD_LISTENING
);
1826 SetLastError(wsaErrno());
1829 else SetLastError(WSAENOTSOCK
);
1830 return SOCKET_ERROR
;
1833 /***********************************************************************
1834 * shutdown() (WINSOCK.22)
1836 INT16 WINAPI
WINSOCK_shutdown16(SOCKET16 s
, INT16 how
)
1838 return (INT16
)WSOCK32_shutdown( s
, how
);
1842 /***********************************************************************
1843 * socket() (WSOCK32.23)
1845 SOCKET WINAPI
WSOCK32_socket(INT af
, INT type
, INT protocol
)
1847 LPWSINFO pwsi
= WINSOCK_GetIData();
1848 struct create_socket_request
*req
= get_req_buffer();
1850 TRACE("(%08x): af=%d type=%d protocol=%d\n",
1851 (unsigned)pwsi
, af
, type
, protocol
);
1855 /* check the socket family */
1859 case WS_AF_IPX
: af
= AF_IPX
;
1862 case AF_UNSPEC
: break;
1863 default: SetLastError(WSAEAFNOSUPPORT
);
1864 return INVALID_SOCKET
;
1867 /* check the socket type */
1872 case SOCK_RAW
: break;
1873 default: SetLastError(WSAESOCKTNOSUPPORT
);
1874 return INVALID_SOCKET
;
1877 /* check the protocol type */
1878 if ( protocol
< 0 ) /* don't support negative values */
1879 { SetLastError(WSAEPROTONOSUPPORT
); return INVALID_SOCKET
; }
1881 if ( af
== AF_UNSPEC
) /* did they not specify the address family? */
1885 if (type
== SOCK_STREAM
) { af
= AF_INET
; break; }
1887 if (type
== SOCK_DGRAM
) { af
= AF_INET
; break; }
1888 default: SetLastError(WSAEPROTOTYPE
); return INVALID_SOCKET
;
1893 req
->protocol
= protocol
;
1894 req
->access
= GENERIC_READ
|GENERIC_WRITE
|SYNCHRONIZE
;
1895 req
->inherit
= TRUE
;
1896 sock_server_call( REQ_CREATE_SOCKET
);
1897 if ( req
->handle
>= 0)
1899 TRACE("\tcreated %04x\n", req
->handle
);
1904 if (GetLastError() == WSAEACCES
) /* raw socket denied */
1906 if (type
== SOCK_RAW
)
1907 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
1909 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
1910 SetLastError(WSAESOCKTNOSUPPORT
);
1914 WARN("\t\tfailed!\n");
1915 return INVALID_SOCKET
;
1918 /***********************************************************************
1919 * socket() (WINSOCK.23)
1921 SOCKET16 WINAPI
WINSOCK_socket16(INT16 af
, INT16 type
, INT16 protocol
)
1923 return (SOCKET16
)WSOCK32_socket( af
, type
, protocol
);
1927 /* ----------------------------------- DNS services
1929 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
1930 * Also, we have to use wsock32 stubs to convert structures and
1931 * error codes from Unix to WSA, hence there is no direct mapping in
1932 * the relay32/wsock32.spec.
1935 static char* NULL_STRING
= "NULL";
1937 /***********************************************************************
1938 * gethostbyaddr() (WINSOCK.51)(WSOCK32.51)
1940 static struct WIN_hostent
* __ws_gethostbyaddr(const char *addr
, int len
, int type
, int dup_flag
)
1942 LPWSINFO pwsi
= WINSOCK_GetIData();
1946 struct hostent
* host
;
1947 if( (host
= gethostbyaddr(addr
, len
, type
)) != NULL
)
1948 if( WS_dup_he(pwsi
, host
, dup_flag
) )
1949 return (struct WIN_hostent
*)(pwsi
->he
);
1951 SetLastError(WSAENOBUFS
);
1953 SetLastError((h_errno
< 0) ? wsaErrno() : wsaHerrno());
1958 SEGPTR WINAPI
WINSOCK_gethostbyaddr16(const char *addr
, INT16 len
, INT16 type
)
1960 struct WIN_hostent
* retval
;
1961 TRACE("ptr %08x, len %d, type %d\n",
1962 (unsigned) addr
, len
, type
);
1963 retval
= __ws_gethostbyaddr( addr
, len
, type
, WS_DUP_SEGPTR
);
1964 return retval
? SEGPTR_GET(retval
) : ((SEGPTR
)NULL
);
1967 struct WIN_hostent
* WINAPI
WSOCK32_gethostbyaddr(const char *addr
, INT len
,
1970 TRACE("ptr %08x, len %d, type %d\n",
1971 (unsigned) addr
, len
, type
);
1972 return __ws_gethostbyaddr(addr
, len
, type
, WS_DUP_LINEAR
);
1975 /***********************************************************************
1976 * gethostbyname() (WINSOCK.52)(WSOCK32.52)
1978 static struct WIN_hostent
* __ws_gethostbyname(const char *name
, int dup_flag
)
1980 LPWSINFO pwsi
= WINSOCK_GetIData();
1984 struct hostent
* host
;
1985 if( (host
= gethostbyname(name
)) != NULL
)
1986 if( WS_dup_he(pwsi
, host
, dup_flag
) )
1987 return (struct WIN_hostent
*)(pwsi
->he
);
1988 else SetLastError(WSAENOBUFS
);
1989 else SetLastError((h_errno
< 0) ? wsaErrno() : wsaHerrno());
1994 SEGPTR WINAPI
WINSOCK_gethostbyname16(const char *name
)
1996 struct WIN_hostent
* retval
;
1997 TRACE("%s\n", (name
)?name
:NULL_STRING
);
1998 retval
= __ws_gethostbyname( name
, WS_DUP_SEGPTR
);
1999 return (retval
)? SEGPTR_GET(retval
) : ((SEGPTR
)NULL
) ;
2002 struct WIN_hostent
* WINAPI
WSOCK32_gethostbyname(const char* name
)
2004 TRACE("%s\n", (name
)?name
:NULL_STRING
);
2005 return __ws_gethostbyname( name
, WS_DUP_LINEAR
);
2009 /***********************************************************************
2010 * getprotobyname() (WINSOCK.53)(WSOCK32.53)
2012 static struct WIN_protoent
* __ws_getprotobyname(const char *name
, int dup_flag
)
2014 LPWSINFO pwsi
= WINSOCK_GetIData();
2018 struct protoent
* proto
;
2019 if( (proto
= getprotobyname(name
)) != NULL
)
2020 if( WS_dup_pe(pwsi
, proto
, dup_flag
) )
2021 return (struct WIN_protoent
*)(pwsi
->pe
);
2022 else SetLastError(WSAENOBUFS
);
2024 MESSAGE("protocol %s not found; You might want to add "
2025 "this to /etc/protocols\n", debugstr_a(name
) );
2026 SetLastError(WSANO_DATA
);
2028 } else SetLastError(WSANOTINITIALISED
);
2032 SEGPTR WINAPI
WINSOCK_getprotobyname16(const char *name
)
2034 struct WIN_protoent
* retval
;
2035 TRACE("%s\n", (name
)?name
:NULL_STRING
);
2036 retval
= __ws_getprotobyname(name
, WS_DUP_SEGPTR
);
2037 return retval
? SEGPTR_GET(retval
) : ((SEGPTR
)NULL
);
2040 struct WIN_protoent
* WINAPI
WSOCK32_getprotobyname(const char* name
)
2042 TRACE("%s\n", (name
)?name
:NULL_STRING
);
2043 return __ws_getprotobyname(name
, WS_DUP_LINEAR
);
2047 /***********************************************************************
2048 * getprotobynumber() (WINSOCK.54)(WSOCK32.54)
2050 static struct WIN_protoent
* __ws_getprotobynumber(int number
, int dup_flag
)
2052 LPWSINFO pwsi
= WINSOCK_GetIData();
2056 struct protoent
* proto
;
2057 if( (proto
= getprotobynumber(number
)) != NULL
)
2058 if( WS_dup_pe(pwsi
, proto
, dup_flag
) )
2059 return (struct WIN_protoent
*)(pwsi
->pe
);
2060 else SetLastError(WSAENOBUFS
);
2062 MESSAGE("protocol number %d not found; You might want to add "
2063 "this to /etc/protocols\n", number
);
2064 SetLastError(WSANO_DATA
);
2066 } else SetLastError(WSANOTINITIALISED
);
2070 SEGPTR WINAPI
WINSOCK_getprotobynumber16(INT16 number
)
2072 struct WIN_protoent
* retval
;
2073 TRACE("%i\n", number
);
2074 retval
= __ws_getprotobynumber(number
, WS_DUP_SEGPTR
);
2075 return retval
? SEGPTR_GET(retval
) : ((SEGPTR
)NULL
);
2078 struct WIN_protoent
* WINAPI
WSOCK32_getprotobynumber(INT number
)
2080 TRACE("%i\n", number
);
2081 return __ws_getprotobynumber(number
, WS_DUP_LINEAR
);
2085 /***********************************************************************
2086 * getservbyname() (WINSOCK.55)(WSOCK32.55)
2088 struct WIN_servent
* __ws_getservbyname(const char *name
, const char *proto
, int dup_flag
)
2090 LPWSINFO pwsi
= WINSOCK_GetIData();
2094 struct servent
* serv
;
2095 int i
= wsi_strtolo( pwsi
, name
, proto
);
2098 serv
= getservbyname(pwsi
->buffer
,
2099 proto
? (pwsi
->buffer
+ i
) : NULL
);
2101 if( WS_dup_se(pwsi
, serv
, dup_flag
) )
2102 return (struct WIN_servent
*)(pwsi
->se
);
2103 else SetLastError(WSAENOBUFS
);
2105 MESSAGE("service %s protocol %s not found; You might want to add "
2106 "this to /etc/services\n", debugstr_a(pwsi
->buffer
),
2107 proto
? debugstr_a(pwsi
->buffer
+i
):"*");
2108 SetLastError(WSANO_DATA
);
2111 else SetLastError(WSAENOBUFS
);
2112 } else SetLastError(WSANOTINITIALISED
);
2116 SEGPTR WINAPI
WINSOCK_getservbyname16(const char *name
, const char *proto
)
2118 struct WIN_servent
* retval
;
2119 TRACE("'%s', '%s'\n",
2120 (name
)?name
:NULL_STRING
, (proto
)?proto
:NULL_STRING
);
2121 retval
= __ws_getservbyname(name
, proto
, WS_DUP_SEGPTR
);
2122 return retval
? SEGPTR_GET(retval
) : ((SEGPTR
)NULL
);
2125 struct WIN_servent
* WINAPI
WSOCK32_getservbyname(const char *name
, const char *proto
)
2127 TRACE("'%s', '%s'\n",
2128 (name
)?name
:NULL_STRING
, (proto
)?proto
:NULL_STRING
);
2129 return __ws_getservbyname(name
, proto
, WS_DUP_LINEAR
);
2133 /***********************************************************************
2134 * getservbyport() (WINSOCK.56)(WSOCK32.56)
2136 static struct WIN_servent
* __ws_getservbyport(int port
, const char* proto
, int dup_flag
)
2138 LPWSINFO pwsi
= WINSOCK_GetIData();
2142 struct servent
* serv
;
2143 if (!proto
|| wsi_strtolo( pwsi
, proto
, NULL
)) {
2144 if( (serv
= getservbyport(port
, (proto
) ? pwsi
->buffer
: NULL
)) != NULL
) {
2145 if( WS_dup_se(pwsi
, serv
, dup_flag
) )
2146 return (struct WIN_servent
*)(pwsi
->se
);
2147 else SetLastError(WSAENOBUFS
);
2150 MESSAGE("service on port %lu protocol %s not found; You might want to add "
2151 "this to /etc/services\n", (unsigned long)ntohl(port
),
2152 proto
? debugstr_a(pwsi
->buffer
) : "*");
2153 SetLastError(WSANO_DATA
);
2156 else SetLastError(WSAENOBUFS
);
2157 } else SetLastError(WSANOTINITIALISED
);
2161 SEGPTR WINAPI
WINSOCK_getservbyport16(INT16 port
, const char *proto
)
2163 struct WIN_servent
* retval
;
2165 (int)port
, (proto
)?proto
:NULL_STRING
);
2166 retval
= __ws_getservbyport(port
, proto
, WS_DUP_SEGPTR
);
2167 return retval
? SEGPTR_GET(retval
) : ((SEGPTR
)NULL
);
2170 struct WIN_servent
* WINAPI
WSOCK32_getservbyport(INT port
, const char *proto
)
2173 (int)port
, (proto
)?proto
:NULL_STRING
);
2174 return __ws_getservbyport(port
, proto
, WS_DUP_LINEAR
);
2178 /***********************************************************************
2179 * gethostname() (WSOCK32.57)
2181 INT WINAPI
WSOCK32_gethostname(char *name
, INT namelen
)
2183 LPWSINFO pwsi
= WINSOCK_GetIData();
2185 TRACE("(%08x): name %s, len %d\n",
2186 (unsigned)pwsi
, (name
)?name
:NULL_STRING
, namelen
);
2189 if (gethostname(name
, namelen
) == 0) return 0;
2190 SetLastError((errno
== EINVAL
) ? WSAEFAULT
: wsaErrno());
2192 return SOCKET_ERROR
;
2195 /***********************************************************************
2196 * gethostname() (WINSOCK.57)
2198 INT16 WINAPI
WINSOCK_gethostname16(char *name
, INT16 namelen
)
2200 return (INT16
)WSOCK32_gethostname(name
, namelen
);
2204 /* ------------------------------------- Windows sockets extensions -- *
2206 * ------------------------------------------------------------------- */
2208 /***********************************************************************
2209 * WSAEnumNetworkEvents
2211 int WINAPI
WSAEnumNetworkEvents(SOCKET s
, WSAEVENT hEvent
, LPWSANETWORKEVENTS lpEvent
)
2213 LPWSINFO pwsi
= WINSOCK_GetIData();
2214 struct get_socket_event_request
*req
= get_req_buffer();
2216 TRACE("(%08x): %08x, hEvent %08x, lpEvent %08x\n",
2217 (unsigned)pwsi
, s
, hEvent
, (unsigned)lpEvent
);
2218 if( _check_ws(pwsi
, s
) )
2221 req
->service
= TRUE
;
2223 req
->c_event
= hEvent
;
2224 sock_server_call( REQ_GET_SOCKET_EVENT
);
2225 lpEvent
->lNetworkEvents
= req
->pmask
;
2226 memcpy(lpEvent
->iErrorCode
, req
->errors
, sizeof(lpEvent
->iErrorCode
));
2229 else SetLastError(WSAEINVAL
);
2230 return SOCKET_ERROR
;
2233 /***********************************************************************
2236 int WINAPI
WSAEventSelect(SOCKET s
, WSAEVENT hEvent
, LONG lEvent
)
2238 LPWSINFO pwsi
= WINSOCK_GetIData();
2239 struct set_socket_event_request
*req
= get_req_buffer();
2241 TRACE("(%08x): %08x, hEvent %08x, event %08x\n",
2242 (unsigned)pwsi
, s
, hEvent
, (unsigned)lEvent
);
2243 if( _check_ws(pwsi
, s
) )
2247 req
->event
= hEvent
;
2248 sock_server_call( REQ_SET_SOCKET_EVENT
);
2251 else SetLastError(WSAEINVAL
);
2252 return SOCKET_ERROR
;
2255 /***********************************************************************
2256 * WSAAsyncSelect() (WINSOCK.101)(WSOCK32.101)
2259 VOID CALLBACK
WINSOCK_DoAsyncEvent( ULONG_PTR ptr
)
2261 ws_select_info
*info
= (ws_select_info
*)ptr
;
2262 LPWSINFO pwsi
= info
->pwsi
;
2263 struct get_socket_event_request
*req
= get_req_buffer();
2264 unsigned int i
, pmask
, orphan
= FALSE
;
2266 TRACE("socket %08x, event %08x\n", info
->sock
, info
->event
);
2268 req
->handle
= info
->sock
;
2269 req
->service
= TRUE
;
2270 req
->s_event
= info
->event
; /* <== avoid race conditions */
2271 req
->c_event
= info
->event
;
2272 sock_server_call( REQ_GET_SOCKET_EVENT
);
2273 if ( (GetLastError() == WSAENOTSOCK
) || (GetLastError() == WSAEINVAL
) )
2275 /* orphaned event (socket closed or something) */
2276 pmask
= WS_FD_SERVEVENT
;
2280 /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2281 if (pmask
& WS_FD_SERVEVENT
) {
2283 for (q
=0; q
<WS_ACCEPT_QUEUE
; q
++)
2284 if (pwsi
->accept_old
[q
] == info
->sock
) {
2285 /* there's only one service thread per pwsi, no lock necessary */
2286 HANDLE as
= pwsi
->accept_new
[q
];
2288 pwsi
->accept_new
[q
] = 0;
2289 pwsi
->accept_old
[q
] = 0;
2290 WSAAsyncSelect(as
, info
->hWnd
, info
->uMsg
, info
->lEvent
);
2293 pmask
&= ~WS_FD_SERVEVENT
;
2295 /* dispatch network events */
2296 for (i
=0; i
<FD_MAX_EVENTS
; i
++)
2297 if (pmask
& (1<<i
)) {
2298 TRACE("post: event bit %d, error %d\n", i
, req
->errors
[i
]);
2299 PostMessageA(info
->hWnd
, info
->uMsg
, info
->sock
,
2300 WSAMAKESELECTREPLY(1<<i
, req
->errors
[i
]));
2305 TRACE("orphaned event, self-destructing\n");
2306 /* SERVICE_Delete closes the event object */
2307 SERVICE_Delete( info
->service
);
2312 INT WINAPI
WSAAsyncSelect(SOCKET s
, HWND hWnd
, UINT uMsg
, LONG lEvent
)
2314 LPWSINFO pwsi
= WINSOCK_GetIData();
2316 TRACE("(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
2317 (unsigned)pwsi
, (SOCKET16
)s
, (HWND16
)hWnd
, uMsg
, (unsigned)lEvent
);
2318 if( _check_ws(pwsi
, s
) )
2322 ws_select_info
*info
= (ws_select_info
*)WS_ALLOC(sizeof(ws_select_info
));
2325 HANDLE hObj
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
2332 info
->lEvent
= lEvent
;
2334 info
->service
= SERVICE_AddObject( hObj
, WINSOCK_DoAsyncEvent
, (ULONG_PTR
)info
);
2336 err
= WSAEventSelect( s
, hObj
, lEvent
| WS_FD_SERVEVENT
);
2338 /* SERVICE_Delete closes the event object */
2339 SERVICE_Delete( info
->service
);
2344 return 0; /* success */
2346 else SetLastError(WSAENOBUFS
);
2350 WSAEventSelect(s
, 0, 0);
2354 else SetLastError(WSAEINVAL
);
2355 return SOCKET_ERROR
;
2358 INT16 WINAPI
WSAAsyncSelect16(SOCKET16 s
, HWND16 hWnd
, UINT16 wMsg
, LONG lEvent
)
2360 return (INT16
)WSAAsyncSelect( s
, hWnd
, wMsg
, lEvent
);
2363 /***********************************************************************
2364 * WSARecvEx() (WSOCK32.1107)
2366 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
2367 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
2368 * into the flags parameter when a partial packet is read. This only applies to
2369 * sockets using the datagram protocol. This method does not seem to be implemented
2370 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
2371 * flag when a fragmented packet arrives.
2373 INT WINAPI
WSARecvEx(SOCKET s
, char *buf
, INT len
, INT
*flags
) {
2374 FIXME("(WSARecvEx) partial packet return value not set \n");
2376 return WSOCK32_recv(s
, buf
, len
, *flags
);
2380 /***********************************************************************
2381 * WSARecvEx16() (WINSOCK.1107)
2383 * See description for WSARecvEx()
2385 INT16 WINAPI
WSARecvEx16(SOCKET16 s
, char *buf
, INT16 len
, INT16
*flags
) {
2386 FIXME("(WSARecvEx16) partial packet return value not set \n");
2388 return WINSOCK_recv16(s
, buf
, len
, *flags
);
2392 /***********************************************************************
2393 * WSACreateEvent() (WS2_32.???)
2396 WSAEVENT WINAPI
WSACreateEvent(void)
2398 /* Create a manual-reset event, with initial state: unsignealed */
2401 return CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
2404 /***********************************************************************
2405 * WSACloseEvent() (WS2_32.???)
2408 BOOL WINAPI
WSACloseEvent(WSAEVENT event
)
2410 TRACE ("event=0x%x\n", event
);
2412 return CloseHandle(event
);
2415 /***********************************************************************
2416 * WSASocketA() (WS2_32.???)
2419 SOCKET WINAPI
WSASocketA(int af
, int type
, int protocol
,
2420 LPWSAPROTOCOL_INFOA lpProtocolInfo
,
2421 GROUP g
, DWORD dwFlags
)
2424 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2425 g, dwFlags) are ignored.
2428 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
2429 af
, type
, protocol
, lpProtocolInfo
, g
, dwFlags
);
2431 return ( WSOCK32_socket (af
, type
, protocol
) );
2435 /***********************************************************************
2436 * __WSAFDIsSet() (WINSOCK.151)
2438 INT16 WINAPI
__WSAFDIsSet16(SOCKET16 s
, ws_fd_set16
*set
)
2440 int i
= set
->fd_count
;
2442 TRACE("(%d,%8lx(%i))\n", s
,(unsigned long)set
, i
);
2445 if (set
->fd_array
[i
] == s
) return 1;
2449 /***********************************************************************
2450 * __WSAFDIsSet() (WSOCK32.151)
2452 INT WINAPI
__WSAFDIsSet(SOCKET s
, ws_fd_set32
*set
)
2454 int i
= set
->fd_count
;
2456 TRACE("(%d,%8lx(%i))\n", s
,(unsigned long)set
, i
);
2459 if (set
->fd_array
[i
] == s
) return 1;
2463 /***********************************************************************
2464 * WSAIsBlocking() (WINSOCK.114)(WSOCK32.114)
2466 BOOL WINAPI
WSAIsBlocking(void)
2468 /* By default WinSock should set all its sockets to non-blocking mode
2469 * and poll in PeekMessage loop when processing "blocking" ones. This
2470 * function is supposed to tell if the program is in this loop. Our
2471 * blocking calls are truly blocking so we always return FALSE.
2473 * Note: It is allowed to call this function without prior WSAStartup().
2480 /***********************************************************************
2481 * WSACancelBlockingCall() (WINSOCK.113)(WSOCK32.113)
2483 INT WINAPI
WSACancelBlockingCall(void)
2485 LPWSINFO pwsi
= WINSOCK_GetIData();
2487 TRACE("(%08x)\n", (unsigned)pwsi
);
2489 if( pwsi
) return 0;
2490 return SOCKET_ERROR
;
2494 /***********************************************************************
2495 * WSASetBlockingHook16() (WINSOCK.109)
2497 FARPROC16 WINAPI
WSASetBlockingHook16(FARPROC16 lpBlockFunc
)
2500 LPWSINFO pwsi
= WINSOCK_GetIData();
2502 TRACE("(%08x): hook %08x\n",
2503 (unsigned)pwsi
, (unsigned) lpBlockFunc
);
2506 prev
= (FARPROC16
)pwsi
->blocking_hook
;
2507 pwsi
->blocking_hook
= (DWORD
)lpBlockFunc
;
2508 pwsi
->flags
&= ~WSI_BLOCKINGHOOK
;
2515 /***********************************************************************
2516 * WSASetBlockingHook()
2518 FARPROC WINAPI
WSASetBlockingHook(FARPROC lpBlockFunc
)
2521 LPWSINFO pwsi
= WINSOCK_GetIData();
2523 TRACE("(%08x): hook %08x\n",
2524 (unsigned)pwsi
, (unsigned) lpBlockFunc
);
2526 prev
= (FARPROC
)pwsi
->blocking_hook
;
2527 pwsi
->blocking_hook
= (DWORD
)lpBlockFunc
;
2528 pwsi
->flags
|= WSI_BLOCKINGHOOK
;
2535 /***********************************************************************
2536 * WSAUnhookBlockingHook16() (WINSOCK.110)
2538 INT16 WINAPI
WSAUnhookBlockingHook16(void)
2540 LPWSINFO pwsi
= WINSOCK_GetIData();
2542 TRACE("(%08x)\n", (unsigned)pwsi
);
2543 if( pwsi
) return (INT16
)(pwsi
->blocking_hook
= 0);
2544 return SOCKET_ERROR
;
2548 /***********************************************************************
2549 * WSAUnhookBlockingHook()
2551 INT WINAPI
WSAUnhookBlockingHook(void)
2553 LPWSINFO pwsi
= WINSOCK_GetIData();
2555 TRACE("(%08x)\n", (unsigned)pwsi
);
2558 pwsi
->blocking_hook
= 0;
2559 pwsi
->flags
&= ~WSI_BLOCKINGHOOK
;
2562 return SOCKET_ERROR
;
2566 /* ----------------------------------- end of API stuff */
2568 /* ----------------------------------- helper functions -
2570 * TODO: Merge WS_dup_..() stuff into one function that
2571 * would operate with a generic structure containing internal
2572 * pointers (via a template of some kind).
2575 static int list_size(char** l
, int item_size
)
2580 j
+= (item_size
) ? item_size
: strlen(l
[i
]) + 1;
2581 j
+= (i
+ 1) * sizeof(char*); }
2585 static int list_dup(char** l_src
, char* ref
, char* base
, int item_size
)
2587 /* base is either either equal to ref or 0 or SEGPTR */
2590 char** l_to
= (char**)ref
;
2593 for(j
=0;l_src
[j
];j
++) ;
2594 p
+= (j
+ 1) * sizeof(char*);
2596 { l_to
[i
] = base
+ (p
- ref
);
2597 k
= ( item_size
) ? item_size
: strlen(l_src
[i
]) + 1;
2598 memcpy(p
, l_src
[i
], k
); p
+= k
; }
2605 static int hostent_size(struct hostent
* p_he
)
2609 { size
= sizeof(struct hostent
);
2610 size
+= strlen(p_he
->h_name
) + 1;
2611 size
+= list_size(p_he
->h_aliases
, 0);
2612 size
+= list_size(p_he
->h_addr_list
, p_he
->h_length
); }
2616 int WS_dup_he(LPWSINFO pwsi
, struct hostent
* p_he
, int flag
)
2618 /* Convert hostent structure into ws_hostent so that the data fits
2619 * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or
2620 * relative to pwsi->buffer depending on "flag" value. Returns size
2621 * of the data copied (also in the pwsi->buflen).
2624 int size
= hostent_size(p_he
);
2628 struct ws_hostent
* p_to
;
2629 char* p_name
,*p_aliases
,*p_addr
,*p_base
,*p
;
2631 _check_buffer_he(pwsi
, size
);
2632 p_to
= (struct ws_hostent
*)pwsi
->he
;
2633 p
= (char*)pwsi
->he
;
2634 p_base
= (flag
& WS_DUP_OFFSET
) ? NULL
2635 : ((flag
& WS_DUP_SEGPTR
) ? (char*)SEGPTR_GET(p
) : p
);
2636 p
+= sizeof(struct ws_hostent
);
2638 strcpy(p
, p_he
->h_name
); p
+= strlen(p
) + 1;
2640 p
+= list_dup(p_he
->h_aliases
, p
, p_base
+ (p
- (char*)pwsi
->he
), 0);
2642 list_dup(p_he
->h_addr_list
, p
, p_base
+ (p
- (char*)pwsi
->he
), p_he
->h_length
);
2644 p_to
->h_addrtype
= (INT16
)p_he
->h_addrtype
;
2645 p_to
->h_length
= (INT16
)p_he
->h_length
;
2646 p_to
->h_name
= (SEGPTR
)(p_base
+ (p_name
- (char*)pwsi
->he
));
2647 p_to
->h_aliases
= (SEGPTR
)(p_base
+ (p_aliases
- (char*)pwsi
->he
));
2648 p_to
->h_addr_list
= (SEGPTR
)(p_base
+ (p_addr
- (char*)pwsi
->he
));
2650 size
+= (sizeof(struct ws_hostent
) - sizeof(struct hostent
));
2655 /* ----- protoent */
2657 static int protoent_size(struct protoent
* p_pe
)
2661 { size
= sizeof(struct protoent
);
2662 size
+= strlen(p_pe
->p_name
) + 1;
2663 size
+= list_size(p_pe
->p_aliases
, 0); }
2667 int WS_dup_pe(LPWSINFO pwsi
, struct protoent
* p_pe
, int flag
)
2669 int size
= protoent_size(p_pe
);
2672 struct ws_protoent
* p_to
;
2673 char* p_name
,*p_aliases
,*p_base
,*p
;
2675 _check_buffer_pe(pwsi
, size
);
2676 p_to
= (struct ws_protoent
*)pwsi
->pe
;
2677 p
= (char*)pwsi
->pe
;
2678 p_base
= (flag
& WS_DUP_OFFSET
) ? NULL
2679 : ((flag
& WS_DUP_SEGPTR
) ? (char*)SEGPTR_GET(p
) : p
);
2680 p
+= sizeof(struct ws_protoent
);
2682 strcpy(p
, p_pe
->p_name
); p
+= strlen(p
) + 1;
2684 list_dup(p_pe
->p_aliases
, p
, p_base
+ (p
- (char*)pwsi
->pe
), 0);
2686 p_to
->p_proto
= (INT16
)p_pe
->p_proto
;
2687 p_to
->p_name
= (SEGPTR
)(p_base
) + (p_name
- (char*)pwsi
->pe
);
2688 p_to
->p_aliases
= (SEGPTR
)((p_base
) + (p_aliases
- (char*)pwsi
->pe
));
2690 size
+= (sizeof(struct ws_protoent
) - sizeof(struct protoent
));
2697 static int servent_size(struct servent
* p_se
)
2701 { size
+= sizeof(struct servent
);
2702 size
+= strlen(p_se
->s_proto
) + strlen(p_se
->s_name
) + 2;
2703 size
+= list_size(p_se
->s_aliases
, 0); }
2707 int WS_dup_se(LPWSINFO pwsi
, struct servent
* p_se
, int flag
)
2709 int size
= servent_size(p_se
);
2712 struct ws_servent
* p_to
;
2713 char* p_name
,*p_aliases
,*p_proto
,*p_base
,*p
;
2715 _check_buffer_se(pwsi
, size
);
2716 p_to
= (struct ws_servent
*)pwsi
->se
;
2717 p
= (char*)pwsi
->se
;
2718 p_base
= (flag
& WS_DUP_OFFSET
) ? NULL
2719 : ((flag
& WS_DUP_SEGPTR
) ? (char*)SEGPTR_GET(p
) : p
);
2720 p
+= sizeof(struct ws_servent
);
2722 strcpy(p
, p_se
->s_name
); p
+= strlen(p
) + 1;
2724 strcpy(p
, p_se
->s_proto
); p
+= strlen(p
) + 1;
2726 list_dup(p_se
->s_aliases
, p
, p_base
+ (p
- (char*)pwsi
->se
), 0);
2728 p_to
->s_port
= (INT16
)p_se
->s_port
;
2729 p_to
->s_name
= (SEGPTR
)(p_base
+ (p_name
- (char*)pwsi
->se
));
2730 p_to
->s_proto
= (SEGPTR
)(p_base
+ (p_proto
- (char*)pwsi
->se
));
2731 p_to
->s_aliases
= (SEGPTR
)(p_base
+ (p_aliases
- (char*)pwsi
->se
));
2733 size
+= (sizeof(struct ws_servent
) - sizeof(struct servent
));
2738 /* ----------------------------------- error handling */
2740 UINT16
wsaErrno(void)
2742 int loc_errno
= errno
;
2743 #ifdef HAVE_STRERROR
2744 WARN("errno %d, (%s).\n", loc_errno
, strerror(loc_errno
));
2746 WARN("errno %d\n", loc_errno
);
2751 case EINTR
: return WSAEINTR
;
2752 case EBADF
: return WSAEBADF
;
2754 case EACCES
: return WSAEACCES
;
2755 case EFAULT
: return WSAEFAULT
;
2756 case EINVAL
: return WSAEINVAL
;
2757 case EMFILE
: return WSAEMFILE
;
2758 case EWOULDBLOCK
: return WSAEWOULDBLOCK
;
2759 case EINPROGRESS
: return WSAEINPROGRESS
;
2760 case EALREADY
: return WSAEALREADY
;
2761 case ENOTSOCK
: return WSAENOTSOCK
;
2762 case EDESTADDRREQ
: return WSAEDESTADDRREQ
;
2763 case EMSGSIZE
: return WSAEMSGSIZE
;
2764 case EPROTOTYPE
: return WSAEPROTOTYPE
;
2765 case ENOPROTOOPT
: return WSAENOPROTOOPT
;
2766 case EPROTONOSUPPORT
: return WSAEPROTONOSUPPORT
;
2767 case ESOCKTNOSUPPORT
: return WSAESOCKTNOSUPPORT
;
2768 case EOPNOTSUPP
: return WSAEOPNOTSUPP
;
2769 case EPFNOSUPPORT
: return WSAEPFNOSUPPORT
;
2770 case EAFNOSUPPORT
: return WSAEAFNOSUPPORT
;
2771 case EADDRINUSE
: return WSAEADDRINUSE
;
2772 case EADDRNOTAVAIL
: return WSAEADDRNOTAVAIL
;
2773 case ENETDOWN
: return WSAENETDOWN
;
2774 case ENETUNREACH
: return WSAENETUNREACH
;
2775 case ENETRESET
: return WSAENETRESET
;
2776 case ECONNABORTED
: return WSAECONNABORTED
;
2778 case ECONNRESET
: return WSAECONNRESET
;
2779 case ENOBUFS
: return WSAENOBUFS
;
2780 case EISCONN
: return WSAEISCONN
;
2781 case ENOTCONN
: return WSAENOTCONN
;
2782 case ESHUTDOWN
: return WSAESHUTDOWN
;
2783 case ETOOMANYREFS
: return WSAETOOMANYREFS
;
2784 case ETIMEDOUT
: return WSAETIMEDOUT
;
2785 case ECONNREFUSED
: return WSAECONNREFUSED
;
2786 case ELOOP
: return WSAELOOP
;
2787 case ENAMETOOLONG
: return WSAENAMETOOLONG
;
2788 case EHOSTDOWN
: return WSAEHOSTDOWN
;
2789 case EHOSTUNREACH
: return WSAEHOSTUNREACH
;
2790 case ENOTEMPTY
: return WSAENOTEMPTY
;
2792 case EPROCLIM
: return WSAEPROCLIM
;
2795 case EUSERS
: return WSAEUSERS
;
2798 case EDQUOT
: return WSAEDQUOT
;
2801 case ESTALE
: return WSAESTALE
;
2804 case EREMOTE
: return WSAEREMOTE
;
2807 /* just in case we ever get here and there are no problems */
2810 WARN("Unknown errno %d!\n", loc_errno
);
2811 return WSAEOPNOTSUPP
;
2815 UINT16
wsaHerrno(void)
2817 int loc_errno
= h_errno
;
2819 WARN("h_errno %d.\n", loc_errno
);
2823 case HOST_NOT_FOUND
: return WSAHOST_NOT_FOUND
;
2824 case TRY_AGAIN
: return WSATRY_AGAIN
;
2825 case NO_RECOVERY
: return WSANO_RECOVERY
;
2826 case NO_DATA
: return WSANO_DATA
;
2830 WARN("Unknown h_errno %d!\n", loc_errno
);
2831 return WSAEOPNOTSUPP
;