Removed some unnecessary #includes and dll dependencies.
[wine/multimedia.git] / dlls / winsock / socket.c
blob41eee910d3ce07ac4b2527efc3a49b4fe3fcbafa
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 "debugtools.h"
92 DEFAULT_DEBUG_CHANNEL(winsock);
94 #define DEBUG_SOCKADDR 0
95 #define dump_sockaddr(a) \
96 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
97 ((struct sockaddr_in *)a)->sin_family, \
98 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
99 ntohs(((struct sockaddr_in *)a)->sin_port))
101 /* ----------------------------------- internal data */
103 /* ws_... struct conversion flags */
105 #define WS_DUP_LINEAR 0x0001
106 #define WS_DUP_NATIVE 0x0000 /* not used anymore */
107 #define WS_DUP_OFFSET 0x0002 /* internal pointers are offsets */
108 #define WS_DUP_SEGPTR 0x0004 /* internal pointers are SEGPTRs */
109 /* by default, internal pointers are linear */
110 typedef struct /* WSAAsyncSelect() control struct */
112 HANDLE service, event, sock;
113 HWND hWnd;
114 UINT uMsg;
115 LONG lEvent;
116 struct _WSINFO *pwsi;
117 } ws_select_info;
119 #define WS_MAX_SOCKETS_PER_PROCESS 128 /* reasonable guess */
120 #define WS_MAX_UDP_DATAGRAM 1024
122 #define WS_ACCEPT_QUEUE 6
124 #define WSI_BLOCKINGCALL 0x00000001 /* per-thread info flags */
125 #define WSI_BLOCKINGHOOK 0x00000002 /* 32-bit callback */
127 #define PROCFS_NETDEV_FILE "/proc/net/dev" /* Points to the file in the /proc fs
128 that lists the network devices.
129 Do we need an #ifdef LINUX for this? */
131 typedef struct _WSINFO
133 DWORD dwThisProcess;
134 struct _WSINFO *lpNextIData;
136 unsigned flags;
137 INT16 num_startup; /* reference counter */
138 INT16 num_async_rq;
139 INT16 last_free; /* entry in the socket table */
140 UINT16 buflen;
141 char* buffer; /* allocated from SEGPTR heap */
142 void *he; /* typecast for Win16/32 ws_hostent */
143 int helen;
144 void *se; /* typecast for Win16/32 ws_servent */
145 int selen;
146 void *pe; /* typecast for Win16/32 ws_protoent */
147 int pelen;
148 char* dbuffer; /* buffer for dummies (32 bytes) */
150 DWORD blocking_hook;
152 volatile HANDLE accept_old[WS_ACCEPT_QUEUE], accept_new[WS_ACCEPT_QUEUE];
153 } WSINFO, *LPWSINFO;
155 /* function prototypes */
156 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag);
157 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag);
158 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag);
160 typedef void WIN_hostent;
161 typedef void WIN_protoent;
162 typedef void WIN_servent;
164 int WSAIOCTL_GetInterfaceCount(void);
165 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
167 UINT16 wsaErrno(void);
168 UINT16 wsaHerrno(void);
170 static HANDLE _WSHeap = 0;
172 #define WS_ALLOC(size) \
173 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
174 #define WS_FREE(ptr) \
175 HeapFree(_WSHeap, 0, (ptr) )
177 static INT _ws_sock_ops[] =
178 { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
179 WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
180 WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER,
181 #ifdef SO_RCVTIMEO
182 WS_SO_RCVTIMEO,
183 #endif
184 0 };
185 static int _px_sock_ops[] =
186 { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
187 SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
188 WS_SO_DONTLINGER, /* no unix equivalent */
189 #ifdef SO_RCVTIMEO
190 SO_RCVTIMEO,
191 #endif
194 static INT _ws_tcp_ops[] = {
195 #ifdef TCP_NODELAY
196 WS_TCP_NODELAY,
197 #endif
200 static int _px_tcp_ops[] = {
201 #ifdef TCP_NODELAY
202 TCP_NODELAY,
203 #endif
207 /* we need a special routine to handle WSA* errors */
208 static inline int sock_server_call( enum request req )
210 unsigned int res = server_call_noerr( req );
211 if (res)
213 /* do not map WSA errors */
214 if ((res < WSABASEERR) || (res >= 0x10000000)) res = RtlNtStatusToDosError(res);
215 SetLastError( res );
217 return res;
220 static int _check_ws(LPWSINFO pwsi, SOCKET s);
221 static char* _check_buffer(LPWSINFO pwsi, int size);
223 static int _get_sock_fd(SOCKET s)
225 struct get_read_fd_request *req = get_req_buffer();
226 int fd;
228 req->handle = s;
229 server_call_fd( REQ_GET_READ_FD, -1, &fd );
230 if (fd == -1)
231 FIXME("handle %d is not a socket (GLE %ld)\n",s,GetLastError());
232 return fd;
235 static void _enable_event(SOCKET s, unsigned int event,
236 unsigned int sstate, unsigned int cstate)
238 struct enable_socket_event_request *req = get_req_buffer();
240 req->handle = s;
241 req->mask = event;
242 req->sstate = sstate;
243 req->cstate = cstate;
244 sock_server_call( REQ_ENABLE_SOCKET_EVENT );
247 static int _is_blocking(SOCKET s)
249 struct get_socket_event_request *req = get_req_buffer();
251 req->handle = s;
252 req->service = FALSE;
253 req->s_event = 0;
254 req->c_event = 0;
255 sock_server_call( REQ_GET_SOCKET_EVENT );
256 return (req->state & WS_FD_NONBLOCKING) == 0;
259 static unsigned int _get_sock_mask(SOCKET s)
261 struct get_socket_event_request *req = get_req_buffer();
263 req->handle = s;
264 req->service = FALSE;
265 req->s_event = 0;
266 req->c_event = 0;
267 sock_server_call( REQ_GET_SOCKET_EVENT );
268 return req->mask;
271 static void _sync_sock_state(SOCKET s)
273 /* do a dummy wineserver request in order to let
274 the wineserver run through its select loop once */
275 (void)_is_blocking(s);
278 static int _get_sock_error(SOCKET s, unsigned int bit)
280 struct get_socket_event_request *req = get_req_buffer();
282 req->handle = s;
283 req->service = FALSE;
284 req->s_event = 0;
285 req->c_event = 0;
286 sock_server_call( REQ_GET_SOCKET_EVENT );
287 return req->errors[bit];
290 static LPWSINFO lpFirstIData = NULL;
292 static LPWSINFO WINSOCK_GetIData(void)
294 DWORD pid = GetCurrentProcessId();
295 LPWSINFO iData;
297 for (iData = lpFirstIData; iData; iData = iData->lpNextIData) {
298 if (iData->dwThisProcess == pid)
299 break;
301 return iData;
304 static BOOL WINSOCK_CreateIData(void)
306 LPWSINFO iData;
308 iData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WSINFO));
309 if (!iData)
310 return FALSE;
311 iData->dwThisProcess = GetCurrentProcessId();
312 iData->lpNextIData = lpFirstIData;
313 lpFirstIData = iData;
314 return TRUE;
317 static void WINSOCK_DeleteIData(void)
319 LPWSINFO iData = WINSOCK_GetIData();
320 LPWSINFO* ppid;
321 if (iData) {
322 for (ppid = &lpFirstIData; *ppid; ppid = &(*ppid)->lpNextIData) {
323 if (*ppid == iData) {
324 *ppid = iData->lpNextIData;
325 break;
329 if( iData->flags & WSI_BLOCKINGCALL )
330 TRACE("\tinside blocking call!\n");
332 /* delete scratch buffers */
334 if( iData->buffer ) SEGPTR_FREE(iData->buffer);
335 if( iData->dbuffer ) SEGPTR_FREE(iData->dbuffer);
337 HeapFree(GetProcessHeap(), 0, iData);
341 /***********************************************************************
342 * WSOCK32_LibMain (WSOCK32.init)
344 BOOL WINAPI WSOCK32_LibMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
346 TRACE("0x%x 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
347 switch (fdwReason) {
348 case DLL_PROCESS_DETACH:
349 WINSOCK_DeleteIData();
350 break;
352 return TRUE;
355 /***********************************************************************
356 * WINSOCK_LibMain (WINSOCK.init)
358 BOOL WINAPI WINSOCK_LibMain(DWORD fdwReason, HINSTANCE hInstDLL, WORD ds,
359 WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
361 TRACE("0x%x 0x%lx\n", hInstDLL, fdwReason);
362 switch (fdwReason) {
363 case DLL_PROCESS_DETACH:
364 WINSOCK_DeleteIData();
365 break;
367 return TRUE;
370 /***********************************************************************
371 * convert_sockopt()
373 * Converts socket flags from Windows format.
375 static void convert_sockopt(INT *level, INT *optname)
377 int i;
378 switch (*level)
380 case WS_SOL_SOCKET:
381 *level = SOL_SOCKET;
382 for(i=0; _ws_sock_ops[i]; i++)
383 if( _ws_sock_ops[i] == *optname ) break;
384 if( _ws_sock_ops[i] ) *optname = _px_sock_ops[i];
385 else FIXME("Unknown SOL_SOCKET optname %d\n", *optname);
386 break;
387 case WS_IPPROTO_TCP:
388 *level = IPPROTO_TCP;
389 for(i=0; _ws_tcp_ops[i]; i++)
390 if ( _ws_tcp_ops[i] == *optname ) break;
391 if( _ws_tcp_ops[i] ) *optname = _px_tcp_ops[i];
392 else FIXME("Unknown IPPROTO_TCP optname %d\n", *optname);
393 break;
397 /* ----------------------------------- Per-thread info (or per-process?) */
399 static int wsi_strtolo(LPWSINFO pwsi, const char* name, const char* opt)
401 /* Stuff a lowercase copy of the string into the local buffer */
403 int i = strlen(name) + 2;
404 char* p = _check_buffer(pwsi, i + ((opt)?strlen(opt):0));
406 if( p )
408 do *p++ = tolower(*name); while(*name++);
409 i = (p - (char*)(pwsi->buffer));
410 if( opt ) do *p++ = tolower(*opt); while(*opt++);
411 return i;
413 return 0;
416 static fd_set* fd_set_import( fd_set* fds, LPWSINFO pwsi, void* wsfds, int* highfd, int lfd[], BOOL b32 )
418 /* translate Winsock fd set into local fd set */
420 if( wsfds )
422 #define wsfds16 ((ws_fd_set16*)wsfds)
423 #define wsfds32 ((ws_fd_set32*)wsfds)
424 int i, count;
426 FD_ZERO(fds);
427 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
429 for( i = 0; i < count; i++ )
431 int s = (b32) ? wsfds32->fd_array[i]
432 : wsfds16->fd_array[i];
433 if( _check_ws(pwsi, s) )
435 int fd = _get_sock_fd(s);
436 lfd[ i ] = fd;
437 if( fd > *highfd ) *highfd = fd;
438 FD_SET(fd, fds);
440 else lfd[ i ] = -1;
442 #undef wsfds32
443 #undef wsfds16
444 return fds;
446 return NULL;
449 inline static int sock_error_p(int s)
451 unsigned int optval, optlen;
453 optlen = sizeof(optval);
454 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
455 if (optval) WARN("\t[%i] error: %d\n", s, optval);
456 return optval != 0;
459 static int fd_set_export( LPWSINFO pwsi, fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
461 int num_err = 0;
463 /* translate local fd set into Winsock fd set, adding
464 * errors to exceptfds (only if app requested it) */
466 if( wsfds )
468 #define wsfds16 ((ws_fd_set16*)wsfds)
469 #define wsfds32 ((ws_fd_set32*)wsfds)
470 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
472 for( i = 0, j = 0; i < count; i++ )
474 if( lfd[i] >= 0 )
476 int fd = lfd[i];
477 if( FD_ISSET(fd, fds) )
479 if ( exceptfds && sock_error_p(fd) )
481 FD_SET(fd, exceptfds);
482 num_err++;
484 else if( b32 )
485 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
486 else
487 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
489 close(fd);
490 lfd[i] = -1;
494 if( b32 ) wsfds32->fd_count = j;
495 else wsfds16->fd_count = j;
497 TRACE("\n");
498 #undef wsfds32
499 #undef wsfds16
501 return num_err;
504 static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
506 if ( wsfds )
508 #define wsfds16 ((ws_fd_set16*)wsfds)
509 #define wsfds32 ((ws_fd_set32*)wsfds)
510 int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
512 for( i = 0; i < count; i++ )
513 if ( lfd[i] >= 0 )
514 close(lfd[i]);
516 TRACE("\n");
517 #undef wsfds32
518 #undef wsfds16
522 static int do_block( int fd, int mask )
524 fd_set fds[3];
525 int i, r;
527 FD_ZERO(&fds[0]);
528 FD_ZERO(&fds[1]);
529 FD_ZERO(&fds[2]);
530 for (i=0; i<3; i++)
531 if (mask & (1<<i))
532 FD_SET(fd, &fds[i]);
533 i = select( fd+1, &fds[0], &fds[1], &fds[2], NULL );
534 if (i <= 0) return -1;
535 r = 0;
536 for (i=0; i<3; i++)
537 if (FD_ISSET(fd, &fds[i]))
538 r |= 1<<i;
539 return r;
542 void* __ws_memalloc( int size )
544 return WS_ALLOC(size);
547 void __ws_memfree(void* ptr)
549 WS_FREE(ptr);
553 /* ----------------------------------- API -----
555 * Init / cleanup / error checking.
558 /***********************************************************************
559 * WSAStartup16() (WINSOCK.115)
561 * Create socket control struct, attach it to the global list and
562 * update a pointer in the task struct.
564 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA lpWSAData)
566 WSADATA WINSOCK_data = { 0x0101, 0x0101,
567 "WINE Sockets 1.1",
568 #ifdef linux
569 "Linux/i386",
570 #elif defined(__NetBSD__)
571 "NetBSD/i386",
572 #elif defined(sunos)
573 "SunOS",
574 #elif defined(__FreeBSD__)
575 "FreeBSD",
576 #elif defined(__OpenBSD__)
577 "OpenBSD/i386",
578 #else
579 "Unknown",
580 #endif
581 WS_MAX_SOCKETS_PER_PROCESS,
582 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
583 LPWSINFO pwsi;
585 TRACE("verReq=%x\n", wVersionRequested);
587 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
588 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
590 if (!lpWSAData) return WSAEINVAL;
592 /* initialize socket heap */
594 if( !_WSHeap )
596 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
597 if( !_WSHeap )
599 ERR("Fatal: failed to create WinSock heap\n");
600 return 0;
603 if( _WSHeap == 0 ) return WSASYSNOTREADY;
605 pwsi = WINSOCK_GetIData();
606 if( pwsi == NULL )
608 WINSOCK_CreateIData();
609 pwsi = WINSOCK_GetIData();
610 if (!pwsi) return WSASYSNOTREADY;
612 pwsi->num_startup++;
614 /* return winsock information */
616 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
618 TRACE("succeeded\n");
619 return 0;
622 /***********************************************************************
623 * WSAStartup() (WS2_32.115)
625 INT WINAPI WSAStartup(UINT wVersionRequested, LPWSADATA lpWSAData)
627 WSADATA WINSOCK_data = { 0x0202, 0x0202,
628 "WINE Sockets 2.0",
629 #ifdef linux
630 "Linux/i386",
631 #elif defined(__NetBSD__)
632 "NetBSD/i386",
633 #elif defined(sunos)
634 "SunOS",
635 #elif defined(__FreeBSD__)
636 "FreeBSD",
637 #elif defined(__OpenBSD__)
638 "OpenBSD/i386",
639 #else
640 "Unknown",
641 #endif
642 WS_MAX_SOCKETS_PER_PROCESS,
643 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
644 LPWSINFO pwsi;
646 TRACE("verReq=%x\n", wVersionRequested);
648 if (LOBYTE(wVersionRequested) < 1)
649 return WSAVERNOTSUPPORTED;
651 if (!lpWSAData) return WSAEINVAL;
653 /* initialize socket heap */
655 if( !_WSHeap )
657 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
658 if( !_WSHeap )
660 ERR("Fatal: failed to create WinSock heap\n");
661 return 0;
664 if( _WSHeap == 0 ) return WSASYSNOTREADY;
666 pwsi = WINSOCK_GetIData();
667 if( pwsi == NULL )
669 WINSOCK_CreateIData();
670 pwsi = WINSOCK_GetIData();
671 if (!pwsi) return WSASYSNOTREADY;
673 pwsi->num_startup++;
675 /* return winsock information */
676 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
678 /* that's the whole of the negotiation for now */
679 lpWSAData->wVersion = wVersionRequested;
681 TRACE("succeeded\n");
682 return 0;
686 /***********************************************************************
687 * WSACleanup() (WINSOCK.116)
689 INT WINAPI WSACleanup(void)
691 LPWSINFO pwsi = WINSOCK_GetIData();
692 if( pwsi ) {
693 if( --pwsi->num_startup > 0 ) return 0;
695 WINSOCK_DeleteIData();
696 return 0;
698 SetLastError(WSANOTINITIALISED);
699 return SOCKET_ERROR;
703 /***********************************************************************
704 * WSAGetLastError() (WSOCK32.111)(WINSOCK.111)
706 INT WINAPI WSAGetLastError(void)
708 return GetLastError();
711 /***********************************************************************
712 * WSASetLastError() (WSOCK32.112)
714 void WINAPI WSASetLastError(INT iError) {
715 SetLastError(iError);
718 /***********************************************************************
719 * WSASetLastError16() (WINSOCK.112)
721 void WINAPI WSASetLastError16(INT16 iError)
723 WSASetLastError(iError);
726 int _check_ws(LPWSINFO pwsi, SOCKET s)
728 if( pwsi )
730 int fd;
731 if( pwsi->flags & WSI_BLOCKINGCALL ) SetLastError(WSAEINPROGRESS);
732 if ( (fd = _get_sock_fd(s)) < 0 ) {
733 SetLastError(WSAENOTSOCK);
734 return 0;
736 /* FIXME: maybe check whether fd is really a socket? */
737 close( fd );
738 return 1;
740 return 0;
743 char* _check_buffer(LPWSINFO pwsi, int size)
745 if( pwsi->buffer && pwsi->buflen >= size ) return pwsi->buffer;
746 else SEGPTR_FREE(pwsi->buffer);
748 pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size));
749 return pwsi->buffer;
752 struct ws_hostent* _check_buffer_he(LPWSINFO pwsi, int size)
754 if( pwsi->he && pwsi->helen >= size ) return pwsi->he;
755 else SEGPTR_FREE(pwsi->he);
757 pwsi->he = SEGPTR_ALLOC((pwsi->helen = size));
758 return pwsi->he;
761 void* _check_buffer_se(LPWSINFO pwsi, int size)
763 if( pwsi->se && pwsi->selen >= size ) return pwsi->se;
764 else SEGPTR_FREE(pwsi->se);
766 pwsi->se = SEGPTR_ALLOC((pwsi->selen = size));
767 return pwsi->se;
770 struct ws_protoent* _check_buffer_pe(LPWSINFO pwsi, int size)
772 if( pwsi->pe && pwsi->pelen >= size ) return pwsi->pe;
773 else SEGPTR_FREE(pwsi->pe);
775 pwsi->pe = SEGPTR_ALLOC((pwsi->pelen = size));
776 return pwsi->pe;
779 /* ----------------------------------- i/o APIs */
781 /***********************************************************************
782 * accept() (WSOCK32.1)
784 static void WSOCK32_async_accept(LPWSINFO pwsi, SOCKET s, SOCKET as)
786 int q;
787 /* queue socket for WSAAsyncSelect */
788 for (q=0; q<WS_ACCEPT_QUEUE; q++)
789 if (InterlockedCompareExchange((PVOID*)&pwsi->accept_old[q], (PVOID)s, (PVOID)0) == (PVOID)0)
790 break;
791 if (q<WS_ACCEPT_QUEUE)
792 pwsi->accept_new[q] = as;
793 else
794 ERR("accept queue too small\n");
795 /* now signal our AsyncSelect handler */
796 _enable_event(s, WS_FD_SERVEVENT, 0, 0);
799 SOCKET WINAPI WSOCK32_accept(SOCKET s, struct sockaddr *addr,
800 INT *addrlen32)
802 LPWSINFO pwsi = WINSOCK_GetIData();
803 #ifdef HAVE_IPX
804 struct ws_sockaddr_ipx* addr2 = (struct ws_sockaddr_ipx *)addr;
805 #endif
806 struct accept_socket_request *req = get_req_buffer();
808 TRACE("(%08x): socket %04x\n",
809 (unsigned)pwsi, (UINT16)s );
810 if( _check_ws(pwsi, s) )
812 if (_is_blocking(s))
814 /* block here */
815 int fd = _get_sock_fd(s);
816 do_block(fd, 5);
817 close(fd);
818 _sync_sock_state(s); /* let wineserver notice connection */
819 /* retrieve any error codes from it */
820 SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
821 /* FIXME: care about the error? */
823 req->lhandle = s;
824 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
825 req->inherit = TRUE;
826 sock_server_call( REQ_ACCEPT_SOCKET );
827 if( req->handle >= 0 )
829 SOCKET as = req->handle;
830 unsigned omask = _get_sock_mask( s );
831 int fd = _get_sock_fd( as );
832 if( getpeername(fd, addr, addrlen32) != -1 )
834 #ifdef HAVE_IPX
835 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
836 addr = (struct sockaddr *)
837 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
838 memcpy(addr, addr2,
839 addrlen32 ? *addrlen32 : sizeof(*addr2));
840 addr2->sipx_family = WS_AF_IPX;
841 addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
842 addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
843 memcpy(addr2->sipx_node,
844 ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
845 free(addr);
847 #endif
848 } else SetLastError(wsaErrno());
849 close(fd);
850 if (omask & WS_FD_SERVEVENT)
851 WSOCK32_async_accept(pwsi, s, as);
852 return as;
855 return INVALID_SOCKET;
858 /***********************************************************************
859 * accept() (WINSOCK.1)
861 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
862 INT16* addrlen16 )
864 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
865 SOCKET retSocket = WSOCK32_accept( s, addr, &addrlen32 );
866 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
867 return (SOCKET16)retSocket;
870 /***********************************************************************
871 * bind() (WSOCK32.2)
873 INT WINAPI WSOCK32_bind(SOCKET s, struct sockaddr *name, INT namelen)
875 LPWSINFO pwsi = WINSOCK_GetIData();
876 #ifdef HAVE_IPX
877 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
878 #endif
880 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
881 (unsigned)pwsi, s, (int) name, namelen);
882 #if DEBUG_SOCKADDR
883 dump_sockaddr(name);
884 #endif
886 if ( _check_ws(pwsi, s) )
888 int fd = _get_sock_fd(s);
889 /* FIXME: what family does this really map to on the Unix side? */
890 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
891 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
892 #ifdef HAVE_IPX
893 else if (name &&
894 ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
896 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
897 memset(name, '\0', sizeof(struct sockaddr_ipx));
898 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
899 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
900 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
901 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
902 name2->sipx_node, IPX_NODE_LEN);
903 namelen = sizeof(struct sockaddr_ipx);
905 #endif
906 if ( namelen >= sizeof(*name) )
908 if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET
909 #ifdef HAVE_IPX
910 || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX
911 #endif
914 if ( bind(fd, name, namelen) < 0 )
916 int loc_errno = errno;
917 WARN("\tfailure - errno = %i\n", errno);
918 errno = loc_errno;
919 switch(errno)
921 case EBADF: SetLastError(WSAENOTSOCK); break;
922 case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break;
923 default: SetLastError(wsaErrno());break;
926 else {
927 #ifdef HAVE_IPX
928 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
929 free(name);
930 #endif
931 close(fd);
932 return 0; /* success */
934 } else SetLastError(WSAEAFNOSUPPORT);
935 } else SetLastError(WSAEFAULT);
936 #ifdef HAVE_IPX
937 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
938 free(name);
939 #endif
940 close(fd);
942 return SOCKET_ERROR;
945 /***********************************************************************
946 * bind() (WINSOCK.2)
948 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
950 return (INT16)WSOCK32_bind( s, name, namelen );
953 /***********************************************************************
954 * closesocket() (WSOCK32.3)
956 INT WINAPI WSOCK32_closesocket(SOCKET s)
958 LPWSINFO pwsi = WINSOCK_GetIData();
960 TRACE("(%08x): socket %08x\n", (unsigned)pwsi, s);
962 if( _check_ws(pwsi, s) )
964 if( CloseHandle(s) )
965 return 0;
967 return SOCKET_ERROR;
970 /***********************************************************************
971 * closesocket() (WINSOCK.3)
973 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
975 return (INT16)WSOCK32_closesocket(s);
978 /***********************************************************************
979 * connect() (WSOCK32.4)
981 INT WINAPI WSOCK32_connect(SOCKET s, struct sockaddr *name, INT namelen)
983 LPWSINFO pwsi = WINSOCK_GetIData();
984 #ifdef HAVE_IPX
985 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
986 #endif
988 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
989 (unsigned)pwsi, s, (int) name, namelen);
990 #if DEBUG_SOCKADDR
991 dump_sockaddr(name);
992 #endif
994 if( _check_ws(pwsi, s) )
996 int fd = _get_sock_fd(s);
997 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
998 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
999 #ifdef HAVE_IPX
1000 else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
1002 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1003 memset(name, '\0', sizeof(struct sockaddr_ipx));
1004 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
1005 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
1006 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
1007 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
1008 name2->sipx_node, IPX_NODE_LEN);
1009 namelen = sizeof(struct sockaddr_ipx);
1011 #endif
1012 if (connect(fd, name, namelen) == 0) {
1013 close(fd);
1014 goto connect_success;
1016 if (errno == EINPROGRESS)
1018 /* tell wineserver that a connection is in progress */
1019 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1020 WS_FD_CONNECT|WS_FD_READ|WS_FD_WRITE,
1021 WS_FD_CONNECTED|WS_FD_LISTENING);
1022 if (_is_blocking(s))
1024 int result;
1025 /* block here */
1026 do_block(fd, 6);
1027 _sync_sock_state(s); /* let wineserver notice connection */
1028 /* retrieve any error codes from it */
1029 result = _get_sock_error(s, FD_CONNECT_BIT);
1030 if (result)
1031 SetLastError(result);
1032 else {
1033 close(fd);
1034 goto connect_success;
1037 else SetLastError(WSAEWOULDBLOCK);
1038 close(fd);
1040 else
1042 SetLastError(wsaErrno());
1043 close(fd);
1046 #ifdef HAVE_IPX
1047 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1048 free(name);
1049 #endif
1050 return SOCKET_ERROR;
1051 connect_success:
1052 #ifdef HAVE_IPX
1053 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
1054 free(name);
1055 #endif
1056 _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE,
1057 WS_FD_CONNECTED|WS_FD_READ|WS_FD_WRITE,
1058 WS_FD_CONNECT|WS_FD_LISTENING);
1059 return 0;
1062 /***********************************************************************
1063 * connect() (WINSOCK.4)
1065 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
1067 return (INT16)WSOCK32_connect( s, name, namelen );
1070 /***********************************************************************
1071 * getpeername() (WSOCK32.5)
1073 INT WINAPI WSOCK32_getpeername(SOCKET s, struct sockaddr *name,
1074 INT *namelen)
1076 LPWSINFO pwsi = WINSOCK_GetIData();
1077 #ifdef HAVE_IPX
1078 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1079 #endif
1081 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1082 (unsigned)pwsi, s, (int) name, *namelen);
1083 if( _check_ws(pwsi, s) )
1085 int fd = _get_sock_fd(s);
1086 if (getpeername(fd, name, namelen) == 0) {
1087 #ifdef HAVE_IPX
1088 if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1089 name = (struct sockaddr *)
1090 malloc(namelen ? *namelen : sizeof(*name2));
1091 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1092 name2->sipx_family = WS_AF_IPX;
1093 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1094 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1095 memcpy(name2->sipx_node,
1096 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1097 free(name);
1099 #endif
1100 close(fd);
1101 return 0;
1103 SetLastError(wsaErrno());
1104 close(fd);
1106 return SOCKET_ERROR;
1109 /***********************************************************************
1110 * getpeername() (WINSOCK.5)
1112 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
1113 INT16 *namelen16)
1115 INT namelen32 = *namelen16;
1116 INT retVal = WSOCK32_getpeername( s, name, &namelen32 );
1118 #if DEBUG_SOCKADDR
1119 dump_sockaddr(name);
1120 #endif
1122 *namelen16 = namelen32;
1123 return (INT16)retVal;
1126 /***********************************************************************
1127 * getsockname() (WSOCK32.6)
1129 INT WINAPI WSOCK32_getsockname(SOCKET s, struct sockaddr *name,
1130 INT *namelen)
1132 LPWSINFO pwsi = WINSOCK_GetIData();
1133 #ifdef HAVE_IPX
1134 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1135 #endif
1137 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1138 (unsigned)pwsi, s, (int) name, (int) *namelen);
1139 if( _check_ws(pwsi, s) )
1141 int fd = _get_sock_fd(s);
1142 if (getsockname(fd, name, namelen) == 0) {
1143 #ifdef HAVE_IPX
1144 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1145 name = (struct sockaddr *)
1146 malloc(namelen ? *namelen : sizeof(*name2));
1147 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1148 name2->sipx_family = WS_AF_IPX;
1149 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1150 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1151 memcpy(name2->sipx_node,
1152 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1153 free(name);
1155 #endif
1156 close(fd);
1157 return 0;
1159 SetLastError(wsaErrno());
1160 close(fd);
1162 return SOCKET_ERROR;
1165 /***********************************************************************
1166 * getsockname() (WINSOCK.6)
1168 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
1169 INT16 *namelen16)
1171 INT retVal;
1173 if( namelen16 )
1175 INT namelen32 = *namelen16;
1176 retVal = WSOCK32_getsockname( s, name, &namelen32 );
1177 *namelen16 = namelen32;
1179 #if DEBUG_SOCKADDR
1180 dump_sockaddr(name);
1181 #endif
1184 else retVal = SOCKET_ERROR;
1185 return (INT16)retVal;
1189 /***********************************************************************
1190 * getsockopt() (WSOCK32.7)
1192 INT WINAPI WSOCK32_getsockopt(SOCKET s, INT level,
1193 INT optname, char *optval, INT *optlen)
1195 LPWSINFO pwsi = WINSOCK_GetIData();
1197 TRACE("(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n",
1198 (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
1199 if( _check_ws(pwsi, s) )
1201 int fd = _get_sock_fd(s);
1202 convert_sockopt(&level, &optname);
1203 if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
1205 close(fd);
1206 return 0;
1208 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1209 close(fd);
1211 return SOCKET_ERROR;
1214 /***********************************************************************
1215 * getsockopt() (WINSOCK.7)
1217 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1218 INT16 optname, char *optval, INT16 *optlen)
1220 INT optlen32;
1221 INT *p = &optlen32;
1222 INT retVal;
1223 if( optlen ) optlen32 = *optlen; else p = NULL;
1224 retVal = WSOCK32_getsockopt( s, (UINT16)level, optname, optval, p );
1225 if( optlen ) *optlen = optlen32;
1226 return (INT16)retVal;
1229 /***********************************************************************
1230 * htonl() (WINSOCK.8)(WSOCK32.8)
1232 u_long WINAPI WINSOCK_htonl(u_long hostlong) { return( htonl(hostlong) ); }
1233 /***********************************************************************
1234 * htons() (WINSOCK.9)(WSOCK32.9)
1236 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
1237 /***********************************************************************
1238 * inet_addr() (WINSOCK.10)(WSOCK32.10)
1240 u_long WINAPI WINSOCK_inet_addr(char *cp) { return( inet_addr(cp) ); }
1241 /***********************************************************************
1242 * ntohl() (WINSOCK.14)(WSOCK32.14)
1244 u_long WINAPI WINSOCK_ntohl(u_long netlong) { return( ntohl(netlong) ); }
1245 /***********************************************************************
1246 * ntohs() (WINSOCK.15)(WSOCK32.15)
1248 u_short WINAPI WINSOCK_ntohs(u_short netshort) { return( ntohs(netshort) ); }
1250 /***********************************************************************
1251 * inet_ntoa() (WINSOCK.11)(WSOCK32.11)
1253 char* WINAPI WSOCK32_inet_ntoa(struct in_addr in)
1255 /* use "buffer for dummies" here because some applications have
1256 * propensity to decode addresses in ws_hostent structure without
1257 * saving them first...
1260 LPWSINFO pwsi = WINSOCK_GetIData();
1262 if( pwsi )
1264 char* s = inet_ntoa(in);
1265 if( s )
1267 if( pwsi->dbuffer == NULL ) {
1268 /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1269 if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(16)) == NULL )
1271 SetLastError(WSAENOBUFS);
1272 return NULL;
1275 strcpy(pwsi->dbuffer, s);
1276 return pwsi->dbuffer;
1278 SetLastError(wsaErrno());
1280 return NULL;
1283 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1285 char* retVal = WSOCK32_inet_ntoa(in);
1286 return retVal ? SEGPTR_GET(retVal) : (SEGPTR)NULL;
1290 /**********************************************************************
1291 * WSAIoctl (WS2_32)
1294 * FIXME: Only SIO_GET_INTERFACE_LIST option implemented.
1296 INT WINAPI WSAIoctl (SOCKET s,
1297 DWORD dwIoControlCode,
1298 LPVOID lpvInBuffer,
1299 DWORD cbInBuffer,
1300 LPVOID lpbOutBuffer,
1301 DWORD cbOutBuffer,
1302 LPDWORD lpcbBytesReturned,
1303 LPWSAOVERLAPPED lpOverlapped,
1304 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1306 LPWSINFO pwsi = WINSOCK_GetIData();
1308 if( _check_ws(pwsi, s) )
1310 int fd = _get_sock_fd(s);
1312 switch( dwIoControlCode )
1314 case SIO_GET_INTERFACE_LIST:
1316 INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1317 int i, numInt;
1318 struct ifreq ifInfo;
1319 char ifName[512];
1322 TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
1324 numInt = WSAIOCTL_GetInterfaceCount();
1325 if (numInt < 0)
1327 ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
1328 close(fd);
1329 WSASetLastError(WSAEINVAL);
1330 return (SOCKET_ERROR);
1333 for (i=0; i<numInt; i++)
1335 if (!WSAIOCTL_GetInterfaceName(i, ifName))
1337 ERR ("Error parsing /proc filesystem!\n");
1338 close(fd);
1339 WSASetLastError(WSAEINVAL);
1340 return (SOCKET_ERROR);
1343 ifInfo.ifr_addr.sa_family = AF_INET;
1345 /* IP Address */
1346 strcpy (ifInfo.ifr_name, ifName);
1347 if (ioctl(fd, SIOCGIFADDR, &ifInfo) < 0)
1349 ERR ("Error obtaining IP address\n");
1350 close(fd);
1351 WSASetLastError(WSAEINVAL);
1352 return (SOCKET_ERROR);
1354 else
1356 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1358 intArray->iiAddress.AddressIn.sin_family = AF_INET;
1359 intArray->iiAddress.AddressIn.sin_port = ipTemp->sin_port;
1360 intArray->iiAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1363 /* Broadcast Address */
1364 strcpy (ifInfo.ifr_name, ifName);
1365 if (ioctl(fd, SIOCGIFBRDADDR, &ifInfo) < 0)
1367 ERR ("Error obtaining Broadcast IP address\n");
1368 close(fd);
1369 WSASetLastError(WSAEINVAL);
1370 return (SOCKET_ERROR);
1372 else
1374 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
1376 intArray->iiBroadcastAddress.AddressIn.sin_family = AF_INET;
1377 intArray->iiBroadcastAddress.AddressIn.sin_port = ipTemp->sin_port;
1378 intArray->iiBroadcastAddress.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1381 /* Subnet Mask */
1382 strcpy (ifInfo.ifr_name, ifName);
1383 if (ioctl(fd, SIOCGIFNETMASK, &ifInfo) < 0)
1385 ERR ("Error obtaining Subnet IP address\n");
1386 close(fd);
1387 WSASetLastError(WSAEINVAL);
1388 return (SOCKET_ERROR);
1390 else
1392 /* Trying to avoid some compile problems across platforms.
1393 (Linux, FreeBSD, Solaris...) */
1394 #ifndef ifr_netmask
1395 #ifndef ifr_addr
1396 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1397 intArray->iiNetmask.AddressIn.sin_port = 0;
1398 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = 0;
1399 ERR ("Unable to determine Netmask on your platform!\n");
1400 #else
1401 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
1403 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1404 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1405 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1406 #endif
1407 #else
1408 struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
1410 intArray->iiNetmask.AddressIn.sin_family = AF_INET;
1411 intArray->iiNetmask.AddressIn.sin_port = ipTemp->sin_port;
1412 intArray->iiNetmask.AddressIn.sin_addr.ws_addr = ipTemp->sin_addr.S_un.S_addr;
1413 #endif
1416 /* Socket Status Flags */
1417 strcpy(ifInfo.ifr_name, ifName);
1418 if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1420 ERR ("Error obtaining status flags for socket!\n");
1421 close(fd);
1422 WSASetLastError(WSAEINVAL);
1423 return (SOCKET_ERROR);
1425 else
1427 /* FIXME - Is this the right flag to use? */
1428 intArray->iiFlags = ifInfo.ifr_flags;
1430 intArray++; /* Prepare for another interface */
1433 /* Calculate the size of the array being returned */
1434 *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
1435 break;
1438 default:
1440 WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
1441 close(fd);
1442 WSASetLastError(WSAEOPNOTSUPP);
1443 return (SOCKET_ERROR);
1447 /* Function executed with no errors */
1448 close(fd);
1449 return (0);
1451 else
1453 WSASetLastError(WSAENOTSOCK);
1454 return (SOCKET_ERROR);
1460 Helper function for WSAIoctl - Get count of the number of interfaces
1461 by parsing /proc filesystem.
1463 int WSAIOCTL_GetInterfaceCount(void)
1465 FILE *procfs;
1466 char buf[512]; /* Size doesn't matter, something big */
1467 int intcnt=0;
1470 /* Open /proc filesystem file for network devices */
1471 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1472 if (!procfs)
1474 /* If we can't open the file, return an error */
1475 return (-1);
1478 /* Omit first two lines, they are only headers */
1479 fgets(buf, sizeof buf, procfs);
1480 fgets(buf, sizeof buf, procfs);
1482 while (fgets(buf, sizeof buf, procfs))
1484 /* Each line in the file represents a network interface */
1485 intcnt++;
1488 fclose(procfs);
1489 return(intcnt);
1494 Helper function for WSAIoctl - Get name of device from interface number
1495 by parsing /proc filesystem.
1497 int WSAIOCTL_GetInterfaceName(int intNumber, char *intName)
1499 FILE *procfs;
1500 char buf[512]; /* Size doesn't matter, something big */
1501 int i;
1503 /* Open /proc filesystem file for network devices */
1504 procfs = fopen(PROCFS_NETDEV_FILE, "r");
1505 if (!procfs)
1507 /* If we can't open the file, return an error */
1508 return (-1);
1511 /* Omit first two lines, they are only headers */
1512 fgets(buf, sizeof(buf), procfs);
1513 fgets(buf, sizeof(buf), procfs);
1515 for (i=0; i<intNumber; i++)
1517 /* Skip the lines that don't interest us. */
1518 fgets(buf, sizeof(buf), procfs);
1520 fgets(buf, sizeof(buf), procfs); /* This is the line we want */
1523 /* Parse out the line, grabbing only the name of the device
1524 to the intName variable
1526 The Line comes in like this: (we only care about the device name)
1527 lo: 21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
1529 i=0;
1530 while (isspace(buf[i])) /* Skip initial space(s) */
1532 i++;
1535 while (buf[i])
1537 if (isspace(buf[i]))
1539 break;
1542 if (buf[i] == ':') /* FIXME: Not sure if this block (alias detection) works properly */
1544 /* This interface could be an alias... */
1545 int hold = i;
1546 char *dotname = intName;
1547 *intName++ = buf[i++];
1549 while (isdigit(buf[i]))
1551 *intName++ = buf[i++];
1554 if (buf[i] != ':')
1556 /* ... It wasn't, so back up */
1557 i = hold;
1558 intName = dotname;
1561 if (buf[i] == '\0')
1563 fclose(procfs);
1564 return(FALSE);
1567 i++;
1568 break;
1571 *intName++ = buf[i++];
1573 *intName++ = '\0';
1575 fclose(procfs);
1576 return(TRUE);
1580 /***********************************************************************
1581 * ioctlsocket() (WSOCK32.12)
1583 INT WINAPI WSOCK32_ioctlsocket(SOCKET s, LONG cmd, ULONG *argp)
1585 LPWSINFO pwsi = WINSOCK_GetIData();
1587 TRACE("(%08x): socket %04x, cmd %08lx, ptr %8x\n",
1588 (unsigned)pwsi, s, cmd, (unsigned) argp);
1589 if( _check_ws(pwsi, s) )
1591 int fd = _get_sock_fd(s);
1592 long newcmd = cmd;
1594 switch( cmd )
1596 case WS_FIONREAD:
1597 newcmd=FIONREAD;
1598 break;
1600 case WS_FIONBIO:
1601 newcmd=FIONBIO;
1602 if( _get_sock_mask(s) )
1604 /* AsyncSelect()'ed sockets are always nonblocking */
1605 if (*argp) {
1606 close(fd);
1607 return 0;
1609 SetLastError(WSAEINVAL);
1610 close(fd);
1611 return SOCKET_ERROR;
1613 close(fd);
1614 if (*argp)
1615 _enable_event(s, 0, WS_FD_NONBLOCKING, 0);
1616 else
1617 _enable_event(s, 0, 0, WS_FD_NONBLOCKING);
1618 return 0;
1620 case WS_SIOCATMARK:
1621 newcmd=SIOCATMARK;
1622 break;
1624 case WS_IOW('f',125,u_long):
1625 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1626 SetLastError(WSAEINVAL);
1627 return SOCKET_ERROR;
1629 default:
1630 /* Netscape tries hard to use bogus ioctl 0x667e */
1631 WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
1633 if( ioctl(fd, newcmd, (char*)argp ) == 0 )
1635 close(fd);
1636 return 0;
1638 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1639 close(fd);
1641 return SOCKET_ERROR;
1644 /***********************************************************************
1645 * ioctlsocket() (WINSOCK.12)
1647 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
1649 return (INT16)WSOCK32_ioctlsocket( s, cmd, argp );
1653 /***********************************************************************
1654 * listen() (WSOCK32.13)
1656 INT WINAPI WSOCK32_listen(SOCKET s, INT backlog)
1658 LPWSINFO pwsi = WINSOCK_GetIData();
1660 TRACE("(%08x): socket %04x, backlog %d\n",
1661 (unsigned)pwsi, s, backlog);
1662 if( _check_ws(pwsi, s) )
1664 int fd = _get_sock_fd(s);
1665 if (listen(fd, backlog) == 0)
1667 close(fd);
1668 _enable_event(s, FD_ACCEPT,
1669 WS_FD_LISTENING,
1670 WS_FD_CONNECT|WS_FD_CONNECTED);
1671 return 0;
1673 SetLastError(wsaErrno());
1675 else SetLastError(WSAENOTSOCK);
1676 return SOCKET_ERROR;
1679 /***********************************************************************
1680 * listen() (WINSOCK.13)
1682 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1684 return (INT16)WSOCK32_listen( s, backlog );
1688 /***********************************************************************
1689 * recv() (WSOCK32.16)
1691 INT WINAPI WSOCK32_recv(SOCKET s, char *buf, INT len, INT flags)
1693 LPWSINFO pwsi = WINSOCK_GetIData();
1695 TRACE("(%08x): socket %04x, buf %8x, len %d, "
1696 "flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1697 len, flags);
1698 if( _check_ws(pwsi, s) )
1700 int fd = _get_sock_fd(s);
1701 INT length;
1703 if (_is_blocking(s))
1705 /* block here */
1706 /* FIXME: OOB and exceptfds? */
1707 do_block(fd, 1);
1709 if ((length = recv(fd, buf, len, flags)) >= 0)
1711 TRACE(" -> %i bytes\n", length);
1713 close(fd);
1714 _enable_event(s, FD_READ, 0, 0);
1715 return length;
1717 SetLastError(wsaErrno());
1718 close(fd);
1720 else SetLastError(WSAENOTSOCK);
1721 WARN(" -> ERROR\n");
1722 return SOCKET_ERROR;
1725 /***********************************************************************
1726 * recv() (WINSOCK.16)
1728 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1730 return (INT16)WSOCK32_recv( s, buf, len, flags );
1734 /***********************************************************************
1735 * recvfrom() (WSOCK32.17)
1737 INT WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, INT flags,
1738 struct sockaddr *from, INT *fromlen32)
1740 LPWSINFO pwsi = WINSOCK_GetIData();
1741 #ifdef HAVE_IPX
1742 struct ws_sockaddr_ipx* from2 = (struct ws_sockaddr_ipx *)from;
1743 #endif
1745 TRACE("(%08x): socket %04x, ptr %08x, "
1746 "len %d, flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1747 len, flags);
1748 #if DEBUG_SOCKADDR
1749 if( from ) dump_sockaddr(from);
1750 else DPRINTF("from = NULL\n");
1751 #endif
1753 if( _check_ws(pwsi, s) )
1755 int fd = _get_sock_fd(s);
1756 int length;
1758 if (_is_blocking(s))
1760 /* block here */
1761 /* FIXME: OOB and exceptfds */
1762 do_block(fd, 1);
1764 if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0)
1766 TRACE(" -> %i bytes\n", length);
1768 #ifdef HAVE_IPX
1769 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1770 from = (struct sockaddr *)
1771 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1772 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1773 from2->sipx_family = WS_AF_IPX;
1774 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1775 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1776 memcpy(from2->sipx_node,
1777 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1778 free(from);
1780 #endif
1781 close(fd);
1782 _enable_event(s, FD_READ, 0, 0);
1783 return (INT16)length;
1785 SetLastError(wsaErrno());
1786 close(fd);
1788 else SetLastError(WSAENOTSOCK);
1789 WARN(" -> ERROR\n");
1790 #ifdef HAVE_IPX
1791 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1792 from = (struct sockaddr *)
1793 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1794 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1795 from2->sipx_family = WS_AF_IPX;
1796 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1797 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1798 memcpy(from2->sipx_node,
1799 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1800 free(from);
1802 #endif
1803 return SOCKET_ERROR;
1806 /***********************************************************************
1807 * recvfrom() (WINSOCK.17)
1809 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1810 struct sockaddr *from, INT16 *fromlen16)
1812 INT fromlen32;
1813 INT *p = &fromlen32;
1814 INT retVal;
1816 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1817 retVal = WSOCK32_recvfrom( s, buf, len, flags, from, p );
1818 if( fromlen16 ) *fromlen16 = fromlen32;
1819 return (INT16)retVal;
1822 /***********************************************************************
1823 * select() (WINSOCK.18)(WSOCK32.18)
1825 static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1826 struct timeval *timeout )
1828 LPWSINFO pwsi = WINSOCK_GetIData();
1830 TRACE("(%08x): read %8x, write %8x, excp %8x\n",
1831 (unsigned) pwsi, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
1833 if( pwsi )
1835 int highfd = 0;
1836 fd_set readfds, writefds, exceptfds;
1837 fd_set *p_read, *p_write, *p_except;
1838 int readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
1840 p_read = fd_set_import(&readfds, pwsi, ws_readfds, &highfd, readfd, b32);
1841 p_write = fd_set_import(&writefds, pwsi, ws_writefds, &highfd, writefd, b32);
1842 p_except = fd_set_import(&exceptfds, pwsi, ws_exceptfds, &highfd, exceptfd, b32);
1844 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
1846 fd_set_export(pwsi, &readfds, p_except, ws_readfds, readfd, b32);
1847 fd_set_export(pwsi, &writefds, p_except, ws_writefds, writefd, b32);
1849 if (p_except && ws_exceptfds)
1851 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1852 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1853 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1855 for (i = j = 0; i < count; i++)
1857 int fd = exceptfd[i];
1858 if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
1860 if( b32 )
1861 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1862 else
1863 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1865 if( fd >= 0 ) close(fd);
1866 exceptfd[i] = -1;
1868 if( b32 )
1869 wsfds32->fd_count = j;
1870 else
1871 wsfds16->fd_count = j;
1872 #undef wsfds32
1873 #undef wsfds16
1875 return highfd;
1877 fd_set_unimport(ws_readfds, readfd, b32);
1878 fd_set_unimport(ws_writefds, writefd, b32);
1879 fd_set_unimport(ws_exceptfds, exceptfd, b32);
1880 if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1881 if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1882 if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1884 if( highfd == 0 ) return 0;
1885 SetLastError(wsaErrno());
1887 return SOCKET_ERROR;
1890 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1891 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1892 struct timeval *timeout)
1894 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1897 INT WINAPI WSOCK32_select(INT nfds, ws_fd_set32 *ws_readfds,
1898 ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
1899 struct timeval *timeout)
1901 /* struct timeval is the same for both 32- and 16-bit code */
1902 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1906 /***********************************************************************
1907 * send() (WSOCK32.19)
1909 INT WINAPI WSOCK32_send(SOCKET s, char *buf, INT len, INT flags)
1911 LPWSINFO pwsi = WINSOCK_GetIData();
1913 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1914 (unsigned)pwsi, s, (unsigned) buf, len, flags);
1915 if( _check_ws(pwsi, s) )
1917 int fd = _get_sock_fd(s);
1918 int length;
1920 if (_is_blocking(s))
1922 /* block here */
1923 /* FIXME: exceptfds */
1924 do_block(fd, 2);
1926 if ((length = send(fd, buf, len, flags)) < 0 )
1928 SetLastError(wsaErrno());
1929 if( GetLastError() == WSAEWOULDBLOCK )
1930 _enable_event(s, FD_WRITE, 0, 0);
1932 else
1934 close(fd);
1935 return (INT16)length;
1937 close(fd);
1939 else SetLastError(WSAENOTSOCK);
1940 return SOCKET_ERROR;
1943 /***********************************************************************
1944 * send() (WINSOCK.19)
1946 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1948 return WSOCK32_send( s, buf, len, flags );
1951 /***********************************************************************
1952 * sendto() (WSOCK32.20)
1954 INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags,
1955 struct sockaddr *to, INT tolen)
1957 LPWSINFO pwsi = WINSOCK_GetIData();
1958 #ifdef HAVE_IPX
1959 struct ws_sockaddr_ipx* to2 = (struct ws_sockaddr_ipx *)to;
1960 #endif
1962 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1963 (unsigned)pwsi, s, (unsigned) buf, len, flags);
1964 if( _check_ws(pwsi, s) )
1966 int fd = _get_sock_fd(s);
1967 INT length;
1969 if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
1970 ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
1971 #ifdef HAVE_IPX
1972 else if (to &&
1973 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
1975 to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1976 memset(to, '\0', sizeof(struct sockaddr_ipx));
1977 ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
1978 ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
1979 ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
1980 memcpy(((struct sockaddr_ipx *)to)->sipx_node,
1981 to2->sipx_node, IPX_NODE_LEN);
1982 tolen = sizeof(struct sockaddr_ipx);
1984 #endif
1985 if (_is_blocking(s))
1987 /* block here */
1988 /* FIXME: exceptfds */
1989 do_block(fd, 2);
1991 if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 )
1993 SetLastError(wsaErrno());
1994 if( GetLastError() == WSAEWOULDBLOCK )
1995 _enable_event(s, FD_WRITE, 0, 0);
1997 else {
1998 #ifdef HAVE_IPX
1999 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
2000 free(to);
2002 #endif
2003 close(fd);
2004 return length;
2006 close(fd);
2008 else SetLastError(WSAENOTSOCK);
2009 #ifdef HAVE_IPX
2010 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
2011 free(to);
2013 #endif
2014 return SOCKET_ERROR;
2017 /***********************************************************************
2018 * sendto() (WINSOCK.20)
2020 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
2021 struct sockaddr *to, INT16 tolen)
2023 return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen );
2026 /***********************************************************************
2027 * setsockopt() (WSOCK32.21)
2029 INT WINAPI WSOCK32_setsockopt(SOCKET16 s, INT level, INT optname,
2030 char *optval, INT optlen)
2032 LPWSINFO pwsi = WINSOCK_GetIData();
2034 TRACE("(%08x): socket %04x, lev %d, opt %d, ptr %08x, len %d\n",
2035 (unsigned)pwsi, s, level, optname, (int) optval, optlen);
2036 if( _check_ws(pwsi, s) )
2038 struct linger linger;
2039 int fd = _get_sock_fd(s);
2040 int woptval;
2042 convert_sockopt(&level, &optname);
2043 if(optname == WS_SO_DONTLINGER) {
2044 linger.l_onoff = *((int*)optval) ? 0: 1;
2045 linger.l_linger = 0;
2046 optname=SO_LINGER;
2047 optval = (char*)&linger;
2048 optlen = sizeof(struct linger);
2049 }else{
2050 if (optname == SO_LINGER && optval) {
2051 /* yes, uses unsigned short in both win16/win32 */
2052 linger.l_onoff = ((UINT16*)optval)[0];
2053 linger.l_linger = ((UINT16*)optval)[1];
2054 /* FIXME: what is documented behavior if SO_LINGER optval
2055 is null?? */
2056 optval = (char*)&linger;
2057 optlen = sizeof(struct linger);
2058 } else if (optlen < sizeof(int)){
2059 woptval= *((INT16 *) optval);
2060 optval= (char*) &woptval;
2061 optlen=sizeof(int);
2064 if (setsockopt(fd, level, optname, optval, optlen) == 0)
2066 close(fd);
2067 return 0;
2069 SetLastError(wsaErrno());
2070 close(fd);
2072 else SetLastError(WSAENOTSOCK);
2073 return SOCKET_ERROR;
2076 /***********************************************************************
2077 * setsockopt() (WINSOCK.21)
2079 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
2080 char *optval, INT16 optlen)
2082 if( !optval ) return SOCKET_ERROR;
2083 return (INT16)WSOCK32_setsockopt( s, (UINT16)level, optname, optval, optlen );
2087 /***********************************************************************
2088 * shutdown() (WSOCK32.22)
2090 INT WINAPI WSOCK32_shutdown(SOCKET s, INT how)
2092 LPWSINFO pwsi = WINSOCK_GetIData();
2094 TRACE("(%08x): socket %04x, how %i\n",
2095 (unsigned)pwsi, s, how );
2096 if( _check_ws(pwsi, s) )
2098 int fd = _get_sock_fd(s);
2099 switch( how )
2101 case 0: /* drop receives */
2102 _enable_event(s, 0, 0, WS_FD_READ);
2103 #ifdef SHUT_RD
2104 how = SHUT_RD;
2105 #endif
2106 break;
2108 case 1: /* drop sends */
2109 _enable_event(s, 0, 0, WS_FD_WRITE);
2110 #ifdef SHUT_WR
2111 how = SHUT_WR;
2112 #endif
2113 break;
2115 case 2: /* drop all */
2116 #ifdef SHUT_RDWR
2117 how = SHUT_RDWR;
2118 #endif
2119 default:
2120 WSAAsyncSelect( s, 0, 0, 0 );
2121 break;
2124 if (shutdown(fd, how) == 0)
2126 if( how > 1 )
2128 _enable_event(s, 0, 0, WS_FD_CONNECTED|WS_FD_LISTENING);
2130 close(fd);
2131 return 0;
2133 SetLastError(wsaErrno());
2134 close(fd);
2136 else SetLastError(WSAENOTSOCK);
2137 return SOCKET_ERROR;
2140 /***********************************************************************
2141 * shutdown() (WINSOCK.22)
2143 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
2145 return (INT16)WSOCK32_shutdown( s, how );
2149 /***********************************************************************
2150 * socket() (WSOCK32.23)
2152 SOCKET WINAPI WSOCK32_socket(INT af, INT type, INT protocol)
2154 LPWSINFO pwsi = WINSOCK_GetIData();
2155 struct create_socket_request *req = get_req_buffer();
2157 TRACE("(%08x): af=%d type=%d protocol=%d\n",
2158 (unsigned)pwsi, af, type, protocol);
2160 if( pwsi )
2162 /* check the socket family */
2163 switch(af)
2165 #ifdef HAVE_IPX
2166 case WS_AF_IPX: af = AF_IPX;
2167 #endif
2168 case AF_INET:
2169 case AF_UNSPEC: break;
2170 default: SetLastError(WSAEAFNOSUPPORT);
2171 return INVALID_SOCKET;
2174 /* check the socket type */
2175 switch(type)
2177 case SOCK_STREAM:
2178 case SOCK_DGRAM:
2179 case SOCK_RAW: break;
2180 default: SetLastError(WSAESOCKTNOSUPPORT);
2181 return INVALID_SOCKET;
2184 /* check the protocol type */
2185 if ( protocol < 0 ) /* don't support negative values */
2186 { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
2188 if ( af == AF_UNSPEC) /* did they not specify the address family? */
2189 switch(protocol)
2191 case IPPROTO_TCP:
2192 if (type == SOCK_STREAM) { af = AF_INET; break; }
2193 case IPPROTO_UDP:
2194 if (type == SOCK_DGRAM) { af = AF_INET; break; }
2195 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
2198 req->family = af;
2199 req->type = type;
2200 req->protocol = protocol;
2201 req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
2202 req->inherit = TRUE;
2203 sock_server_call( REQ_CREATE_SOCKET );
2204 if ( req->handle >= 0)
2206 TRACE("\tcreated %04x\n", req->handle);
2208 return req->handle;
2211 if (GetLastError() == WSAEACCES) /* raw socket denied */
2213 if (type == SOCK_RAW)
2214 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
2215 else
2216 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
2217 SetLastError(WSAESOCKTNOSUPPORT);
2221 WARN("\t\tfailed!\n");
2222 return INVALID_SOCKET;
2225 /***********************************************************************
2226 * socket() (WINSOCK.23)
2228 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
2230 return (SOCKET16)WSOCK32_socket( af, type, protocol );
2234 /* ----------------------------------- DNS services
2236 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
2237 * Also, we have to use wsock32 stubs to convert structures and
2238 * error codes from Unix to WSA, hence there is no direct mapping in
2239 * the relay32/wsock32.spec.
2242 static char* NULL_STRING = "NULL";
2244 /***********************************************************************
2245 * gethostbyaddr() (WINSOCK.51)(WSOCK32.51)
2247 static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
2249 LPWSINFO pwsi = WINSOCK_GetIData();
2251 if( pwsi )
2253 struct hostent* host;
2254 if( (host = gethostbyaddr(addr, len, type)) != NULL )
2255 if( WS_dup_he(pwsi, host, dup_flag) )
2256 return (WIN_hostent*)(pwsi->he);
2257 else
2258 SetLastError(WSAENOBUFS);
2259 else
2260 SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
2262 return NULL;
2265 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
2267 WIN_hostent* retval;
2268 TRACE("ptr %08x, len %d, type %d\n",
2269 (unsigned) addr, len, type);
2270 retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
2271 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2274 WIN_hostent* WINAPI WSOCK32_gethostbyaddr(const char *addr, INT len,
2275 INT type)
2277 TRACE("ptr %08x, len %d, type %d\n",
2278 (unsigned) addr, len, type);
2279 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
2282 /***********************************************************************
2283 * gethostbyname() (WINSOCK.52)(WSOCK32.52)
2285 static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
2287 LPWSINFO pwsi = WINSOCK_GetIData();
2289 if( pwsi )
2291 struct hostent* host;
2292 if( (host = gethostbyname(name)) != NULL )
2293 if( WS_dup_he(pwsi, host, dup_flag) )
2294 return (WIN_hostent*)(pwsi->he);
2295 else SetLastError(WSAENOBUFS);
2296 else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
2298 return NULL;
2301 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
2303 WIN_hostent* retval;
2304 TRACE("%s\n", (name)?name:NULL_STRING);
2305 retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
2306 return (retval)? SEGPTR_GET(retval) : ((SEGPTR)NULL) ;
2309 WIN_hostent* WINAPI WSOCK32_gethostbyname(const char* name)
2311 TRACE("%s\n", (name)?name:NULL_STRING);
2312 return __ws_gethostbyname( name, WS_DUP_LINEAR );
2316 /***********************************************************************
2317 * getprotobyname() (WINSOCK.53)(WSOCK32.53)
2319 static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
2321 LPWSINFO pwsi = WINSOCK_GetIData();
2323 if( pwsi )
2325 struct protoent* proto;
2326 if( (proto = getprotobyname(name)) != NULL )
2327 if( WS_dup_pe(pwsi, proto, dup_flag) )
2328 return (WIN_protoent*)(pwsi->pe);
2329 else SetLastError(WSAENOBUFS);
2330 else {
2331 MESSAGE("protocol %s not found; You might want to add "
2332 "this to /etc/protocols\n", debugstr_a(name) );
2333 SetLastError(WSANO_DATA);
2335 } else SetLastError(WSANOTINITIALISED);
2336 return NULL;
2339 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
2341 WIN_protoent* retval;
2342 TRACE("%s\n", (name)?name:NULL_STRING);
2343 retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
2344 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2347 WIN_protoent* WINAPI WSOCK32_getprotobyname(const char* name)
2349 TRACE("%s\n", (name)?name:NULL_STRING);
2350 return __ws_getprotobyname(name, WS_DUP_LINEAR);
2354 /***********************************************************************
2355 * getprotobynumber() (WINSOCK.54)(WSOCK32.54)
2357 static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
2359 LPWSINFO pwsi = WINSOCK_GetIData();
2361 if( pwsi )
2363 struct protoent* proto;
2364 if( (proto = getprotobynumber(number)) != NULL )
2365 if( WS_dup_pe(pwsi, proto, dup_flag) )
2366 return (WIN_protoent*)(pwsi->pe);
2367 else SetLastError(WSAENOBUFS);
2368 else {
2369 MESSAGE("protocol number %d not found; You might want to add "
2370 "this to /etc/protocols\n", number );
2371 SetLastError(WSANO_DATA);
2373 } else SetLastError(WSANOTINITIALISED);
2374 return NULL;
2377 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
2379 WIN_protoent* retval;
2380 TRACE("%i\n", number);
2381 retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
2382 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2385 WIN_protoent* WINAPI WSOCK32_getprotobynumber(INT number)
2387 TRACE("%i\n", number);
2388 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
2392 /***********************************************************************
2393 * getservbyname() (WINSOCK.55)(WSOCK32.55)
2395 static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
2397 LPWSINFO pwsi = WINSOCK_GetIData();
2399 if( pwsi )
2401 struct servent* serv;
2402 int i = wsi_strtolo( pwsi, name, proto );
2404 if( i ) {
2405 serv = getservbyname(pwsi->buffer,
2406 proto ? (pwsi->buffer + i) : NULL);
2407 if( serv != NULL )
2408 if( WS_dup_se(pwsi, serv, dup_flag) )
2409 return (WIN_servent*)(pwsi->se);
2410 else SetLastError(WSAENOBUFS);
2411 else {
2412 MESSAGE("service %s protocol %s not found; You might want to add "
2413 "this to /etc/services\n", debugstr_a(pwsi->buffer),
2414 proto ? debugstr_a(pwsi->buffer+i):"*");
2415 SetLastError(WSANO_DATA);
2418 else SetLastError(WSAENOBUFS);
2419 } else SetLastError(WSANOTINITIALISED);
2420 return NULL;
2423 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2425 WIN_servent* retval;
2426 TRACE("'%s', '%s'\n",
2427 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2428 retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2429 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2432 WIN_servent* WINAPI WSOCK32_getservbyname(const char *name, const char *proto)
2434 TRACE("'%s', '%s'\n",
2435 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2436 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2440 /***********************************************************************
2441 * getservbyport() (WINSOCK.56)(WSOCK32.56)
2443 static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2445 LPWSINFO pwsi = WINSOCK_GetIData();
2447 if( pwsi )
2449 struct servent* serv;
2450 if (!proto || wsi_strtolo( pwsi, proto, NULL )) {
2451 if( (serv = getservbyport(port, (proto) ? pwsi->buffer : NULL)) != NULL ) {
2452 if( WS_dup_se(pwsi, serv, dup_flag) )
2453 return (WIN_servent*)(pwsi->se);
2454 else SetLastError(WSAENOBUFS);
2456 else {
2457 MESSAGE("service on port %lu protocol %s not found; You might want to add "
2458 "this to /etc/services\n", (unsigned long)ntohl(port),
2459 proto ? debugstr_a(pwsi->buffer) : "*");
2460 SetLastError(WSANO_DATA);
2463 else SetLastError(WSAENOBUFS);
2464 } else SetLastError(WSANOTINITIALISED);
2465 return NULL;
2468 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2470 WIN_servent* retval;
2471 TRACE("%d (i.e. port %d), '%s'\n",
2472 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2473 retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2474 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2477 WIN_servent* WINAPI WSOCK32_getservbyport(INT port, const char *proto)
2479 TRACE("%d (i.e. port %d), '%s'\n",
2480 (int)port, (int)ntohl(port), (proto)?proto:NULL_STRING);
2481 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2485 /***********************************************************************
2486 * gethostname() (WSOCK32.57)
2488 INT WINAPI WSOCK32_gethostname(char *name, INT namelen)
2490 LPWSINFO pwsi = WINSOCK_GetIData();
2492 TRACE("(%08x): name %s, len %d\n",
2493 (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
2494 if( pwsi )
2496 if (gethostname(name, namelen) == 0) return 0;
2497 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2499 return SOCKET_ERROR;
2502 /***********************************************************************
2503 * gethostname() (WINSOCK.57)
2505 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2507 return (INT16)WSOCK32_gethostname(name, namelen);
2511 /* ------------------------------------- Windows sockets extensions -- *
2513 * ------------------------------------------------------------------- */
2515 /***********************************************************************
2516 * WSAEnumNetworkEvents
2518 int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2520 LPWSINFO pwsi = WINSOCK_GetIData();
2521 struct get_socket_event_request *req = get_req_buffer();
2523 TRACE("(%08x): %08x, hEvent %08x, lpEvent %08x\n",
2524 (unsigned)pwsi, s, hEvent, (unsigned)lpEvent );
2525 if( _check_ws(pwsi, s) )
2527 req->handle = s;
2528 req->service = TRUE;
2529 req->s_event = 0;
2530 req->c_event = hEvent;
2531 sock_server_call( REQ_GET_SOCKET_EVENT );
2532 lpEvent->lNetworkEvents = req->pmask;
2533 memcpy(lpEvent->iErrorCode, req->errors, sizeof(lpEvent->iErrorCode));
2534 return 0;
2536 else SetLastError(WSAEINVAL);
2537 return SOCKET_ERROR;
2540 /***********************************************************************
2541 * WSAEventSelect
2543 int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, LONG lEvent)
2545 LPWSINFO pwsi = WINSOCK_GetIData();
2546 struct set_socket_event_request *req = get_req_buffer();
2548 TRACE("(%08x): %08x, hEvent %08x, event %08x\n",
2549 (unsigned)pwsi, s, hEvent, (unsigned)lEvent );
2550 if( _check_ws(pwsi, s) )
2552 req->handle = s;
2553 req->mask = lEvent;
2554 req->event = hEvent;
2555 sock_server_call( REQ_SET_SOCKET_EVENT );
2556 return 0;
2558 else SetLastError(WSAEINVAL);
2559 return SOCKET_ERROR;
2562 /***********************************************************************
2563 * WSAAsyncSelect() (WINSOCK.101)(WSOCK32.101)
2566 VOID CALLBACK WINSOCK_DoAsyncEvent( ULONG_PTR ptr )
2568 ws_select_info *info = (ws_select_info*)ptr;
2569 LPWSINFO pwsi = info->pwsi;
2570 struct get_socket_event_request *req = get_req_buffer();
2571 unsigned int i, pmask, orphan = FALSE;
2573 TRACE("socket %08x, event %08x\n", info->sock, info->event);
2574 SetLastError(0);
2575 req->handle = info->sock;
2576 req->service = TRUE;
2577 req->s_event = info->event; /* <== avoid race conditions */
2578 req->c_event = info->event;
2579 sock_server_call( REQ_GET_SOCKET_EVENT );
2580 if ( (GetLastError() == WSAENOTSOCK) || (GetLastError() == WSAEINVAL) )
2582 /* orphaned event (socket closed or something) */
2583 pmask = WS_FD_SERVEVENT;
2584 orphan = TRUE;
2585 } else
2586 pmask = req->pmask;
2587 /* check for accepted sockets that needs to inherit WSAAsyncSelect */
2588 if (pmask & WS_FD_SERVEVENT) {
2589 int q;
2590 for (q=0; q<WS_ACCEPT_QUEUE; q++)
2591 if (pwsi->accept_old[q] == info->sock) {
2592 /* there's only one service thread per pwsi, no lock necessary */
2593 HANDLE as = pwsi->accept_new[q];
2594 if (as) {
2595 pwsi->accept_new[q] = 0;
2596 pwsi->accept_old[q] = 0;
2597 WSAAsyncSelect(as, info->hWnd, info->uMsg, info->lEvent);
2600 pmask &= ~WS_FD_SERVEVENT;
2602 /* dispatch network events */
2603 for (i=0; i<FD_MAX_EVENTS; i++)
2604 if (pmask & (1<<i)) {
2605 TRACE("post: event bit %d, error %d\n", i, req->errors[i]);
2606 PostMessageA(info->hWnd, info->uMsg, info->sock,
2607 WSAMAKESELECTREPLY(1<<i, req->errors[i]));
2609 /* cleanup */
2610 if (orphan)
2612 TRACE("orphaned event, self-destructing\n");
2613 /* SERVICE_Delete closes the event object */
2614 SERVICE_Delete( info->service );
2615 WS_FREE(info);
2619 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, LONG lEvent)
2621 LPWSINFO pwsi = WINSOCK_GetIData();
2623 TRACE("(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
2624 (unsigned)pwsi, (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2625 if( _check_ws(pwsi, s) )
2627 if( lEvent )
2629 ws_select_info *info = (ws_select_info*)WS_ALLOC(sizeof(ws_select_info));
2630 if( info )
2632 HANDLE hObj = CreateEventA( NULL, TRUE, FALSE, NULL );
2633 INT err;
2635 info->sock = s;
2636 info->event = hObj;
2637 info->hWnd = hWnd;
2638 info->uMsg = uMsg;
2639 info->lEvent = lEvent;
2640 info->pwsi = pwsi;
2641 info->service = SERVICE_AddObject( hObj, WINSOCK_DoAsyncEvent, (ULONG_PTR)info );
2643 err = WSAEventSelect( s, hObj, lEvent | WS_FD_SERVEVENT );
2644 if (err) {
2645 /* SERVICE_Delete closes the event object */
2646 SERVICE_Delete( info->service );
2647 WS_FREE(info);
2648 return err;
2651 return 0; /* success */
2653 else SetLastError(WSAENOBUFS);
2655 else
2657 WSAEventSelect(s, 0, 0);
2658 return 0;
2661 else SetLastError(WSAEINVAL);
2662 return SOCKET_ERROR;
2665 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
2667 return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2670 /***********************************************************************
2671 * WSARecvEx() (WSOCK32.1107)
2673 * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
2674 * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
2675 * into the flags parameter when a partial packet is read. This only applies to
2676 * sockets using the datagram protocol. This method does not seem to be implemented
2677 * correctly by microsoft as the winsock implementation does not set the MSG_PARTIAL
2678 * flag when a fragmented packet arrives.
2680 INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags) {
2681 FIXME("(WSARecvEx) partial packet return value not set \n");
2683 return WSOCK32_recv(s, buf, len, *flags);
2687 /***********************************************************************
2688 * WSARecvEx16() (WINSOCK.1107)
2690 * See description for WSARecvEx()
2692 INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags) {
2693 FIXME("(WSARecvEx16) partial packet return value not set \n");
2695 return WINSOCK_recv16(s, buf, len, *flags);
2699 /***********************************************************************
2700 * WSACreateEvent() (WS2_32.???)
2703 WSAEVENT WINAPI WSACreateEvent(void)
2705 /* Create a manual-reset event, with initial state: unsignealed */
2706 TRACE("\n");
2708 return CreateEventA(NULL, TRUE, FALSE, NULL);
2711 /***********************************************************************
2712 * WSACloseEvent() (WS2_32.???)
2715 BOOL WINAPI WSACloseEvent(WSAEVENT event)
2717 TRACE ("event=0x%x\n", event);
2719 return CloseHandle(event);
2722 /***********************************************************************
2723 * WSASocketA() (WS2_32.???)
2726 SOCKET WINAPI WSASocketA(int af, int type, int protocol,
2727 LPWSAPROTOCOL_INFOA lpProtocolInfo,
2728 GROUP g, DWORD dwFlags)
2731 FIXME: The "advanced" parameters of WSASocketA (lpProtocolInfo,
2732 g, dwFlags) are ignored.
2735 TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
2736 af, type, protocol, lpProtocolInfo, g, dwFlags );
2738 return ( WSOCK32_socket (af, type, protocol) );
2742 /***********************************************************************
2743 * __WSAFDIsSet() (WINSOCK.151)
2745 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2747 int i = set->fd_count;
2749 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2751 while (i--)
2752 if (set->fd_array[i] == s) return 1;
2753 return 0;
2756 /***********************************************************************
2757 * __WSAFDIsSet() (WSOCK32.151)
2759 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2761 int i = set->fd_count;
2763 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2765 while (i--)
2766 if (set->fd_array[i] == s) return 1;
2767 return 0;
2770 /***********************************************************************
2771 * WSAIsBlocking() (WINSOCK.114)(WSOCK32.114)
2773 BOOL WINAPI WSAIsBlocking(void)
2775 /* By default WinSock should set all its sockets to non-blocking mode
2776 * and poll in PeekMessage loop when processing "blocking" ones. This
2777 * function is supposed to tell if the program is in this loop. Our
2778 * blocking calls are truly blocking so we always return FALSE.
2780 * Note: It is allowed to call this function without prior WSAStartup().
2783 TRACE("\n");
2784 return FALSE;
2787 /***********************************************************************
2788 * WSACancelBlockingCall() (WINSOCK.113)(WSOCK32.113)
2790 INT WINAPI WSACancelBlockingCall(void)
2792 LPWSINFO pwsi = WINSOCK_GetIData();
2794 TRACE("(%08x)\n", (unsigned)pwsi);
2796 if( pwsi ) return 0;
2797 return SOCKET_ERROR;
2801 /***********************************************************************
2802 * WSASetBlockingHook16() (WINSOCK.109)
2804 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2806 FARPROC16 prev;
2807 LPWSINFO pwsi = WINSOCK_GetIData();
2809 TRACE("(%08x): hook %08x\n",
2810 (unsigned)pwsi, (unsigned) lpBlockFunc);
2811 if( pwsi )
2813 prev = (FARPROC16)pwsi->blocking_hook;
2814 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2815 pwsi->flags &= ~WSI_BLOCKINGHOOK;
2816 return prev;
2818 return 0;
2822 /***********************************************************************
2823 * WSASetBlockingHook()
2825 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2827 FARPROC prev;
2828 LPWSINFO pwsi = WINSOCK_GetIData();
2830 TRACE("(%08x): hook %08x\n",
2831 (unsigned)pwsi, (unsigned) lpBlockFunc);
2832 if( pwsi ) {
2833 prev = (FARPROC)pwsi->blocking_hook;
2834 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2835 pwsi->flags |= WSI_BLOCKINGHOOK;
2836 return prev;
2838 return NULL;
2842 /***********************************************************************
2843 * WSAUnhookBlockingHook16() (WINSOCK.110)
2845 INT16 WINAPI WSAUnhookBlockingHook16(void)
2847 LPWSINFO pwsi = WINSOCK_GetIData();
2849 TRACE("(%08x)\n", (unsigned)pwsi);
2850 if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
2851 return SOCKET_ERROR;
2855 /***********************************************************************
2856 * WSAUnhookBlockingHook()
2858 INT WINAPI WSAUnhookBlockingHook(void)
2860 LPWSINFO pwsi = WINSOCK_GetIData();
2862 TRACE("(%08x)\n", (unsigned)pwsi);
2863 if( pwsi )
2865 pwsi->blocking_hook = 0;
2866 pwsi->flags &= ~WSI_BLOCKINGHOOK;
2867 return 0;
2869 return SOCKET_ERROR;
2873 /* ----------------------------------- end of API stuff */
2875 /* ----------------------------------- helper functions -
2877 * TODO: Merge WS_dup_..() stuff into one function that
2878 * would operate with a generic structure containing internal
2879 * pointers (via a template of some kind).
2882 static int list_size(char** l, int item_size)
2884 int i,j = 0;
2885 if(l)
2886 { for(i=0;l[i];i++)
2887 j += (item_size) ? item_size : strlen(l[i]) + 1;
2888 j += (i + 1) * sizeof(char*); }
2889 return j;
2892 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2894 /* base is either either equal to ref or 0 or SEGPTR */
2896 char* p = ref;
2897 char** l_to = (char**)ref;
2898 int i,j,k;
2900 for(j=0;l_src[j];j++) ;
2901 p += (j + 1) * sizeof(char*);
2902 for(i=0;i<j;i++)
2903 { l_to[i] = base + (p - ref);
2904 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2905 memcpy(p, l_src[i], k); p += k; }
2906 l_to[i] = NULL;
2907 return (p - ref);
2910 /* ----- hostent */
2912 static int hostent_size(struct hostent* p_he)
2914 int size = 0;
2915 if( p_he )
2916 { size = sizeof(struct hostent);
2917 size += strlen(p_he->h_name) + 1;
2918 size += list_size(p_he->h_aliases, 0);
2919 size += list_size(p_he->h_addr_list, p_he->h_length ); }
2920 return size;
2923 /* duplicate hostent entry
2924 * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
2925 * Dito for protoent and servent.
2927 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
2929 /* Convert hostent structure into ws_hostent so that the data fits
2930 * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or
2931 * relative to pwsi->buffer depending on "flag" value. Returns size
2932 * of the data copied (also in the pwsi->buflen).
2935 int size = hostent_size(p_he);
2936 if( size )
2938 char *p_name,*p_aliases,*p_addr,*p_base,*p;
2939 char *p_to;
2940 struct ws_hostent16 *p_to16;
2941 struct ws_hostent32 *p_to32;
2943 _check_buffer_he(pwsi, size);
2944 p_to = (char *)pwsi->he;
2945 p_to16 = (struct ws_hostent16*)pwsi->he;
2946 p_to32 = (struct ws_hostent32*)pwsi->he;
2948 p = p_to;
2949 p_base = (flag & WS_DUP_OFFSET) ? NULL
2950 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2951 p += (flag & WS_DUP_SEGPTR) ?
2952 sizeof(struct ws_hostent16) : sizeof(struct ws_hostent32);
2953 p_name = p;
2954 strcpy(p, p_he->h_name); p += strlen(p) + 1;
2955 p_aliases = p;
2956 p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
2957 p_addr = p;
2958 list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
2960 if (flag & WS_DUP_SEGPTR) /* Win16 */
2962 p_to16->h_addrtype = (INT16)p_he->h_addrtype;
2963 p_to16->h_length = (INT16)p_he->h_length;
2964 p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
2965 p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
2966 p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
2967 size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
2969 else /* Win32 */
2971 p_to32->h_addrtype = p_he->h_addrtype;
2972 p_to32->h_length = p_he->h_length;
2973 p_to32->h_name = (p_base + (p_name - p_to));
2974 p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
2975 p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
2976 size += (sizeof(struct ws_hostent32) - sizeof(struct hostent));
2979 return size;
2982 /* ----- protoent */
2984 static int protoent_size(struct protoent* p_pe)
2986 int size = 0;
2987 if( p_pe )
2988 { size = sizeof(struct protoent);
2989 size += strlen(p_pe->p_name) + 1;
2990 size += list_size(p_pe->p_aliases, 0); }
2991 return size;
2994 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
2996 int size = protoent_size(p_pe);
2997 if( size )
2999 char *p_to;
3000 struct ws_protoent16 *p_to16;
3001 struct ws_protoent32 *p_to32;
3002 char *p_name,*p_aliases,*p_base,*p;
3004 _check_buffer_pe(pwsi, size);
3005 p_to = (char *)pwsi->pe;
3006 p_to16 = (struct ws_protoent16*)pwsi->pe;
3007 p_to32 = (struct ws_protoent32*)pwsi->pe;
3008 p = p_to;
3009 p_base = (flag & WS_DUP_OFFSET) ? NULL
3010 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3011 p += (flag & WS_DUP_SEGPTR) ?
3012 sizeof(struct ws_protoent16) : sizeof(struct ws_protoent32);
3013 p_name = p;
3014 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
3015 p_aliases = p;
3016 list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
3018 if (flag & WS_DUP_SEGPTR) /* Win16 */
3020 p_to16->p_proto = (INT16)p_pe->p_proto;
3021 p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
3022 p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
3023 size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
3025 else /* Win32 */
3027 p_to32->p_proto = p_pe->p_proto;
3028 p_to32->p_name = (p_base) + (p_name - p_to);
3029 p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
3030 size += (sizeof(struct ws_protoent32) - sizeof(struct protoent));
3033 return size;
3036 /* ----- servent */
3038 static int servent_size(struct servent* p_se)
3040 int size = 0;
3041 if( p_se )
3042 { size += sizeof(struct servent);
3043 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
3044 size += list_size(p_se->s_aliases, 0); }
3045 return size;
3048 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
3050 int size = servent_size(p_se);
3051 if( size )
3053 char *p_name,*p_aliases,*p_proto,*p_base,*p;
3054 char *p_to;
3055 struct ws_servent16 *p_to16;
3056 struct ws_servent32 *p_to32;
3058 _check_buffer_se(pwsi, size);
3059 p_to = (char *)pwsi->se;
3060 p_to16 = (struct ws_servent16*)pwsi->se;
3061 p_to32 = (struct ws_servent32*)pwsi->se;
3062 p = p_to;
3063 p_base = (flag & WS_DUP_OFFSET) ? NULL
3064 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
3065 p += (flag & WS_DUP_SEGPTR) ?
3066 sizeof(struct ws_servent16) : sizeof(struct ws_servent32);
3067 p_name = p;
3068 strcpy(p, p_se->s_name); p += strlen(p) + 1;
3069 p_proto = p;
3070 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
3071 p_aliases = p;
3072 list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
3074 if (flag & WS_DUP_SEGPTR) /* Win16 */
3076 p_to16->s_port = (INT16)p_se->s_port;
3077 p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
3078 p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
3079 p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
3080 size += (sizeof(struct ws_servent16) - sizeof(struct servent));
3082 else /* Win32 */
3084 p_to32->s_port = p_se->s_port;
3085 p_to32->s_name = (p_base + (p_name - p_to));
3086 p_to32->s_proto = (p_base + (p_proto - p_to));
3087 p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
3088 size += (sizeof(struct ws_servent32) - sizeof(struct servent));
3091 return size;
3094 /* ----------------------------------- error handling */
3096 UINT16 wsaErrno(void)
3098 int loc_errno = errno;
3099 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3101 switch(loc_errno)
3103 case EINTR: return WSAEINTR;
3104 case EBADF: return WSAEBADF;
3105 case EPERM:
3106 case EACCES: return WSAEACCES;
3107 case EFAULT: return WSAEFAULT;
3108 case EINVAL: return WSAEINVAL;
3109 case EMFILE: return WSAEMFILE;
3110 case EWOULDBLOCK: return WSAEWOULDBLOCK;
3111 case EINPROGRESS: return WSAEINPROGRESS;
3112 case EALREADY: return WSAEALREADY;
3113 case ENOTSOCK: return WSAENOTSOCK;
3114 case EDESTADDRREQ: return WSAEDESTADDRREQ;
3115 case EMSGSIZE: return WSAEMSGSIZE;
3116 case EPROTOTYPE: return WSAEPROTOTYPE;
3117 case ENOPROTOOPT: return WSAENOPROTOOPT;
3118 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
3119 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
3120 case EOPNOTSUPP: return WSAEOPNOTSUPP;
3121 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
3122 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
3123 case EADDRINUSE: return WSAEADDRINUSE;
3124 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
3125 case ENETDOWN: return WSAENETDOWN;
3126 case ENETUNREACH: return WSAENETUNREACH;
3127 case ENETRESET: return WSAENETRESET;
3128 case ECONNABORTED: return WSAECONNABORTED;
3129 case EPIPE:
3130 case ECONNRESET: return WSAECONNRESET;
3131 case ENOBUFS: return WSAENOBUFS;
3132 case EISCONN: return WSAEISCONN;
3133 case ENOTCONN: return WSAENOTCONN;
3134 case ESHUTDOWN: return WSAESHUTDOWN;
3135 case ETOOMANYREFS: return WSAETOOMANYREFS;
3136 case ETIMEDOUT: return WSAETIMEDOUT;
3137 case ECONNREFUSED: return WSAECONNREFUSED;
3138 case ELOOP: return WSAELOOP;
3139 case ENAMETOOLONG: return WSAENAMETOOLONG;
3140 case EHOSTDOWN: return WSAEHOSTDOWN;
3141 case EHOSTUNREACH: return WSAEHOSTUNREACH;
3142 case ENOTEMPTY: return WSAENOTEMPTY;
3143 #ifdef EPROCLIM
3144 case EPROCLIM: return WSAEPROCLIM;
3145 #endif
3146 #ifdef EUSERS
3147 case EUSERS: return WSAEUSERS;
3148 #endif
3149 #ifdef EDQUOT
3150 case EDQUOT: return WSAEDQUOT;
3151 #endif
3152 #ifdef ESTALE
3153 case ESTALE: return WSAESTALE;
3154 #endif
3155 #ifdef EREMOTE
3156 case EREMOTE: return WSAEREMOTE;
3157 #endif
3159 /* just in case we ever get here and there are no problems */
3160 case 0: return 0;
3161 default:
3162 WARN("Unknown errno %d!\n", loc_errno);
3163 return WSAEOPNOTSUPP;
3167 UINT16 wsaHerrno(void)
3169 int loc_errno = h_errno;
3171 WARN("h_errno %d.\n", loc_errno);
3173 switch(loc_errno)
3175 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
3176 case TRY_AGAIN: return WSATRY_AGAIN;
3177 case NO_RECOVERY: return WSANO_RECOVERY;
3178 case NO_DATA: return WSANO_DATA;
3180 case 0: return 0;
3181 default:
3182 WARN("Unknown h_errno %d!\n", loc_errno);
3183 return WSAEOPNOTSUPP;