When checking the socket return by the server request, we should do a
[wine/multimedia.git] / dlls / winsock / socket.c
blob102a4ba2379b3eed25e1922de26752575e9ca944
1 /*
2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
4 *
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).
11 * NOTE 2: Many winsock structs such as servent, hostent, protoent, ...
12 * are used with 1-byte alignment for Win16 programs and 4-byte alignment
13 * for Win32 programs in winsock.h. winsock2.h uses forced 4-byte alignment.
14 * So we have non-forced (just as MSDN) ws_XXXXent (winsock.h), 4-byte forced
15 * ws_XXXXent32 (winsock2.h) and 1-byte forced ws_XXXXent16 (winsock16.h).
18 #include "config.h"
20 #include <string.h>
21 #include <sys/types.h>
22 #ifdef HAVE_SYS_IPC_H
23 # include <sys/ipc.h>
24 #endif
25 #include <sys/ioctl.h>
26 #ifdef HAVE_SYS_FILIO_H
27 # include <sys/filio.h>
28 #endif
29 #ifdef HAVE_SYS_SOCKIO_H
30 # include <sys/sockio.h>
31 #endif
33 #if defined(__EMX__)
34 # include <sys/so_ioctl.h>
35 #endif
37 #ifdef HAVE_SYS_PARAM_H
38 # include <sys/param.h>
39 #endif
41 #ifdef HAVE_SYS_MSG_H
42 # include <sys/msg.h>
43 #endif
44 #ifdef HAVE_SYS_WAIT_H
45 # include <sys/wait.h>
46 #endif
47 #ifdef HAVE_SYS_SOCKET_H
48 #include <sys/socket.h>
49 #endif
50 #ifdef HAVE_NETINET_IN_H
51 # include <netinet/in.h>
52 #endif
53 #ifdef HAVE_NETINET_TCP_H
54 # include <netinet/tcp.h>
55 #endif
56 #ifdef HAVE_ARPA_INET_H
57 # include <arpa/inet.h>
58 #endif
59 #include <ctype.h>
60 #include <fcntl.h>
61 #include <errno.h>
62 #ifdef HAVE_SYS_ERRNO_H
63 #include <sys/errno.h>
64 #endif
65 #include <netdb.h>
66 #include <unistd.h>
67 #include <stdlib.h>
68 #ifdef HAVE_ARPA_NAMESER_H
69 # include <arpa/nameser.h>
70 #endif
71 #ifdef HAVE_RESOLV_H
72 # include <resolv.h>
73 #endif
74 #ifdef HAVE_NET_IF_H
75 # include <net/if.h>
76 #endif
78 #include "wine/winbase16.h"
79 #include "wingdi.h"
80 #include "winuser.h"
81 #include "winsock2.h"
82 #include "wine/winsock16.h"
83 #include "winnt.h"
84 #include "heap.h"
85 #include "task.h"
86 #include "wine/port.h"
87 #include "services.h"
88 #include "server.h"
89 #include "file.h"
90 #include "debugtools.h"
93 DEFAULT_DEBUG_CHANNEL(winsock);
95 #define DEBUG_SOCKADDR 0
96 #define dump_sockaddr(a) \
97 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
98 ((struct sockaddr_in *)a)->sin_family, \
99 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
100 ntohs(((struct sockaddr_in *)a)->sin_port))
102 /* ----------------------------------- internal data */
104 /* ws_... struct conversion flags */
106 #define WS_DUP_LINEAR 0x0001
107 #define WS_DUP_NATIVE 0x0000 /* not used anymore */
108 #define WS_DUP_OFFSET 0x0002 /* internal pointers are offsets */
109 #define WS_DUP_SEGPTR 0x0004 /* internal pointers are SEGPTRs */
110 /* by default, internal pointers are linear */
111 typedef struct /* WSAAsyncSelect() control struct */
113 HANDLE service, event, sock;
114 HWND hWnd;
115 UINT uMsg;
116 LONG lEvent;
117 struct _WSINFO *pwsi;
118 } ws_select_info;
120 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
121 #define WS_MAX_UDP_DATAGRAM 1024
123 #define WS_ACCEPT_QUEUE 6
125 #define WSI_BLOCKINGCALL 0x00000001 /* per-thread info flags */
126 #define WSI_BLOCKINGHOOK 0x00000002 /* 32-bit callback */
128 #define PROCFS_NETDEV_FILE "/proc/net/dev" /* Points to the file in the /proc fs
129 that lists the network devices.
130 Do we need an #ifdef LINUX for this? */
132 typedef struct _WSINFO
134 DWORD dwThisProcess;
135 struct _WSINFO *lpNextIData;
137 unsigned flags;
138 INT16 num_startup; /* reference counter */
139 INT16 num_async_rq;
140 INT16 last_free; /* entry in the socket table */
141 UINT16 buflen;
142 char* buffer; /* allocated from SEGPTR heap */
143 void *he; /* typecast for Win16/32 ws_hostent */
144 int helen;
145 void *se; /* typecast for Win16/32 ws_servent */
146 int selen;
147 void *pe; /* typecast for Win16/32 ws_protoent */
148 int pelen;
149 char* dbuffer; /* buffer for dummies (32 bytes) */
151 DWORD blocking_hook;
153 volatile HANDLE accept_old[WS_ACCEPT_QUEUE], accept_new[WS_ACCEPT_QUEUE];
154 } WSINFO, *LPWSINFO;
156 /* function prototypes */
157 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag);
158 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag);
159 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag);
161 typedef void WIN_hostent;
162 typedef void WIN_protoent;
163 typedef void WIN_servent;
165 int WSAIOCTL_GetInterfaceCount(void);
166 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
168 UINT16 wsaErrno(void);
169 UINT16 wsaHerrno(void);
171 static HANDLE _WSHeap = 0;
173 #define WS_ALLOC(size) \
174 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
175 #define WS_FREE(ptr) \
176 HeapFree(_WSHeap, 0, (ptr) )
178 static INT _ws_sock_ops[] =
179 { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
180 WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
181 WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER,
182 #ifdef SO_RCVTIMEO
183 WS_SO_RCVTIMEO,
184 #endif
185 0 };
186 static int _px_sock_ops[] =
187 { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
188 SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
189 WS_SO_DONTLINGER, /* no unix equivalent */
190 #ifdef SO_RCVTIMEO
191 SO_RCVTIMEO,
192 #endif
195 static INT _ws_tcp_ops[] = {
196 #ifdef TCP_NODELAY
197 WS_TCP_NODELAY,
198 #endif
201 static int _px_tcp_ops[] = {
202 #ifdef TCP_NODELAY
203 TCP_NODELAY,
204 #endif
208 /* we need a special routine to handle WSA* errors */
209 static inline int sock_server_call( enum request req )
211 unsigned int res = server_call_noerr( req );
212 if (res)
214 /* do not map WSA errors */
215 if ((res < WSABASEERR) || (res >= 0x10000000)) res = RtlNtStatusToDosError(res);
216 SetLastError( res );
218 return res;
221 static int _check_ws(LPWSINFO pwsi, SOCKET s);
222 static char* _check_buffer(LPWSINFO pwsi, int size);
224 static int _get_sock_fd(SOCKET s)
226 int fd = FILE_GetUnixHandle( s, GENERIC_READ );
227 if (fd == -1)
228 FIXME("handle %d is not a socket (GLE %ld)\n",s,GetLastError());
229 return fd;
232 static void _enable_event(SOCKET s, unsigned int event,
233 unsigned int sstate, unsigned int cstate)
235 SERVER_START_REQ
237 struct enable_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
239 req->handle = s;
240 req->mask = event;
241 req->sstate = sstate;
242 req->cstate = cstate;
243 sock_server_call( REQ_ENABLE_SOCKET_EVENT );
245 SERVER_END_REQ;
248 static int _is_blocking(SOCKET s)
250 int ret;
251 SERVER_START_REQ
253 struct get_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
255 req->handle = s;
256 req->service = FALSE;
257 req->s_event = 0;
258 req->c_event = 0;
259 sock_server_call( REQ_GET_SOCKET_EVENT );
260 ret = (req->state & WS_FD_NONBLOCKING) == 0;
262 SERVER_END_REQ;
263 return ret;
266 static unsigned int _get_sock_mask(SOCKET s)
268 unsigned int ret;
269 SERVER_START_REQ
271 struct get_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
273 req->handle = s;
274 req->service = FALSE;
275 req->s_event = 0;
276 req->c_event = 0;
277 sock_server_call( REQ_GET_SOCKET_EVENT );
278 ret = req->mask;
280 SERVER_END_REQ;
281 return ret;
284 static void _sync_sock_state(SOCKET s)
286 /* do a dummy wineserver request in order to let
287 the wineserver run through its select loop once */
288 (void)_is_blocking(s);
291 static int _get_sock_error(SOCKET s, unsigned int bit)
293 int ret;
294 SERVER_START_REQ
296 struct get_socket_event_request *req = server_alloc_req( sizeof(*req),
297 FD_MAX_EVENTS*sizeof(int) );
298 req->handle = s;
299 req->service = FALSE;
300 req->s_event = 0;
301 req->c_event = 0;
302 sock_server_call( REQ_GET_SOCKET_EVENT );
303 ret = *((int *)server_data_ptr(req) + bit);
305 SERVER_END_REQ;
306 return ret;
309 static LPWSINFO lpFirstIData = NULL;
311 static LPWSINFO WINSOCK_GetIData(void)
313 DWORD pid = GetCurrentProcessId();
314 LPWSINFO iData;
316 for (iData = lpFirstIData; iData; iData = iData->lpNextIData) {
317 if (iData->dwThisProcess == pid)
318 break;
320 return iData;
323 static BOOL WINSOCK_CreateIData(void)
325 LPWSINFO iData;
327 iData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WSINFO));
328 if (!iData)
329 return FALSE;
330 iData->dwThisProcess = GetCurrentProcessId();
331 iData->lpNextIData = lpFirstIData;
332 lpFirstIData = iData;
333 return TRUE;
336 static void WINSOCK_DeleteIData(void)
338 LPWSINFO iData = WINSOCK_GetIData();
339 LPWSINFO* ppid;
340 if (iData) {
341 for (ppid = &lpFirstIData; *ppid; ppid = &(*ppid)->lpNextIData) {
342 if (*ppid == iData) {
343 *ppid = iData->lpNextIData;
344 break;
348 if( iData->flags & WSI_BLOCKINGCALL )
349 TRACE("\tinside blocking call!\n");
351 /* delete scratch buffers */
353 if( iData->buffer ) SEGPTR_FREE(iData->buffer);
354 if( iData->dbuffer ) SEGPTR_FREE(iData->dbuffer);
356 HeapFree(GetProcessHeap(), 0, iData);
360 /***********************************************************************
361 * WSOCK32_LibMain (WSOCK32.init)
363 BOOL WINAPI WSOCK32_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
365 TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
366 switch (fdwReason) {
367 case DLL_PROCESS_DETACH:
368 WINSOCK_DeleteIData();
369 break;
371 return TRUE;
374 /***********************************************************************
375 * WINSOCK_LibMain (WINSOCK.init)
377 BOOL WINAPI WINSOCK_LibMain(DWORD fdwReason, HINSTANCE hInstDLL, WORD ds,
378 WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
380 TRACE("0x%x 0x%lx\n", hInstDLL, fdwReason);
381 switch (fdwReason) {
382 case DLL_PROCESS_DETACH:
383 WINSOCK_DeleteIData();
384 break;
386 return TRUE;
389 /***********************************************************************
390 * convert_sockopt()
392 * Converts socket flags from Windows format.
394 static void convert_sockopt(INT *level, INT *optname)
396 int i;
397 switch (*level)
399 case WS_SOL_SOCKET:
400 *level = SOL_SOCKET;
401 for(i=0; _ws_sock_ops[i]; i++)
402 if( _ws_sock_ops[i] == *optname ) break;
403 if( _ws_sock_ops[i] ) *optname = _px_sock_ops[i];
404 else FIXME("Unknown SOL_SOCKET optname %d\n", *optname);
405 break;
406 case WS_IPPROTO_TCP:
407 *level = IPPROTO_TCP;
408 for(i=0; _ws_tcp_ops[i]; i++)
409 if ( _ws_tcp_ops[i] == *optname ) break;
410 if( _ws_tcp_ops[i] ) *optname = _px_tcp_ops[i];
411 else FIXME("Unknown IPPROTO_TCP optname %d\n", *optname);
412 break;
416 /* ----------------------------------- Per-thread info (or per-process?) */
418 static int wsi_strtolo(LPWSINFO pwsi, const char* name, const char* opt)
420 /* Stuff a lowercase copy of the string into the local buffer */
422 int i = strlen(name) + 2;
423 char* p = _check_buffer(pwsi, i + ((opt)?strlen(opt):0));
425 if( p )
427 do *p++ = tolower(*name); while(*name++);
428 i = (p - (char*)(pwsi->buffer));
429 if( opt ) do *p++ = tolower(*opt); while(*opt++);
430 return i;
432 return 0;
435 static fd_set* fd_set_import( fd_set* fds, LPWSINFO pwsi, void* wsfds, int* highfd, int lfd[], BOOL b32 )
437 /* translate Winsock fd set into local fd set */
439 if( wsfds )
441 #define wsfds16 ((ws_fd_set16*)wsfds)
442 #define wsfds32 ((ws_fd_set32*)wsfds)
443 int i, count;
445 FD_ZERO(fds);
446 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
448 for( i = 0; i < count; i++ )
450 int s = (b32) ? wsfds32->fd_array[i]
451 : wsfds16->fd_array[i];
452 if( _check_ws(pwsi, s) )
454 int fd = _get_sock_fd(s);
455 lfd[ i ] = fd;
456 if( fd > *highfd ) *highfd = fd;
457 FD_SET(fd, fds);
459 else lfd[ i ] = -1;
461 #undef wsfds32
462 #undef wsfds16
463 return fds;
465 return NULL;
468 inline static int sock_error_p(int s)
470 unsigned int optval, optlen;
472 optlen = sizeof(optval);
473 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
474 if (optval) WARN("\t[%i] error: %d\n", s, optval);
475 return optval != 0;
478 static int fd_set_export( LPWSINFO pwsi, fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
480 int num_err = 0;
482 /* translate local fd set into Winsock fd set, adding
483 * errors to exceptfds (only if app requested it) */
485 if( wsfds )
487 #define wsfds16 ((ws_fd_set16*)wsfds)
488 #define wsfds32 ((ws_fd_set32*)wsfds)
489 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
491 for( i = 0, j = 0; i < count; i++ )
493 if( lfd[i] >= 0 )
495 int fd = lfd[i];
496 if( FD_ISSET(fd, fds) )
498 if ( exceptfds && sock_error_p(fd) )
500 FD_SET(fd, exceptfds);
501 num_err++;
503 else if( b32 )
504 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
505 else
506 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
508 close(fd);
509 lfd[i] = -1;
513 if( b32 ) wsfds32->fd_count = j;
514 else wsfds16->fd_count = j;
516 TRACE("\n");
517 #undef wsfds32
518 #undef wsfds16
520 return num_err;
523 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
525 if ( wsfds )
527 #define wsfds16 ((ws_fd_set16*)wsfds)
528 #define wsfds32 ((ws_fd_set32*)wsfds)
529 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
531 for( i = 0; i < count; i++ )
532 if ( lfd[i] >= 0 )
533 close(lfd[i]);
535 TRACE("\n");
536 #undef wsfds32
537 #undef wsfds16
541 static int do_block( int fd, int mask )
543 fd_set fds[3];
544 int i, r;
546 FD_ZERO(&fds[0]);
547 FD_ZERO(&fds[1]);
548 FD_ZERO(&fds[2]);
549 for (i=0; i<3; i++)
550 if (mask & (1<<i))
551 FD_SET(fd, &fds[i]);
552 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
553 if (i <= 0) return -1;
554 r = 0;
555 for (i=0; i<3; i++)
556 if (FD_ISSET(fd, &fds[i]))
557 r |= 1<<i;
558 return r;
561 void* __ws_memalloc( int size )
563 return WS_ALLOC(size);
566 void __ws_memfree(void* ptr)
568 WS_FREE(ptr);
572 /* ----------------------------------- API -----
574 * Init / cleanup / error checking.
577 /***********************************************************************
578 * WSAStartup16() (WINSOCK.115)
580 * Create socket control struct, attach it to the global list and
581 * update a pointer in the task struct.
583 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA lpWSAData)
585 WSADATA WINSOCK_data = { 0x0101, 0x0101,
586 "WINE Sockets 1.1",
587 #ifdef linux
588 "Linux/i386",
589 #elif defined(__NetBSD__)
590 "NetBSD/i386",
591 #elif defined(sunos)
592 "SunOS",
593 #elif defined(__FreeBSD__)
594 "FreeBSD",
595 #elif defined(__OpenBSD__)
596 "OpenBSD/i386",
597 #else
598 "Unknown",
599 #endif
600 WS_MAX_SOCKETS_PER_PROCESS,
601 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
602 LPWSINFO pwsi;
604 TRACE("verReq=%x\n", wVersionRequested);
606 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
607 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
609 if (!lpWSAData) return WSAEINVAL;
611 /* initialize socket heap */
613 if( !_WSHeap )
615 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
616 if( !_WSHeap )
618 ERR("Fatal: failed to create WinSock heap\n");
619 return 0;
622 if( _WSHeap == 0 ) return WSASYSNOTREADY;
624 pwsi = WINSOCK_GetIData();
625 if( pwsi == NULL )
627 WINSOCK_CreateIData();
628 pwsi = WINSOCK_GetIData();
629 if (!pwsi) return WSASYSNOTREADY;
631 pwsi->num_startup++;
633 /* return winsock information */
635 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
637 TRACE("succeeded\n");
638 return 0;
641 /***********************************************************************
642 * WSAStartup() (WS2_32.115)
644 INT WINAPI WSAStartup(UINT wVersionRequested, LPWSADATA lpWSAData)
646 WSADATA WINSOCK_data = { 0x0202, 0x0202,
647 "WINE Sockets 2.0",
648 #ifdef linux
649 "Linux/i386",
650 #elif defined(__NetBSD__)
651 "NetBSD/i386",
652 #elif defined(sunos)
653 "SunOS",
654 #elif defined(__FreeBSD__)
655 "FreeBSD",
656 #elif defined(__OpenBSD__)
657 "OpenBSD/i386",
658 #else
659 "Unknown",
660 #endif
661 WS_MAX_SOCKETS_PER_PROCESS,
662 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
663 LPWSINFO pwsi;
665 TRACE("verReq=%x\n", wVersionRequested);
667 if (LOBYTE(wVersionRequested) < 1)
668 return WSAVERNOTSUPPORTED;
670 if (!lpWSAData) return WSAEINVAL;
672 /* initialize socket heap */
674 if( !_WSHeap )
676 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
677 if( !_WSHeap )
679 ERR("Fatal: failed to create WinSock heap\n");
680 return 0;
683 if( _WSHeap == 0 ) return WSASYSNOTREADY;
685 pwsi = WINSOCK_GetIData();
686 if( pwsi == NULL )
688 WINSOCK_CreateIData();
689 pwsi = WINSOCK_GetIData();
690 if (!pwsi) return WSASYSNOTREADY;
692 pwsi->num_startup++;
694 /* return winsock information */
695 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
697 /* that's the whole of the negotiation for now */
698 lpWSAData->wVersion = wVersionRequested;
700 TRACE("succeeded\n");
701 return 0;
705 /***********************************************************************
706 * WSACleanup() (WINSOCK.116)
708 INT WINAPI WSACleanup(void)
710 LPWSINFO pwsi = WINSOCK_GetIData();
711 if( pwsi ) {
712 if( --pwsi->num_startup > 0 ) return 0;
714 WINSOCK_DeleteIData();
715 return 0;
717 SetLastError(WSANOTINITIALISED);
718 return SOCKET_ERROR;
722 /***********************************************************************
723 * WSAGetLastError() (WSOCK32.111)(WINSOCK.111)
725 INT WINAPI WSAGetLastError(void)
727 return GetLastError();
730 /***********************************************************************
731 * WSASetLastError() (WSOCK32.112)
733 void WINAPI WSASetLastError(INT iError) {
734 SetLastError(iError);
737 /***********************************************************************
738 * WSASetLastError16() (WINSOCK.112)
740 void WINAPI WSASetLastError16(INT16 iError)
742 WSASetLastError(iError);
745 int _check_ws(LPWSINFO pwsi, SOCKET s)
747 if( pwsi )
749 int fd;
750 if( pwsi->flags & WSI_BLOCKINGCALL ) SetLastError(WSAEINPROGRESS);
751 if ( (fd = _get_sock_fd(s)) < 0 ) {
752 SetLastError(WSAENOTSOCK);
753 return 0;
755 /* FIXME: maybe check whether fd is really a socket? */
756 close( fd );
757 return 1;
759 return 0;
762 char* _check_buffer(LPWSINFO pwsi, int size)
764 if( pwsi->buffer && pwsi->buflen >= size ) return pwsi->buffer;
765 else SEGPTR_FREE(pwsi->buffer);
767 pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size));
768 return pwsi->buffer;
771 struct ws_hostent* _check_buffer_he(LPWSINFO pwsi, int size)
773 if( pwsi->he && pwsi->helen >= size ) return pwsi->he;
774 else SEGPTR_FREE(pwsi->he);
776 pwsi->he = SEGPTR_ALLOC((pwsi->helen = size));
777 return pwsi->he;
780 void* _check_buffer_se(LPWSINFO pwsi, int size)
782 if( pwsi->se && pwsi->selen >= size ) return pwsi->se;
783 else SEGPTR_FREE(pwsi->se);
785 pwsi->se = SEGPTR_ALLOC((pwsi->selen = size));
786 return pwsi->se;
789 struct ws_protoent* _check_buffer_pe(LPWSINFO pwsi, int size)
791 if( pwsi->pe && pwsi->pelen >= size ) return pwsi->pe;
792 else SEGPTR_FREE(pwsi->pe);
794 pwsi->pe = SEGPTR_ALLOC((pwsi->pelen = size));
795 return pwsi->pe;
798 /* ----------------------------------- i/o APIs */
800 /***********************************************************************
801 * accept() (WSOCK32.1)
803 static void WSOCK32_async_accept(LPWSINFO pwsi, SOCKET s, SOCKET as)
805 int q;
806 /* queue socket for WSAAsyncSelect */
807 for (q=0; q<WS_ACCEPT_QUEUE; q++)
808 if (InterlockedCompareExchange((PVOID*)&pwsi->accept_old[q], (PVOID)s, (PVOID)0) == (PVOID)0)
809 break;
810 if (q<WS_ACCEPT_QUEUE)
811 pwsi->accept_new[q] = as;
812 else
813 ERR("accept queue too small\n");
814 /* now signal our AsyncSelect handler */
815 _enable_event(s, WS_FD_SERVEVENT, 0, 0);
818 SOCKET WINAPI WSOCK32_accept(SOCKET s, struct sockaddr *addr,
819 INT *addrlen32)
821 LPWSINFO pwsi = WINSOCK_GetIData();
822 #ifdef HAVE_IPX
823 struct ws_sockaddr_ipx* addr2 = (struct ws_sockaddr_ipx *)addr;
824 #endif
826 TRACE("(%08x): socket %04x\n",
827 (unsigned)pwsi, (UINT16)s );
828 if( _check_ws(pwsi, s) )
830 SOCKET as;
831 if (_is_blocking(s))
833 /* block here */
834 int fd = _get_sock_fd(s);
835 do_block(fd, 5);
836 close(fd);
837 _sync_sock_state(s); /* let wineserver notice connection */
838 /* retrieve any error codes from it */
839 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
840 /* FIXME: care about the error? */
842 SERVER_START_REQ
844 struct accept_socket_request *req = server_alloc_req( sizeof(*req), 0 );
846 req->lhandle = s;
847 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
848 req->inherit = TRUE;
849 sock_server_call( REQ_ACCEPT_SOCKET );
850 as = req->handle;
852 SERVER_END_REQ;
853 if( ((int)as) >= 0 )
855 unsigned omask = _get_sock_mask( s );
856 int fd = _get_sock_fd( as );
857 if( getpeername(fd, addr, addrlen32) != -1 )
859 #ifdef HAVE_IPX
860 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
861 addr = (struct sockaddr *)
862 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
863 memcpy(addr, addr2,
864 addrlen32 ? *addrlen32 : sizeof(*addr2));
865 addr2->sipx_family = WS_AF_IPX;
866 addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
867 addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
868 memcpy(addr2->sipx_node,
869 ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
870 free(addr);
872 #endif
873 } else SetLastError(wsaErrno());
874 close(fd);
875 if (omask & WS_FD_SERVEVENT)
876 WSOCK32_async_accept(pwsi, s, as);
877 return as;
880 return INVALID_SOCKET;
883 /***********************************************************************
884 * accept() (WINSOCK.1)
886 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
887 INT16* addrlen16 )
889 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
890 SOCKET retSocket = WSOCK32_accept( s, addr, &addrlen32 );
891 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
892 return (SOCKET16)retSocket;
895 /***********************************************************************
896 * bind() (WSOCK32.2)
898 INT WINAPI WSOCK32_bind(SOCKET s, struct sockaddr *name, INT namelen)
900 LPWSINFO pwsi = WINSOCK_GetIData();
901 #ifdef HAVE_IPX
902 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
903 #endif
905 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
906 (unsigned)pwsi, s, (int) name, namelen);
907 #if DEBUG_SOCKADDR
908 dump_sockaddr(name);
909 #endif
911 if ( _check_ws(pwsi, s) )
913 int fd = _get_sock_fd(s);
914 /* FIXME: what family does this really map to on the Unix side? */
915 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
916 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
917 #ifdef HAVE_IPX
918 else if (name &&
919 ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
921 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
922 memset(name, '\0', sizeof(struct sockaddr_ipx));
923 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
924 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
925 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
926 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
927 name2->sipx_node, IPX_NODE_LEN);
928 namelen = sizeof(struct sockaddr_ipx);
930 #endif
931 if ( namelen >= sizeof(*name) )
933 if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET
934 #ifdef HAVE_IPX
935 || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX
936 #endif
939 if ( bind(fd, name, namelen) < 0 )
941 int loc_errno = errno;
942 WARN("\tfailure - errno = %i\n", errno);
943 errno = loc_errno;
944 switch(errno)
946 case EBADF: SetLastError(WSAENOTSOCK); break;
947 case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break;
948 default: SetLastError(wsaErrno());break;
951 else {
952 #ifdef HAVE_IPX
953 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
954 free(name);
955 #endif
956 close(fd);
957 return 0; /* success */
959 } else SetLastError(WSAEAFNOSUPPORT);
960 } else SetLastError(WSAEFAULT);
961 #ifdef HAVE_IPX
962 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
963 free(name);
964 #endif
965 close(fd);
967 return SOCKET_ERROR;
970 /***********************************************************************
971 * bind() (WINSOCK.2)
973 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
975 return (INT16)WSOCK32_bind( s, name, namelen );
978 /***********************************************************************
979 * closesocket() (WSOCK32.3)
981 INT WINAPI WSOCK32_closesocket(SOCKET s)
983 LPWSINFO pwsi = WINSOCK_GetIData();
985 TRACE("(%08x): socket %08x\n", (unsigned)pwsi, s);
987 if( _check_ws(pwsi, s) )
989 if( CloseHandle(s) )
990 return 0;
992 return SOCKET_ERROR;
995 /***********************************************************************
996 * closesocket() (WINSOCK.3)
998 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
1000 return (INT16)WSOCK32_closesocket(s);
1003 /***********************************************************************
1004 * connect() (WSOCK32.4)
1006 INT WINAPI WSOCK32_connect(SOCKET s, struct sockaddr *name, INT namelen)
1008 LPWSINFO pwsi = WINSOCK_GetIData();
1009 #ifdef HAVE_IPX
1010 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1011 #endif
1013 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
1014 (unsigned)pwsi, s, (int) name, namelen);
1015 #if DEBUG_SOCKADDR
1016 dump_sockaddr(name);
1017 #endif
1019 if( _check_ws(pwsi, s) )
1021 int fd = _get_sock_fd(s);
1022 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
1023 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
1024 #ifdef HAVE_IPX
1025 else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
1027 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1028 memset(name, '\0', sizeof(struct sockaddr_ipx));
1029 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
1030 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
1031 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
1032 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
1033 name2->sipx_node, IPX_NODE_LEN);
1034 namelen = sizeof(struct sockaddr_ipx);
1036 #endif
1037 if (connect(fd, name, namelen) == 0) {
1038 close(fd);
1039 goto connect_success;
1041 if (errno == EINPROGRESS)
1043 /* tell wineserver that a connection is in progress */
1044 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1045 WS_FD_CONNECT|WS_FD_READ|WS_FD_WRITE,
1046 WS_FD_CONNECTED|WS_FD_LISTENING);
1047 if (_is_blocking(s))
1049 int result;
1050 /* block here */
1051 do_block(fd, 6);
1052 _sync_sock_state(s); /* let wineserver notice connection */
1053 /* retrieve any error codes from it */
1054 result = _get_sock_error(s, FD_CONNECT_BIT);
1055 if (result)
1056 SetLastError(result);
1057 else {
1058 close(fd);
1059 goto connect_success;
1062 else SetLastError(WSAEWOULDBLOCK);
1063 close(fd);
1065 else
1067 SetLastError(wsaErrno());
1068 close(fd);
1071 #ifdef HAVE_IPX
1072 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1073 free(name);
1074 #endif
1075 return SOCKET_ERROR;
1076 connect_success:
1077 #ifdef HAVE_IPX
1078 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1079 free(name);
1080 #endif
1081 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1082 WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE,
1083 WS_FD_CONNECT|WS_FD_LISTENING);
1084 return 0;
1087 /***********************************************************************
1088 * connect() (WINSOCK.4)
1090 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
1092 return (INT16)WSOCK32_connect( s, name, namelen );
1095 /***********************************************************************
1096 * getpeername() (WSOCK32.5)
1098 INT WINAPI WSOCK32_getpeername(SOCKET s, struct sockaddr *name,
1099 INT *namelen)
1101 LPWSINFO pwsi = WINSOCK_GetIData();
1102 #ifdef HAVE_IPX
1103 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1104 #endif
1106 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1107 (unsigned)pwsi, s, (int) name, *namelen);
1108 if( _check_ws(pwsi, s) )
1110 int fd = _get_sock_fd(s);
1111 if (getpeername(fd, name, namelen) == 0) {
1112 #ifdef HAVE_IPX
1113 if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1114 name = (struct sockaddr *)
1115 malloc(namelen ? *namelen : sizeof(*name2));
1116 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1117 name2->sipx_family = WS_AF_IPX;
1118 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1119 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1120 memcpy(name2->sipx_node,
1121 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1122 free(name);
1124 #endif
1125 close(fd);
1126 return 0;
1128 SetLastError(wsaErrno());
1129 close(fd);
1131 return SOCKET_ERROR;
1134 /***********************************************************************
1135 * getpeername() (WINSOCK.5)
1137 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
1138 INT16 *namelen16)
1140 INT namelen32 = *namelen16;
1141 INT retVal = WSOCK32_getpeername( s, name, &namelen32 );
1143 #if DEBUG_SOCKADDR
1144 dump_sockaddr(name);
1145 #endif
1147 *namelen16 = namelen32;
1148 return (INT16)retVal;
1151 /***********************************************************************
1152 * getsockname() (WSOCK32.6)
1154 INT WINAPI WSOCK32_getsockname(SOCKET s, struct sockaddr *name,
1155 INT *namelen)
1157 LPWSINFO pwsi = WINSOCK_GetIData();
1158 #ifdef HAVE_IPX
1159 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1160 #endif
1162 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1163 (unsigned)pwsi, s, (int) name, (int) *namelen);
1164 if( _check_ws(pwsi, s) )
1166 int fd = _get_sock_fd(s);
1167 if (getsockname(fd, name, namelen) == 0) {
1168 #ifdef HAVE_IPX
1169 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1170 name = (struct sockaddr *)
1171 malloc(namelen ? *namelen : sizeof(*name2));
1172 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1173 name2->sipx_family = WS_AF_IPX;
1174 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1175 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1176 memcpy(name2->sipx_node,
1177 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1178 free(name);
1180 #endif
1181 close(fd);
1182 return 0;
1184 SetLastError(wsaErrno());
1185 close(fd);
1187 return SOCKET_ERROR;
1190 /***********************************************************************
1191 * getsockname() (WINSOCK.6)
1193 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
1194 INT16 *namelen16)
1196 INT retVal;
1198 if( namelen16 )
1200 INT namelen32 = *namelen16;
1201 retVal = WSOCK32_getsockname( s, name, &namelen32 );
1202 *namelen16 = namelen32;
1204 #if DEBUG_SOCKADDR
1205 dump_sockaddr(name);
1206 #endif
1209 else retVal = SOCKET_ERROR;
1210 return (INT16)retVal;
1214 /***********************************************************************
1215 * getsockopt() (WSOCK32.7)
1217 INT WINAPI WSOCK32_getsockopt(SOCKET s, INT level,
1218 INT optname, char *optval, INT *optlen)
1220 LPWSINFO pwsi = WINSOCK_GetIData();
1222 TRACE("(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n",
1223 (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
1224 if( _check_ws(pwsi, s) )
1226 int fd = _get_sock_fd(s);
1227 convert_sockopt(&level, &optname);
1228 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1230 close(fd);
1231 return 0;
1233 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1234 close(fd);
1236 return SOCKET_ERROR;
1239 /***********************************************************************
1240 * getsockopt() (WINSOCK.7)
1242 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1243 INT16 optname, char *optval, INT16 *optlen)
1245 INT optlen32;
1246 INT *p = &optlen32;
1247 INT retVal;
1248 if( optlen ) optlen32 = *optlen; else p = NULL;
1249 retVal = WSOCK32_getsockopt( s, (UINT16)level, optname, optval, p );
1250 if( optlen ) *optlen = optlen32;
1251 return (INT16)retVal;
1254 /***********************************************************************
1255 * htonl() (WINSOCK.8)(WSOCK32.8)
1257 u_long WINAPI WINSOCK_htonl(u_long hostlong) { return( htonl(hostlong) ); }
1258 /***********************************************************************
1259 * htons() (WINSOCK.9)(WSOCK32.9)
1261 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
1262 /***********************************************************************
1263 * inet_addr() (WINSOCK.10)(WSOCK32.10)
1265 u_long WINAPI WINSOCK_inet_addr(char *cp) { return( inet_addr(cp) ); }
1266 /***********************************************************************
1267 * ntohl() (WINSOCK.14)(WSOCK32.14)
1269 u_long WINAPI WINSOCK_ntohl(u_long netlong) { return( ntohl(netlong) ); }
1270 /***********************************************************************
1271 * ntohs() (WINSOCK.15)(WSOCK32.15)
1273 u_short WINAPI WINSOCK_ntohs(u_short netshort) { return( ntohs(netshort) ); }
1275 /***********************************************************************
1276 * inet_ntoa() (WINSOCK.11)(WSOCK32.11)
1278 char* WINAPI WSOCK32_inet_ntoa(struct in_addr in)
1280 /* use "buffer for dummies" here because some applications have
1281 * propensity to decode addresses in ws_hostent structure without
1282 * saving them first...
1285 LPWSINFO pwsi = WINSOCK_GetIData();
1287 if( pwsi )
1289 char* s = inet_ntoa(in);
1290 if( s )
1292 if( pwsi->dbuffer == NULL ) {
1293 /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1294 if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(16)) == NULL )
1296 SetLastError(WSAENOBUFS);
1297 return NULL;
1300 strcpy(pwsi->dbuffer, s);
1301 return pwsi->dbuffer;
1303 SetLastError(wsaErrno());
1305 return NULL;
1308 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1310 char* retVal = WSOCK32_inet_ntoa(in);
1311 return retVal ? SEGPTR_GET(retVal) : (SEGPTR)NULL;
1315 /**********************************************************************
1316 * WSAIoctl (WS2_32)
1319 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1321 INT WINAPI WSAIoctl (SOCKET s,
1322 DWORD dwIoControlCode,
1323 LPVOID lpvInBuffer,
1324 DWORD cbInBuffer,
1325 LPVOID lpbOutBuffer,
1326 DWORD cbOutBuffer,
1327 LPDWORD lpcbBytesReturned,
1328 LPWSAOVERLAPPED lpOverlapped,
1329 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1331 LPWSINFO pwsi = WINSOCK_GetIData();
1333 if( _check_ws(pwsi, s) )
1335 int fd = _get_sock_fd(s);
1337 switch( dwIoControlCode )
1339 case SIO_GET_INTERFACE_LIST:
1341 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1342 int i, numInt;
1343 struct ifreq ifInfo;
1344 char ifName[512];
1347 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1349 numInt = WSAIOCTL_GetInterfaceCount();
1350 if (numInt < 0)
1352 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1353 close(fd);
1354 WSASetLastError(WSAEINVAL);
1355 return (SOCKET_ERROR);
1358 for (i=0; i<numInt; i++)
1360 if (!WSAIOCTL_GetInterfaceName(i, ifName))
1362 ERR ("Error parsing /proc filesystem!\n");
1363 close(fd);
1364 WSASetLastError(WSAEINVAL);
1365 return (SOCKET_ERROR);
1368 ifInfo.ifr_addr.sa_family = AF_INET;
1370 /* IP Address */
1371 strcpy (ifInfo.ifr_name, ifName);
1372 if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
1374 ERR ("Error obtaining IP address\n");
1375 close(fd);
1376 WSASetLastError(WSAEINVAL);
1377 return (SOCKET_ERROR);
1379 else
1381 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1383 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1384 intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1385 intArray->iiAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1388 /* Broadcast Address */
1389 strcpy (ifInfo.ifr_name, ifName);
1390 if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1392 ERR ("Error obtaining Broadcast IP address\n");
1393 close(fd);
1394 WSASetLastError(WSAEINVAL);
1395 return (SOCKET_ERROR);
1397 else
1399 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
1401 intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
1402 intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
1403 intArray->iiBroadcastAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1406 /* Subnet Mask */
1407 strcpy (ifInfo.ifr_name, ifName);
1408 if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
1410 ERR ("Error obtaining Subnet IP address\n");
1411 close(fd);
1412 WSASetLastError(WSAEINVAL);
1413 return (SOCKET_ERROR);
1415 else
1417 /* Trying to avoid some compile problems across platforms.
1418 (Linux, FreeBSD, Solaris...) */
1419 #ifndef ifr_netmask
1420 #ifndef ifr_addr
1421 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1422 intArray->iiNetmask.AddressIn.sin_port = 0;
1423 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = 0;
1424 ERR ("Unable to determine Netmask on your platform!\n");
1425 #else
1426 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1428 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1429 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1430 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1431 #endif
1432 #else
1433 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
1435 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1436 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1437 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1438 #endif
1441 /* Socket Status Flags */
1442 strcpy(ifInfo.ifr_name, ifName);
1443 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1445 ERR ("Error obtaining status flags for socket!\n");
1446 close(fd);
1447 WSASetLastError(WSAEINVAL);
1448 return (SOCKET_ERROR);
1450 else
1452 /* FIXME - Is this the right flag to use? */
1453 intArray->iiFlags = ifInfo.ifr_flags;
1455 intArray++; /* Prepare for another interface */
1458 /* Calculate the size of the array being returned */
1459 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1460 break;
1463 default:
1465 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1466 close(fd);
1467 WSASetLastError(WSAEOPNOTSUPP);
1468 return (SOCKET_ERROR);
1472 /* Function executed with no errors */
1473 close(fd);
1474 return (0);
1476 else
1478 WSASetLastError(WSAENOTSOCK);
1479 return (SOCKET_ERROR);
1485 Helper function for WSAIoctl - Get count of the number of interfaces
1486 by parsing /proc filesystem.
1488 int WSAIOCTL_GetInterfaceCount(void)
1490 FILE *procfs;
1491 char buf[512]; /* Size doesn't matter, something big */
1492 int intcnt=0;
1495 /* Open /proc filesystem file for network devices */
1496 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1497 if (!procfs)
1499 /* If we can't open the file, return an error */
1500 return (-1);
1503 /* Omit first two lines, they are only headers */
1504 fgets(buf, sizeof buf, procfs);
1505 fgets(buf, sizeof buf, procfs);
1507 while (fgets(buf, sizeof buf, procfs))
1509 /* Each line in the file represents a network interface */
1510 intcnt++;
1513 fclose(procfs);
1514 return(intcnt);
1519 Helper function for WSAIoctl - Get name of device from interface number
1520 by parsing /proc filesystem.
1522 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
1524 FILE *procfs;
1525 char buf[512]; /* Size doesn't matter, something big */
1526 int i;
1528 /* Open /proc filesystem file for network devices */
1529 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1530 if (!procfs)
1532 /* If we can't open the file, return an error */
1533 return (-1);
1536 /* Omit first two lines, they are only headers */
1537 fgets(buf, sizeof(buf), procfs);
1538 fgets(buf, sizeof(buf), procfs);
1540 for (i=0; i<intNumber; i++)
1542 /* Skip the lines that don't interest us. */
1543 fgets(buf, sizeof(buf), procfs);
1545 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
1548 /* Parse out the line, grabbing only the name of the device
1549 to the intName variable
1551 The Line comes in like this: (we only care about the device name)
1552 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
1554 i=0;
1555 while (isspace(buf[i])) /* Skip initial space(s) */
1557 i++;
1560 while (buf[i])
1562 if (isspace(buf[i]))
1564 break;
1567 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
1569 /* This interface could be an alias... */
1570 int hold = i;
1571 char *dotname = intName;
1572 *intName++ = buf[i++];
1574 while (isdigit(buf[i]))
1576 *intName++ = buf[i++];
1579 if (buf[i] != ':')
1581 /* ... It wasn't, so back up */
1582 i = hold;
1583 intName = dotname;
1586 if (buf[i] == '\0')
1588 fclose(procfs);
1589 return(FALSE);
1592 i++;
1593 break;
1596 *intName++ = buf[i++];
1598 *intName++ = '\0';
1600 fclose(procfs);
1601 return(TRUE);
1605 /***********************************************************************
1606 * ioctlsocket() (WSOCK32.12)
1608 INT WINAPI WSOCK32_ioctlsocket(SOCKET s, LONG cmd, ULONG *argp)
1610 LPWSINFO pwsi = WINSOCK_GetIData();
1612 TRACE("(%08x): socket %04x, cmd %08lx, ptr %8x\n",
1613 (unsigned)pwsi, s, cmd, (unsigned) argp);
1614 if( _check_ws(pwsi, s) )
1616 int fd = _get_sock_fd(s);
1617 long newcmd = cmd;
1619 switch( cmd )
1621 case WS_FIONREAD:
1622 newcmd=FIONREAD;
1623 break;
1625 case WS_FIONBIO:
1626 newcmd=FIONBIO;
1627 if( _get_sock_mask(s) )
1629 /* AsyncSelect()'ed sockets are always nonblocking */
1630 if (*argp) {
1631 close(fd);
1632 return 0;
1634 SetLastError(WSAEINVAL);
1635 close(fd);
1636 return SOCKET_ERROR;
1638 close(fd);
1639 if (*argp)
1640 _enable_event(s, 0, WS_FD_NONBLOCKING, 0);
1641 else
1642 _enable_event(s, 0, 0, WS_FD_NONBLOCKING);
1643 return 0;
1645 case WS_SIOCATMARK:
1646 newcmd=SIOCATMARK;
1647 break;
1649 case WS_IOW('f',125,u_long):
1650 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1651 SetLastError(WSAEINVAL);
1652 return SOCKET_ERROR;
1654 default:
1655 /* Netscape tries hard to use bogus ioctl 0x667e */
1656 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1658 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1660 close(fd);
1661 return 0;
1663 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1664 close(fd);
1666 return SOCKET_ERROR;
1669 /***********************************************************************
1670 * ioctlsocket() (WINSOCK.12)
1672 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
1674 return (INT16)WSOCK32_ioctlsocket( s, cmd, argp );
1678 /***********************************************************************
1679 * listen() (WSOCK32.13)
1681 INT WINAPI WSOCK32_listen(SOCKET s, INT backlog)
1683 LPWSINFO pwsi = WINSOCK_GetIData();
1685 TRACE("(%08x): socket %04x, backlog %d\n",
1686 (unsigned)pwsi, s, backlog);
1687 if( _check_ws(pwsi, s) )
1689 int fd = _get_sock_fd(s);
1690 if (listen(fd, backlog) == 0)
1692 close(fd);
1693 _enable_event(s, FD_ACCEPT,
1694 WS_FD_LISTENING,
1695 WS_FD_CONNECT|WS_FD_CONNECTED);
1696 return 0;
1698 SetLastError(wsaErrno());
1700 else SetLastError(WSAENOTSOCK);
1701 return SOCKET_ERROR;
1704 /***********************************************************************
1705 * listen() (WINSOCK.13)
1707 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1709 return (INT16)WSOCK32_listen( s, backlog );
1713 /***********************************************************************
1714 * recv() (WSOCK32.16)
1716 INT WINAPI WSOCK32_recv(SOCKET s, char *buf, INT len, INT flags)
1718 LPWSINFO pwsi = WINSOCK_GetIData();
1720 TRACE("(%08x): socket %04x, buf %8x, len %d, "
1721 "flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1722 len, flags);
1723 if( _check_ws(pwsi, s) )
1725 int fd = _get_sock_fd(s);
1726 INT length;
1728 if (_is_blocking(s))
1730 /* block here */
1731 /* FIXME: OOB and exceptfds? */
1732 do_block(fd, 1);
1734 if ((length = recv(fd, buf, len, flags)) >= 0)
1736 TRACE(" -> %i bytes\n", length);
1738 close(fd);
1739 _enable_event(s, FD_READ, 0, 0);
1740 return length;
1742 SetLastError(wsaErrno());
1743 close(fd);
1745 else SetLastError(WSAENOTSOCK);
1746 WARN(" -> ERROR\n");
1747 return SOCKET_ERROR;
1750 /***********************************************************************
1751 * recv() (WINSOCK.16)
1753 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1755 return (INT16)WSOCK32_recv( s, buf, len, flags );
1759 /***********************************************************************
1760 * recvfrom() (WSOCK32.17)
1762 INT WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, INT flags,
1763 struct sockaddr *from, INT *fromlen32)
1765 LPWSINFO pwsi = WINSOCK_GetIData();
1766 #ifdef HAVE_IPX
1767 struct ws_sockaddr_ipx* from2 = (struct ws_sockaddr_ipx *)from;
1768 #endif
1770 TRACE("(%08x): socket %04x, ptr %08x, "
1771 "len %d, flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1772 len, flags);
1773 #if DEBUG_SOCKADDR
1774 if( from ) dump_sockaddr(from);
1775 else DPRINTF("from = NULL\n");
1776 #endif
1778 if( _check_ws(pwsi, s) )
1780 int fd = _get_sock_fd(s);
1781 int length;
1783 if (_is_blocking(s))
1785 /* block here */
1786 /* FIXME: OOB and exceptfds */
1787 do_block(fd, 1);
1789 if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0)
1791 TRACE(" -> %i bytes\n", length);
1793 #ifdef HAVE_IPX
1794 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1795 from = (struct sockaddr *)
1796 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1797 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1798 from2->sipx_family = WS_AF_IPX;
1799 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1800 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1801 memcpy(from2->sipx_node,
1802 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1803 free(from);
1805 #endif
1806 close(fd);
1807 _enable_event(s, FD_READ, 0, 0);
1808 return (INT16)length;
1810 SetLastError(wsaErrno());
1811 close(fd);
1813 else SetLastError(WSAENOTSOCK);
1814 WARN(" -> ERROR\n");
1815 #ifdef HAVE_IPX
1816 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1817 from = (struct sockaddr *)
1818 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1819 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1820 from2->sipx_family = WS_AF_IPX;
1821 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1822 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1823 memcpy(from2->sipx_node,
1824 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1825 free(from);
1827 #endif
1828 return SOCKET_ERROR;
1831 /***********************************************************************
1832 * recvfrom() (WINSOCK.17)
1834 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1835 struct sockaddr *from, INT16 *fromlen16)
1837 INT fromlen32;
1838 INT *p = &fromlen32;
1839 INT retVal;
1841 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1842 retVal = WSOCK32_recvfrom( s, buf, len, flags, from, p );
1843 if( fromlen16 ) *fromlen16 = fromlen32;
1844 return (INT16)retVal;
1847 /***********************************************************************
1848 * select() (WINSOCK.18)(WSOCK32.18)
1850 static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1851 struct timeval *timeout )
1853 LPWSINFO pwsi = WINSOCK_GetIData();
1855 TRACE("(%08x): read %8x, write %8x, excp %8x\n",
1856 (unsigned) pwsi, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
1858 if( pwsi )
1860 int highfd = 0;
1861 fd_set readfds, writefds, exceptfds;
1862 fd_set *p_read, *p_write, *p_except;
1863 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1865 p_read = fd_set_import(&readfds, pwsi, ws_readfds, &highfd, readfd, b32);
1866 p_write = fd_set_import(&writefds, pwsi, ws_writefds, &highfd, writefd, b32);
1867 p_except = fd_set_import(&exceptfds, pwsi, ws_exceptfds, &highfd, exceptfd, b32);
1869 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
1871 fd_set_export(pwsi, &readfds, p_except, ws_readfds, readfd, b32);
1872 fd_set_export(pwsi, &writefds, p_except, ws_writefds, writefd, b32);
1874 if (p_except && ws_exceptfds)
1876 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1877 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1878 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1880 for (i = j = 0; i < count; i++)
1882 int fd = exceptfd[i];
1883 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
1885 if( b32 )
1886 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1887 else
1888 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1890 if( fd >= 0 ) close(fd);
1891 exceptfd[i] = -1;
1893 if( b32 )
1894 wsfds32->fd_count = j;
1895 else
1896 wsfds16->fd_count = j;
1897 #undef wsfds32
1898 #undef wsfds16
1900 return highfd;
1902 fd_set_unimport(ws_readfds, readfd, b32);
1903 fd_set_unimport(ws_writefds, writefd, b32);
1904 fd_set_unimport(ws_exceptfds, exceptfd, b32);
1905 if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1906 if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1907 if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1909 if( highfd == 0 ) return 0;
1910 SetLastError(wsaErrno());
1912 return SOCKET_ERROR;
1915 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1916 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1917 struct timeval *timeout)
1919 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1922 INT WINAPI WSOCK32_select(INT nfds, ws_fd_set32 *ws_readfds,
1923 ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
1924 struct timeval *timeout)
1926 /* struct timeval is the same for both 32- and 16-bit code */
1927 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1931 /***********************************************************************
1932 * send() (WSOCK32.19)
1934 INT WINAPI WSOCK32_send(SOCKET s, char *buf, INT len, INT flags)
1936 LPWSINFO pwsi = WINSOCK_GetIData();
1938 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1939 (unsigned)pwsi, s, (unsigned) buf, len, flags);
1940 if( _check_ws(pwsi, s) )
1942 int fd = _get_sock_fd(s);
1943 int length;
1945 if (_is_blocking(s))
1947 /* block here */
1948 /* FIXME: exceptfds */
1949 do_block(fd, 2);
1951 if ((length = send(fd, buf, len, flags)) < 0 )
1953 SetLastError(wsaErrno());
1954 if( GetLastError() == WSAEWOULDBLOCK )
1955 _enable_event(s, FD_WRITE, 0, 0);
1957 else
1959 close(fd);
1960 return (INT16)length;
1962 close(fd);
1964 else SetLastError(WSAENOTSOCK);
1965 return SOCKET_ERROR;
1968 /***********************************************************************
1969 * send() (WINSOCK.19)
1971 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1973 return WSOCK32_send( s, buf, len, flags );
1976 /***********************************************************************
1977 * sendto() (WSOCK32.20)
1979 INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags,
1980 struct sockaddr *to, INT tolen)
1982 LPWSINFO pwsi = WINSOCK_GetIData();
1983 #ifdef HAVE_IPX
1984 struct ws_sockaddr_ipx* to2 = (struct ws_sockaddr_ipx *)to;
1985 #endif
1987 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1988 (unsigned)pwsi, s, (unsigned) buf, len, flags);
1989 if( _check_ws(pwsi, s) )
1991 int fd = _get_sock_fd(s);
1992 INT length;
1994 if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
1995 ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
1996 #ifdef HAVE_IPX
1997 else if (to &&
1998 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
2000 to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
2001 memset(to, '\0', sizeof(struct sockaddr_ipx));
2002 ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
2003 ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
2004 ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
2005 memcpy(((struct sockaddr_ipx *)to)->sipx_node,
2006 to2->sipx_node, IPX_NODE_LEN);
2007 tolen = sizeof(struct sockaddr_ipx);
2009 #endif
2010 if (_is_blocking(s))
2012 /* block here */
2013 /* FIXME: exceptfds */
2014 do_block(fd, 2);
2016 if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
2018 SetLastError(wsaErrno());
2019 if( GetLastError() == WSAEWOULDBLOCK )
2020 _enable_event(s, FD_WRITE, 0, 0);
2022 else {
2023 #ifdef HAVE_IPX
2024 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
2025 free(to);
2027 #endif
2028 close(fd);
2029 return length;
2031 close(fd);
2033 else SetLastError(WSAENOTSOCK);
2034 #ifdef HAVE_IPX
2035 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
2036 free(to);
2038 #endif
2039 return SOCKET_ERROR;
2042 /***********************************************************************
2043 * sendto() (WINSOCK.20)
2045 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2046 struct sockaddr *to, INT16 tolen)
2048 return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen );
2051 /***********************************************************************
2052 * setsockopt() (WSOCK32.21)
2054 INT WINAPI WSOCK32_setsockopt(SOCKET16 s, INT level, INT optname,
2055 char *optval, INT optlen)
2057 LPWSINFO pwsi = WINSOCK_GetIData();
2059 TRACE("(%08x): socket %04x, lev %d, opt %d, ptr %08x, len %d\n",
2060 (unsigned)pwsi, s, level, optname, (int) optval, optlen);
2061 if( _check_ws(pwsi, s) )
2063 struct linger linger;
2064 int fd = _get_sock_fd(s);
2065 int woptval;
2067 convert_sockopt(&level, &optname);
2068 if(optname == WS_SO_DONTLINGER) {
2069 linger.l_onoff = *((int*)optval) ? 0: 1;
2070 linger.l_linger = 0;
2071 optname=SO_LINGER;
2072 optval = (char*)&linger;
2073 optlen = sizeof(struct linger);
2074 }else{
2075 if (optname == SO_LINGER && optval) {
2076 /* yes, uses unsigned short in both win16/win32 */
2077 linger.l_onoff = ((UINT16*)optval)[0];
2078 linger.l_linger = ((UINT16*)optval)[1];
2079 /* FIXME: what is documented behavior if SO_LINGER optval
2080 is null?? */
2081 optval = (char*)&linger;
2082 optlen = sizeof(struct linger);
2083 } else if (optlen < sizeof(int)){
2084 woptval= *((INT16 *) optval);
2085 optval= (char*) &woptval;
2086 optlen=sizeof(int);
2089 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2091 close(fd);
2092 return 0;
2094 SetLastError(wsaErrno());
2095 close(fd);
2097 else SetLastError(WSAENOTSOCK);
2098 return SOCKET_ERROR;
2101 /***********************************************************************
2102 * setsockopt() (WINSOCK.21)
2104 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2105 char *optval, INT16 optlen)
2107 if( !optval ) return SOCKET_ERROR;
2108 return (INT16)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
2112 /***********************************************************************
2113 * shutdown() (WSOCK32.22)
2115 INT WINAPI WSOCK32_shutdown(SOCKET s, INT how)
2117 LPWSINFO pwsi = WINSOCK_GetIData();
2119 TRACE("(%08x): socket %04x, how %i\n",
2120 (unsigned)pwsi, s, how );
2121 if( _check_ws(pwsi, s) )
2123 int fd = _get_sock_fd(s);
2124 switch( how )
2126 case 0: /* drop receives */
2127 _enable_event(s, 0, 0, WS_FD_READ);
2128 #ifdef SHUT_RD
2129 how = SHUT_RD;
2130 #endif
2131 break;
2133 case 1: /* drop sends */
2134 _enable_event(s, 0, 0, WS_FD_WRITE);
2135 #ifdef SHUT_WR
2136 how = SHUT_WR;
2137 #endif
2138 break;
2140 case 2: /* drop all */
2141 #ifdef SHUT_RDWR
2142 how = SHUT_RDWR;
2143 #endif
2144 default:
2145 WSAAsyncSelect( s, 0, 0, 0 );
2146 break;
2149 if (shutdown(fd, how) == 0)
2151 if( how > 1 )
2153 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
2155 close(fd);
2156 return 0;
2158 SetLastError(wsaErrno());
2159 close(fd);
2161 else SetLastError(WSAENOTSOCK);
2162 return SOCKET_ERROR;
2165 /***********************************************************************
2166 * shutdown() (WINSOCK.22)
2168 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2170 return (INT16)WSOCK32_shutdown( s, how );
2174 /***********************************************************************
2175 * socket() (WSOCK32.23)
2177 SOCKET WINAPI WSOCK32_socket(INT af, INT type, INT protocol)
2179 LPWSINFO pwsi = WINSOCK_GetIData();
2180 SOCKET ret;
2182 TRACE("(%08x): af=%d type=%d protocol=%d\n",
2183 (unsigned)pwsi, af, type, protocol);
2185 if( pwsi )
2187 /* check the socket family */
2188 switch(af)
2190 #ifdef HAVE_IPX
2191 case WS_AF_IPX: af = AF_IPX;
2192 #endif
2193 case AF_INET:
2194 case AF_UNSPEC: break;
2195 default: SetLastError(WSAEAFNOSUPPORT);
2196 return INVALID_SOCKET;
2199 /* check the socket type */
2200 switch(type)
2202 case SOCK_STREAM:
2203 case SOCK_DGRAM:
2204 case SOCK_RAW: break;
2205 default: SetLastError(WSAESOCKTNOSUPPORT);
2206 return INVALID_SOCKET;
2209 /* check the protocol type */
2210 if ( protocol < 0 ) /* don't support negative values */
2211 { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
2213 if ( af == AF_UNSPEC) /* did they not specify the address family? */
2214 switch(protocol)
2216 case IPPROTO_TCP:
2217 if (type == SOCK_STREAM) { af = AF_INET; break; }
2218 case IPPROTO_UDP:
2219 if (type == SOCK_DGRAM) { af = AF_INET; break; }
2220 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2223 SERVER_START_REQ
2225 struct create_socket_request *req = server_alloc_req( sizeof(*req), 0 );
2226 req->family = af;
2227 req->type = type;
2228 req->protocol = protocol;
2229 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2230 req->inherit = TRUE;
2231 sock_server_call( REQ_CREATE_SOCKET );
2232 ret = req->handle;
2234 SERVER_END_REQ;
2235 if ( ((int) ret) >= 0)
2237 TRACE("\tcreated %04x\n", ret );
2238 return ret;
2241 if (GetLastError() == WSAEACCES) /* raw socket denied */
2243 if (type == SOCK_RAW)
2244 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2245 else
2246 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2247 SetLastError(WSAESOCKTNOSUPPORT);
2251 WARN("\t\tfailed!\n");
2252 return INVALID_SOCKET;
2255 /***********************************************************************
2256 * socket() (WINSOCK.23)
2258 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2260 return (SOCKET16)WSOCK32_socket( af, type, protocol );
2264 /* ----------------------------------- DNS services
2266 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2267 * Also, we have to use wsock32 stubs to convert structures and
2268 * error codes from Unix to WSA, hence there is no direct mapping in
2269 * the relay32/wsock32.spec.
2272 static char* NULL_STRING = "NULL";
2274 /***********************************************************************
2275 * gethostbyaddr() (WINSOCK.51)(WSOCK32.51)
2277 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2279 LPWSINFO pwsi = WINSOCK_GetIData();
2281 if( pwsi )
2283 struct hostent* host;
2284 if( (host = gethostbyaddr(addr, len, type)) != NULL )
2285 if( WS_dup_he(pwsi, host, dup_flag) )
2286 return (WIN_hostent*)(pwsi->he);
2287 else
2288 SetLastError(WSAENOBUFS);
2289 else
2290 SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
2292 return NULL;
2295 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2297 WIN_hostent* retval;
2298 TRACE("ptr %08x, len %d, type %d\n",
2299 (unsigned) addr, len, type);
2300 retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
2301 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2304 WIN_hostent* WINAPI WSOCK32_gethostbyaddr(const char *addr, INT len,
2305 INT type)
2307 TRACE("ptr %08x, len %d, type %d\n",
2308 (unsigned) addr, len, type);
2309 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2312 /***********************************************************************
2313 * gethostbyname() (WINSOCK.52)(WSOCK32.52)
2315 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2317 LPWSINFO pwsi = WINSOCK_GetIData();
2319 if( pwsi )
2321 struct hostent* host;
2322 if( (host = gethostbyname(name)) != NULL )
2323 if( WS_dup_he(pwsi, host, dup_flag) )
2324 return (WIN_hostent*)(pwsi->he);
2325 else SetLastError(WSAENOBUFS);
2326 else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
2328 return NULL;
2331 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2333 WIN_hostent* retval;
2334 TRACE("%s\n", (name)?name:NULL_STRING);
2335 retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
2336 return (retval)? SEGPTR_GET(retval) : ((SEGPTR)NULL) ;
2339 WIN_hostent* WINAPI WSOCK32_gethostbyname(const char* name)
2341 TRACE("%s\n", (name)?name:NULL_STRING);
2342 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2346 /***********************************************************************
2347 * getprotobyname() (WINSOCK.53)(WSOCK32.53)
2349 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2351 LPWSINFO pwsi = WINSOCK_GetIData();
2353 if( pwsi )
2355 struct protoent* proto;
2356 if( (proto = getprotobyname(name)) != NULL )
2357 if( WS_dup_pe(pwsi, proto, dup_flag) )
2358 return (WIN_protoent*)(pwsi->pe);
2359 else SetLastError(WSAENOBUFS);
2360 else {
2361 MESSAGE("protocol %s not found; You might want to add "
2362 "this to /etc/protocols\n", debugstr_a(name) );
2363 SetLastError(WSANO_DATA);
2365 } else SetLastError(WSANOTINITIALISED);
2366 return NULL;
2369 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2371 WIN_protoent* retval;
2372 TRACE("%s\n", (name)?name:NULL_STRING);
2373 retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
2374 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2377 WIN_protoent* WINAPI WSOCK32_getprotobyname(const char* name)
2379 TRACE("%s\n", (name)?name:NULL_STRING);
2380 return __ws_getprotobyname(name, WS_DUP_LINEAR);
2384 /***********************************************************************
2385 * getprotobynumber() (WINSOCK.54)(WSOCK32.54)
2387 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2389 LPWSINFO pwsi = WINSOCK_GetIData();
2391 if( pwsi )
2393 struct protoent* proto;
2394 if( (proto = getprotobynumber(number)) != NULL )
2395 if( WS_dup_pe(pwsi, proto, dup_flag) )
2396 return (WIN_protoent*)(pwsi->pe);
2397 else SetLastError(WSAENOBUFS);
2398 else {
2399 MESSAGE("protocol number %d not found; You might want to add "
2400 "this to /etc/protocols\n", number );
2401 SetLastError(WSANO_DATA);
2403 } else SetLastError(WSANOTINITIALISED);
2404 return NULL;
2407 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2409 WIN_protoent* retval;
2410 TRACE("%i\n", number);
2411 retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
2412 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2415 WIN_protoent* WINAPI WSOCK32_getprotobynumber(INT number)
2417 TRACE("%i\n", number);
2418 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2422 /***********************************************************************
2423 * getservbyname() (WINSOCK.55)(WSOCK32.55)
2425 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
2427 LPWSINFO pwsi = WINSOCK_GetIData();
2429 if( pwsi )
2431 struct servent* serv;
2432 int i = wsi_strtolo( pwsi, name, proto );
2434 if( i ) {
2435 serv = getservbyname(pwsi->buffer,
2436 proto ? (pwsi->buffer + i) : NULL);
2437 if( serv != NULL )
2438 if( WS_dup_se(pwsi, serv, dup_flag) )
2439 return (WIN_servent*)(pwsi->se);
2440 else SetLastError(WSAENOBUFS);
2441 else {
2442 MESSAGE("service %s protocol %s not found; You might want to add "
2443 "this to /etc/services\n", debugstr_a(pwsi->buffer),
2444 proto ? debugstr_a(pwsi->buffer+i):"*");
2445 SetLastError(WSANO_DATA);
2448 else SetLastError(WSAENOBUFS);
2449 } else SetLastError(WSANOTINITIALISED);
2450 return NULL;
2453 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2455 WIN_servent* retval;
2456 TRACE("'%s', '%s'\n",
2457 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2458 retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2459 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2462 WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
2464 TRACE("'%s', '%s'\n",
2465 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2466 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2470 /***********************************************************************
2471 * getservbyport() (WINSOCK.56)(WSOCK32.56)
2473 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2475 LPWSINFO pwsi = WINSOCK_GetIData();
2477 if( pwsi )
2479 struct servent* serv;
2480 if (!proto || wsi_strtolo( pwsi, proto, NULL )) {
2481 if( (serv = getservbyport(port, (proto) ? pwsi->buffer : NULL)) != NULL ) {
2482 if( WS_dup_se(pwsi, serv, dup_flag) )
2483 return (WIN_servent*)(pwsi->se);
2484 else SetLastError(WSAENOBUFS);
2486 else {
2487 MESSAGE("service on port %lu protocol %s not found; You might want to add "
2488 "this to /etc/services\n", (unsigned long)ntohl(port),
2489 proto ? debugstr_a(pwsi->buffer) : "*");
2490 SetLastError(WSANO_DATA);
2493 else SetLastError(WSAENOBUFS);
2494 } else SetLastError(WSANOTINITIALISED);
2495 return NULL;
2498 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2500 WIN_servent* retval;
2501 TRACE("%d (i.e. port %d), '%s'\n",
2502 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2503 retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2504 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2507 WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
2509 TRACE("%d (i.e. port %d), '%s'\n",
2510 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2511 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2515 /***********************************************************************
2516 * gethostname() (WSOCK32.57)
2518 INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
2520 LPWSINFO pwsi = WINSOCK_GetIData();
2522 TRACE("(%08x): name %s, len %d\n",
2523 (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
2524 if( pwsi )
2526 if (gethostname(name, namelen) == 0) return 0;
2527 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2529 return SOCKET_ERROR;
2532 /***********************************************************************
2533 * gethostname() (WINSOCK.57)
2535 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2537 return (INT16)WSOCK32_gethostname(name, namelen);
2541 /* ------------------------------------- Windows sockets extensions -- *
2543 * ------------------------------------------------------------------- */
2545 /***********************************************************************
2546 * WSAEnumNetworkEvents
2548 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2550 LPWSINFO pwsi = WINSOCK_GetIData();
2552 TRACE("(%08x): %08x, hEvent %08x, lpEvent %08x\n",
2553 (unsigned)pwsi, s, hEvent, (unsigned)lpEvent );
2554 if( _check_ws(pwsi, s) )
2556 SERVER_START_REQ
2558 struct get_socket_event_request *req = server_alloc_req( sizeof(*req),
2559 sizeof(lpEvent->iErrorCode) );
2560 req->handle = s;
2561 req->service = TRUE;
2562 req->s_event = 0;
2563 req->c_event = hEvent;
2564 sock_server_call( REQ_GET_SOCKET_EVENT );
2565 lpEvent->lNetworkEvents = req->pmask;
2566 memcpy(lpEvent->iErrorCode, server_data_ptr(req), server_data_size(req) );
2568 SERVER_END_REQ;
2569 return 0;
2571 else SetLastError(WSAEINVAL);
2572 return SOCKET_ERROR;
2575 /***********************************************************************
2576 * WSAEventSelect
2578 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2580 LPWSINFO pwsi = WINSOCK_GetIData();
2582 TRACE("(%08x): %08x, hEvent %08x, event %08x\n",
2583 (unsigned)pwsi, s, hEvent, (unsigned)lEvent );
2584 if( _check_ws(pwsi, s) )
2586 SERVER_START_REQ
2588 struct set_socket_event_request *req = server_alloc_req( sizeof(*req), 0 );
2589 req->handle = s;
2590 req->mask = lEvent;
2591 req->event = hEvent;
2592 sock_server_call( REQ_SET_SOCKET_EVENT );
2594 SERVER_END_REQ;
2595 return 0;
2597 else SetLastError(WSAEINVAL);
2598 return SOCKET_ERROR;
2601 /***********************************************************************
2602 * WSAAsyncSelect() (WINSOCK.101)(WSOCK32.101)
2605 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2607 ws_select_info *info = (ws_select_info*)ptr;
2608 LPWSINFO pwsi = info->pwsi;
2609 unsigned int i, pmask, orphan = FALSE;
2610 int errors[FD_MAX_EVENTS];
2612 TRACE("socket %08x, event %08x\n", info->sock, info->event);
2613 SetLastError(0);
2614 SERVER_START_REQ
2616 struct get_socket_event_request *req = server_alloc_req( sizeof(*req), sizeof(errors) );
2617 req->handle = info->sock;
2618 req->service = TRUE;
2619 req->s_event = info->event; /* <== avoid race conditions */
2620 req->c_event = info->event;
2621 sock_server_call( REQ_GET_SOCKET_EVENT );
2622 pmask = req->pmask;
2623 memcpy( errors, server_data_ptr(req), server_data_size(req) );
2625 SERVER_END_REQ;
2626 if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
2628 /* orphaned event (socket closed or something) */
2629 pmask = WS_FD_SERVEVENT;
2630 orphan = TRUE;
2633 /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2634 if (pmask & WS_FD_SERVEVENT) {
2635 int q;
2636 for (q=0; q<WS_ACCEPT_QUEUE; q++)
2637 if (pwsi->accept_old[q] == info->sock) {
2638 /* there's only one service thread per pwsi, no lock necessary */
2639 HANDLE as = pwsi->accept_new[q];
2640 if (as) {
2641 pwsi->accept_new[q] = 0;
2642 pwsi->accept_old[q] = 0;
2643 WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
2646 pmask &= ~WS_FD_SERVEVENT;
2648 /* dispatch network events */
2649 for (i=0; i<FD_MAX_EVENTS; i++)
2650 if (pmask & (1<<i)) {
2651 TRACE("post: event bit %d, error %d\n", i, errors[i]);
2652 PostMessageA(info->hWnd, info->uMsg, info->sock,
2653 WSAMAKESELECTREPLY(1<<i, errors[i]));
2655 /* cleanup */
2656 if (orphan)
2658 TRACE("orphaned event, self-destructing\n");
2659 /* SERVICE_Delete closes the event object */
2660 SERVICE_Delete( info->service );
2661 WS_FREE(info);
2665 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2667 LPWSINFO pwsi = WINSOCK_GetIData();
2669 TRACE("(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
2670 (unsigned)pwsi, (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2671 if( _check_ws(pwsi, s) )
2673 if( lEvent )
2675 ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2676 if( info )
2678 HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
2679 INT err;
2681 info->sock = s;
2682 info->event = hObj;
2683 info->hWnd = hWnd;
2684 info->uMsg = uMsg;
2685 info->lEvent = lEvent;
2686 info->pwsi = pwsi;
2687 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2689 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2690 if (err) {
2691 /* SERVICE_Delete closes the event object */
2692 SERVICE_Delete( info->service );
2693 WS_FREE(info);
2694 return err;
2697 return 0; /* success */
2699 else SetLastError(WSAENOBUFS);
2701 else
2703 WSAEventSelect(s, 0, 0);
2704 return 0;
2707 else SetLastError(WSAEINVAL);
2708 return SOCKET_ERROR;
2711 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2713 return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2716 /***********************************************************************
2717 * WSARecvEx() (WSOCK32.1107)
2719 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
2720 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
2721 * into the flags parameter when a partial packet is read. This only applies to
2722 * sockets using the datagram protocol. This method does not seem to be implemented
2723 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
2724 * flag when a fragmented packet arrives.
2726 INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags) {
2727 FIXME("(WSARecvEx) partial packet return value not set \n");
2729 return WSOCK32_recv(s, buf, len, *flags);
2733 /***********************************************************************
2734 * WSARecvEx16() (WINSOCK.1107)
2736 * See description for WSARecvEx()
2738 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2739 FIXME("(WSARecvEx16) partial packet return value not set \n");
2741 return WINSOCK_recv16(s, buf, len, *flags);
2745 /***********************************************************************
2746 * WSACreateEvent() (WS2_32.???)
2749 WSAEVENT WINAPI WSACreateEvent(void)
2751 /* Create a manual-reset event, with initial state: unsignealed */
2752 TRACE("\n");
2754 return CreateEventA(NULL, TRUE, FALSE, NULL);
2757 /***********************************************************************
2758 * WSACloseEvent() (WS2_32.???)
2761 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2763 TRACE ("event=0x%x\n", event);
2765 return CloseHandle(event);
2768 /***********************************************************************
2769 * WSASocketA() (WS2_32.???)
2772 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2773 LPWSAPROTOCOL_INFOA lpProtocolInfo,
2774 GROUP g, DWORD dwFlags)
2777 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2778 g, dwFlags) are ignored.
2781 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
2782 af, type, protocol, lpProtocolInfo, g, dwFlags );
2784 return ( WSOCK32_socket (af, type, protocol) );
2788 /***********************************************************************
2789 * __WSAFDIsSet() (WINSOCK.151)
2791 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2793 int i = set->fd_count;
2795 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2797 while (i--)
2798 if (set->fd_array[i] == s) return 1;
2799 return 0;
2802 /***********************************************************************
2803 * __WSAFDIsSet() (WSOCK32.151)
2805 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2807 int i = set->fd_count;
2809 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2811 while (i--)
2812 if (set->fd_array[i] == s) return 1;
2813 return 0;
2816 /***********************************************************************
2817 * WSAIsBlocking() (WINSOCK.114)(WSOCK32.114)
2819 BOOL WINAPI WSAIsBlocking(void)
2821 /* By default WinSock should set all its sockets to non-blocking mode
2822 * and poll in PeekMessage loop when processing "blocking" ones. This
2823 * function is supposed to tell if the program is in this loop. Our
2824 * blocking calls are truly blocking so we always return FALSE.
2826 * Note: It is allowed to call this function without prior WSAStartup().
2829 TRACE("\n");
2830 return FALSE;
2833 /***********************************************************************
2834 * WSACancelBlockingCall() (WINSOCK.113)(WSOCK32.113)
2836 INT WINAPI WSACancelBlockingCall(void)
2838 LPWSINFO pwsi = WINSOCK_GetIData();
2840 TRACE("(%08x)\n", (unsigned)pwsi);
2842 if( pwsi ) return 0;
2843 return SOCKET_ERROR;
2847 /***********************************************************************
2848 * WSASetBlockingHook16() (WINSOCK.109)
2850 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2852 FARPROC16 prev;
2853 LPWSINFO pwsi = WINSOCK_GetIData();
2855 TRACE("(%08x): hook %08x\n",
2856 (unsigned)pwsi, (unsigned) lpBlockFunc);
2857 if( pwsi )
2859 prev = (FARPROC16)pwsi->blocking_hook;
2860 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2861 pwsi->flags &= ~WSI_BLOCKINGHOOK;
2862 return prev;
2864 return 0;
2868 /***********************************************************************
2869 * WSASetBlockingHook()
2871 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2873 FARPROC prev;
2874 LPWSINFO pwsi = WINSOCK_GetIData();
2876 TRACE("(%08x): hook %08x\n",
2877 (unsigned)pwsi, (unsigned) lpBlockFunc);
2878 if( pwsi ) {
2879 prev = (FARPROC)pwsi->blocking_hook;
2880 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2881 pwsi->flags |= WSI_BLOCKINGHOOK;
2882 return prev;
2884 return NULL;
2888 /***********************************************************************
2889 * WSAUnhookBlockingHook16() (WINSOCK.110)
2891 INT16 WINAPI WSAUnhookBlockingHook16(void)
2893 LPWSINFO pwsi = WINSOCK_GetIData();
2895 TRACE("(%08x)\n", (unsigned)pwsi);
2896 if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
2897 return SOCKET_ERROR;
2901 /***********************************************************************
2902 * WSAUnhookBlockingHook()
2904 INT WINAPI WSAUnhookBlockingHook(void)
2906 LPWSINFO pwsi = WINSOCK_GetIData();
2908 TRACE("(%08x)\n", (unsigned)pwsi);
2909 if( pwsi )
2911 pwsi->blocking_hook = 0;
2912 pwsi->flags &= ~WSI_BLOCKINGHOOK;
2913 return 0;
2915 return SOCKET_ERROR;
2919 /* ----------------------------------- end of API stuff */
2921 /* ----------------------------------- helper functions -
2923 * TODO: Merge WS_dup_..() stuff into one function that
2924 * would operate with a generic structure containing internal
2925 * pointers (via a template of some kind).
2928 static int list_size(char** l, int item_size)
2930 int i,j = 0;
2931 if(l)
2932 { for(i=0;l[i];i++)
2933 j += (item_size) ? item_size : strlen(l[i]) + 1;
2934 j += (i + 1) * sizeof(char*); }
2935 return j;
2938 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2940 /* base is either either equal to ref or 0 or SEGPTR */
2942 char* p = ref;
2943 char** l_to = (char**)ref;
2944 int i,j,k;
2946 for(j=0;l_src[j];j++) ;
2947 p += (j + 1) * sizeof(char*);
2948 for(i=0;i<j;i++)
2949 { l_to[i] = base + (p - ref);
2950 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2951 memcpy(p, l_src[i], k); p += k; }
2952 l_to[i] = NULL;
2953 return (p - ref);
2956 /* ----- hostent */
2958 static int hostent_size(struct hostent* p_he)
2960 int size = 0;
2961 if( p_he )
2962 { size = sizeof(struct hostent);
2963 size += strlen(p_he->h_name) + 1;
2964 size += list_size(p_he->h_aliases, 0);
2965 size += list_size(p_he->h_addr_list, p_he->h_length ); }
2966 return size;
2969 /* duplicate hostent entry
2970 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
2971 * Dito for protoent and servent.
2973 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
2975 /* Convert hostent structure into ws_hostent so that the data fits
2976 * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or
2977 * relative to pwsi->buffer depending on "flag" value. Returns size
2978 * of the data copied (also in the pwsi->buflen).
2981 int size = hostent_size(p_he);
2982 if( size )
2984 char *p_name,*p_aliases,*p_addr,*p_base,*p;
2985 char *p_to;
2986 struct ws_hostent16 *p_to16;
2987 struct ws_hostent32 *p_to32;
2989 _check_buffer_he(pwsi, size);
2990 p_to = (char *)pwsi->he;
2991 p_to16 = (struct ws_hostent16*)pwsi->he;
2992 p_to32 = (struct ws_hostent32*)pwsi->he;
2994 p = p_to;
2995 p_base = (flag & WS_DUP_OFFSET) ? NULL
2996 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2997 p += (flag & WS_DUP_SEGPTR) ?
2998 sizeof(struct ws_hostent16) : sizeof(struct ws_hostent32);
2999 p_name = p;
3000 strcpy(p, p_he->h_name); p += strlen(p) + 1;
3001 p_aliases = p;
3002 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
3003 p_addr = p;
3004 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
3006 if (flag & WS_DUP_SEGPTR) /* Win16 */
3008 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
3009 p_to16->h_length = (INT16)p_he->h_length;
3010 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
3011 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3012 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
3013 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
3015 else /* Win32 */
3017 p_to32->h_addrtype = p_he->h_addrtype;
3018 p_to32->h_length = p_he->h_length;
3019 p_to32->h_name = (p_base + (p_name - p_to));
3020 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
3021 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
3022 size += (sizeof(struct ws_hostent32) - sizeof(struct hostent));
3025 return size;
3028 /* ----- protoent */
3030 static int protoent_size(struct protoent* p_pe)
3032 int size = 0;
3033 if( p_pe )
3034 { size = sizeof(struct protoent);
3035 size += strlen(p_pe->p_name) + 1;
3036 size += list_size(p_pe->p_aliases, 0); }
3037 return size;
3040 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
3042 int size = protoent_size(p_pe);
3043 if( size )
3045 char *p_to;
3046 struct ws_protoent16 *p_to16;
3047 struct ws_protoent32 *p_to32;
3048 char *p_name,*p_aliases,*p_base,*p;
3050 _check_buffer_pe(pwsi, size);
3051 p_to = (char *)pwsi->pe;
3052 p_to16 = (struct ws_protoent16*)pwsi->pe;
3053 p_to32 = (struct ws_protoent32*)pwsi->pe;
3054 p = p_to;
3055 p_base = (flag & WS_DUP_OFFSET) ? NULL
3056 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3057 p += (flag & WS_DUP_SEGPTR) ?
3058 sizeof(struct ws_protoent16) : sizeof(struct ws_protoent32);
3059 p_name = p;
3060 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3061 p_aliases = p;
3062 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3064 if (flag & WS_DUP_SEGPTR) /* Win16 */
3066 p_to16->p_proto = (INT16)p_pe->p_proto;
3067 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3068 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3069 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3071 else /* Win32 */
3073 p_to32->p_proto = p_pe->p_proto;
3074 p_to32->p_name = (p_base) + (p_name - p_to);
3075 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3076 size += (sizeof(struct ws_protoent32) - sizeof(struct protoent));
3079 return size;
3082 /* ----- servent */
3084 static int servent_size(struct servent* p_se)
3086 int size = 0;
3087 if( p_se )
3088 { size += sizeof(struct servent);
3089 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3090 size += list_size(p_se->s_aliases, 0); }
3091 return size;
3094 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
3096 int size = servent_size(p_se);
3097 if( size )
3099 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3100 char *p_to;
3101 struct ws_servent16 *p_to16;
3102 struct ws_servent32 *p_to32;
3104 _check_buffer_se(pwsi, size);
3105 p_to = (char *)pwsi->se;
3106 p_to16 = (struct ws_servent16*)pwsi->se;
3107 p_to32 = (struct ws_servent32*)pwsi->se;
3108 p = p_to;
3109 p_base = (flag & WS_DUP_OFFSET) ? NULL
3110 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3111 p += (flag & WS_DUP_SEGPTR) ?
3112 sizeof(struct ws_servent16) : sizeof(struct ws_servent32);
3113 p_name = p;
3114 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3115 p_proto = p;
3116 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3117 p_aliases = p;
3118 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3120 if (flag & WS_DUP_SEGPTR) /* Win16 */
3122 p_to16->s_port = (INT16)p_se->s_port;
3123 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3124 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3125 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3126 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3128 else /* Win32 */
3130 p_to32->s_port = p_se->s_port;
3131 p_to32->s_name = (p_base + (p_name - p_to));
3132 p_to32->s_proto = (p_base + (p_proto - p_to));
3133 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3134 size += (sizeof(struct ws_servent32) - sizeof(struct servent));
3137 return size;
3140 /* ----------------------------------- error handling */
3142 UINT16 wsaErrno(void)
3144 int loc_errno = errno;
3145 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3147 switch(loc_errno)
3149 case EINTR: return WSAEINTR;
3150 case EBADF: return WSAEBADF;
3151 case EPERM:
3152 case EACCES: return WSAEACCES;
3153 case EFAULT: return WSAEFAULT;
3154 case EINVAL: return WSAEINVAL;
3155 case EMFILE: return WSAEMFILE;
3156 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3157 case EINPROGRESS: return WSAEINPROGRESS;
3158 case EALREADY: return WSAEALREADY;
3159 case ENOTSOCK: return WSAENOTSOCK;
3160 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3161 case EMSGSIZE: return WSAEMSGSIZE;
3162 case EPROTOTYPE: return WSAEPROTOTYPE;
3163 case ENOPROTOOPT: return WSAENOPROTOOPT;
3164 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3165 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3166 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3167 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3168 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3169 case EADDRINUSE: return WSAEADDRINUSE;
3170 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3171 case ENETDOWN: return WSAENETDOWN;
3172 case ENETUNREACH: return WSAENETUNREACH;
3173 case ENETRESET: return WSAENETRESET;
3174 case ECONNABORTED: return WSAECONNABORTED;
3175 case EPIPE:
3176 case ECONNRESET: return WSAECONNRESET;
3177 case ENOBUFS: return WSAENOBUFS;
3178 case EISCONN: return WSAEISCONN;
3179 case ENOTCONN: return WSAENOTCONN;
3180 case ESHUTDOWN: return WSAESHUTDOWN;
3181 case ETOOMANYREFS: return WSAETOOMANYREFS;
3182 case ETIMEDOUT: return WSAETIMEDOUT;
3183 case ECONNREFUSED: return WSAECONNREFUSED;
3184 case ELOOP: return WSAELOOP;
3185 case ENAMETOOLONG: return WSAENAMETOOLONG;
3186 case EHOSTDOWN: return WSAEHOSTDOWN;
3187 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3188 case ENOTEMPTY: return WSAENOTEMPTY;
3189 #ifdef EPROCLIM
3190 case EPROCLIM: return WSAEPROCLIM;
3191 #endif
3192 #ifdef EUSERS
3193 case EUSERS: return WSAEUSERS;
3194 #endif
3195 #ifdef EDQUOT
3196 case EDQUOT: return WSAEDQUOT;
3197 #endif
3198 #ifdef ESTALE
3199 case ESTALE: return WSAESTALE;
3200 #endif
3201 #ifdef EREMOTE
3202 case EREMOTE: return WSAEREMOTE;
3203 #endif
3205 /* just in case we ever get here and there are no problems */
3206 case 0: return 0;
3207 default:
3208 WARN("Unknown errno %d!\n", loc_errno);
3209 return WSAEOPNOTSUPP;
3213 UINT16 wsaHerrno(void)
3215 int loc_errno = h_errno;
3217 WARN("h_errno %d.\n", loc_errno);
3219 switch(loc_errno)
3221 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3222 case TRY_AGAIN: return WSATRY_AGAIN;
3223 case NO_RECOVERY: return WSANO_RECOVERY;
3224 case NO_DATA: return WSANO_DATA;
3226 case 0: return 0;
3227 default:
3228 WARN("Unknown h_errno %d!\n", loc_errno);
3229 return WSAEOPNOTSUPP;