For large font sizes call XLoadQueryFont with a 100 pixel high font
[wine/wine-kai.git] / misc / winsock.c
blobb7d016b7452fe95adf3ca6eacb4556b509a5565c
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).
13 #include "config.h"
15 #include <string.h>
16 #include <sys/types.h>
17 #include <sys/ipc.h>
18 #include <sys/ioctl.h>
19 #ifdef HAVE_SYS_FILIO_H
20 # include <sys/filio.h>
21 #endif
22 #if defined(__svr4__) || defined(__sun)
23 #include <sys/ioccom.h>
24 #include <sys/sockio.h>
25 #endif
27 #if defined(__EMX__)
28 # include <sys/so_ioctl.h>
29 #endif
31 #ifdef HAVE_SYS_PARAM_H
32 # include <sys/param.h>
33 #endif
35 #include <sys/msg.h>
36 #include <sys/wait.h>
37 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <netinet/tcp.h>
40 #include <arpa/inet.h>
41 #include <ctype.h>
42 #include <fcntl.h>
43 #include <errno.h>
44 #ifdef HAVE_SYS_ERRNO_H
45 #include <sys/errno.h>
46 #endif
47 #include <netdb.h>
48 #include <unistd.h>
49 #include <stdlib.h>
50 #ifdef HAVE_ARPA_NAMESER_H
51 # include <arpa/nameser.h>
52 #endif
53 #ifdef HAVE_RESOLV_H
54 # include <resolv.h>
55 #endif
57 #include "wine/winbase16.h"
58 #include "winsock.h"
59 #include "winnt.h"
60 #include "heap.h"
61 #include "task.h"
62 #include "message.h"
63 #include "miscemu.h"
64 #include "debugtools.h"
66 DEFAULT_DEBUG_CHANNEL(winsock)
68 #define DEBUG_SOCKADDR 0
69 #define dump_sockaddr(a) \
70 DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
71 ((struct sockaddr_in *)a)->sin_family, \
72 inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
73 ntohs(((struct sockaddr_in *)a)->sin_port))
75 /* ----------------------------------- internal data */
77 static HANDLE _WSHeap = 0;
78 static unsigned char* _ws_stub = NULL;
79 static LPWSINFO _wsi_list = NULL;
81 #define WS_ALLOC(size) \
82 HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
83 #define WS_FREE(ptr) \
84 HeapFree(_WSHeap, 0, (ptr) )
86 #define WS_PTR2HANDLE(ptr) \
87 ((short)((int)(ptr) - (int)_ws_stub))
88 #define WS_HANDLE2PTR(handle) \
89 ((unsigned)((int)_ws_stub + (int)(handle)))
91 #define WSI_CHECK_RANGE(pwsi, pws) \
92 ( ((unsigned)(pws) > (unsigned)(pwsi)) && \
93 ((unsigned)(pws) < ((unsigned)(pwsi) + sizeof(WSINFO))) )
95 static INT _ws_sock_ops[] =
96 { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
97 WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
98 WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER,
99 #ifdef SO_RCVTIMEO
100 WS_SO_RCVTIMEO,
101 #endif
102 0 };
103 static int _px_sock_ops[] =
104 { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
105 SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
106 SO_LINGER,
107 #ifdef SO_RCVTIMEO
108 SO_RCVTIMEO,
109 #endif
112 static INT _ws_tcp_ops[] = {
113 #ifdef TCP_NODELAY
114 WS_TCP_NODELAY,
115 #endif
118 static int _px_tcp_ops[] = {
119 #ifdef TCP_NODELAY
120 TCP_NODELAY,
121 #endif
125 static int _check_ws(LPWSINFO pwsi, ws_socket* pws);
126 static char* _check_buffer(LPWSINFO pwsi, int size);
128 /* ----------------------------------- non-blocking I/O */
130 static int WINSOCK_unblock_io(int fd, int noblock)
132 int fd_flags;
134 fd_flags = fcntl(fd, F_GETFL, 0);
135 if (fcntl(fd, F_SETFL, (noblock)? fd_flags | O_NONBLOCK
136 : fd_flags & ~O_NONBLOCK ) != -1) return 0;
137 return -1;
140 /***********************************************************************
141 * convert_sockopt()
143 * Converts socket flags from Windows format.
145 static void convert_sockopt(INT *level, INT *optname)
147 int i;
148 switch (*level)
150 case WS_SOL_SOCKET:
151 *level = SOL_SOCKET;
152 for(i=0; _ws_sock_ops[i]; i++)
153 if( _ws_sock_ops[i] == *optname ) break;
154 if( _ws_sock_ops[i] ) *optname = _px_sock_ops[i];
155 else FIXME("Unknown SOL_SOCKET optname %d\n", *optname);
156 break;
157 case WS_IPPROTO_TCP:
158 *level = IPPROTO_TCP;
159 for(i=0; _ws_tcp_ops[i]; i++)
160 if ( _ws_tcp_ops[i] == *optname ) break;
161 if( _ws_tcp_ops[i] ) *optname = _px_tcp_ops[i];
162 else FIXME("Unknown IPPROTO_TCP optname %d\n", *optname);
163 break;
167 /* ----------------------------------- Per-thread info (or per-process?) */
169 static LPWSINFO wsi_find(HTASK16 hTask)
171 TDB* pTask = (TDB*)GlobalLock16(hTask);
172 if( pTask )
174 if( pTask->pwsi ) return pTask->pwsi;
175 else
177 LPWSINFO pwsi = _wsi_list;
178 while( pwsi && pwsi->tid != hTask ) pwsi = pwsi->next;
179 if( pwsi )
180 WARN("(pwsi=0x%08x,task=0x%04x):Loose wsi struct! \n",
181 (unsigned)pwsi, hTask );
182 return pwsi;
185 return NULL;
188 static ws_socket* wsi_alloc_socket(LPWSINFO pwsi, int fd)
190 /* Initialize a new entry in the socket table */
192 if( pwsi->last_free >= 0 )
194 int i = pwsi->last_free;
196 pwsi->last_free = pwsi->sock[i].flags; /* free list */
197 pwsi->sock[i].fd = fd;
198 pwsi->sock[i].flags = 0;
199 return &pwsi->sock[i];
201 return NULL;
204 static int wsi_strtolo(LPWSINFO pwsi, const char* name, const char* opt)
206 /* Stuff a lowercase copy of the string into the local buffer */
208 int i = strlen(name) + 2;
209 char* p = _check_buffer(pwsi, i + ((opt)?strlen(opt):0));
211 if( p )
213 do *p++ = tolower(*name); while(*name++);
214 i = (p - (char*)(pwsi->buffer));
215 if( opt ) do *p++ = tolower(*opt); while(*opt++);
216 return i;
218 return 0;
221 static fd_set* fd_set_import( fd_set* fds, LPWSINFO pwsi, void* wsfds, int* highfd, BOOL b32 )
223 /* translate Winsock fd set into local fd set */
225 if( wsfds )
227 #define wsfds16 ((ws_fd_set16*)wsfds)
228 #define wsfds32 ((ws_fd_set32*)wsfds)
229 ws_socket* pws;
230 int i, count;
232 FD_ZERO(fds);
233 count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
235 for( i = 0; i < count; i++ )
237 pws = (b32) ? (ws_socket*)WS_HANDLE2PTR(wsfds32->fd_array[i])
238 : (ws_socket*)WS_HANDLE2PTR(wsfds16->fd_array[i]);
239 if( _check_ws(pwsi, pws) )
241 if( pws->fd > *highfd ) *highfd = pws->fd;
242 FD_SET(pws->fd, fds);
245 #undef wsfds32
246 #undef wsfds16
247 return fds;
249 return NULL;
252 inline static int sock_error_p(int s)
254 unsigned int optval, optlen;
256 optlen = sizeof(optval);
257 getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
258 if (optval) WARN("\t[%i] error: %d\n", s, optval);
259 return optval != 0;
262 static int fd_set_export( LPWSINFO pwsi, fd_set* fds, fd_set* exceptfds, void* wsfds, BOOL b32 )
264 int num_err = 0;
266 /* translate local fd set into Winsock fd set, adding
267 * errors to exceptfds (only if app requested it) */
269 if( wsfds )
271 #define wsfds16 ((ws_fd_set16*)wsfds)
272 #define wsfds32 ((ws_fd_set32*)wsfds)
273 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
275 for( i = 0, j = 0; i < count; i++ )
277 ws_socket *pws = (b32) ? (ws_socket*)WS_HANDLE2PTR(wsfds32->fd_array[i])
278 : (ws_socket*)WS_HANDLE2PTR(wsfds16->fd_array[i]);
279 if( _check_ws(pwsi, pws) )
281 int fd = pws->fd;
283 if( FD_ISSET(fd, fds) )
285 if ( exceptfds && sock_error_p(fd) )
287 FD_SET(fd, exceptfds);
288 num_err++;
290 else if( b32 )
291 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
292 else
293 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
298 if( b32 ) wsfds32->fd_count = j;
299 else wsfds16->fd_count = j;
301 TRACE("\n");
302 #undef wsfds32
303 #undef wsfds16
305 return num_err;
308 HANDLE16 __ws_gethandle( void* ptr )
310 return (HANDLE16)WS_PTR2HANDLE(ptr);
313 void* __ws_memalloc( int size )
315 return WS_ALLOC(size);
318 void __ws_memfree(void* ptr)
320 WS_FREE(ptr);
324 * Event handling helper routines
326 * FIXME: This is all a hack; winsock event handling should be moved
327 * to the services thread ...
330 #define EVENT_IO_READ 0
331 #define EVENT_IO_WRITE 1
332 #define EVENT_IO_EXCEPT 2
334 static fd_set __winsock_io_set[3];
335 static int __winsock_max_fd = 0;
336 static int __wakeup_pipe[2];
338 static CRITICAL_SECTION __winsock_crst;
339 static HANDLE __winsock_thread = INVALID_HANDLE_VALUE;
341 BOOL WINSOCK_HandleIO( int* max_fd, int num_pending,
342 fd_set pending_set[3], fd_set event_set[3] );
344 /***********************************************************************
345 * WINSOCK_Init
347 * Initialize network IO.
349 BOOL WINSOCK_Init(void)
351 int i;
352 for( i = 0; i < 3; i++ )
353 FD_ZERO( __winsock_io_set + i );
355 /* pipe used to wake up the winsock thread */
356 pipe(__wakeup_pipe);
358 /* make the pipe non-blocking */
359 fcntl(__wakeup_pipe[0], F_SETFL, O_NONBLOCK);
360 fcntl(__wakeup_pipe[1], F_SETFL, O_NONBLOCK);
362 FD_SET( __wakeup_pipe[0], &__winsock_io_set[EVENT_IO_READ] );
363 __winsock_max_fd = __wakeup_pipe[0];
364 __winsock_max_fd++;
366 /* Inititalize critical section */
367 InitializeCriticalSection( &__winsock_crst );
368 MakeCriticalSectionGlobal( &__winsock_crst );
370 return TRUE;
373 /***********************************************************************
374 * WINSOCK_Shutdown
376 void WINSOCK_Shutdown()
378 /* Called on exit(), has to remove all outstanding async DNS processes. */
380 if ( __winsock_thread != INVALID_HANDLE_VALUE )
382 TerminateThread( __winsock_thread, 0 );
383 __winsock_thread = INVALID_HANDLE_VALUE;
387 /***********************************************************************
388 * WINSOCK_Thread
390 static DWORD CALLBACK WINSOCK_Thread( LPVOID arg )
392 while ( TRUE )
394 int num_pending, max_fd;
395 fd_set io_set[3];
397 EnterCriticalSection( &__winsock_crst );
398 memcpy( io_set, __winsock_io_set, sizeof(io_set) );
399 max_fd = __winsock_max_fd;
400 LeaveCriticalSection( &__winsock_crst );
402 num_pending = select( max_fd, &io_set[EVENT_IO_READ],
403 &io_set[EVENT_IO_WRITE],
404 &io_set[EVENT_IO_EXCEPT], NULL );
406 if ( num_pending == -1 )
408 /* Error - signal, invalid arguments, out of memory */
409 continue;
412 /* Flush the wake-up pipe */
413 if ( FD_ISSET( __wakeup_pipe[0], &io_set[EVENT_IO_READ] ) )
415 char tmpBuf[10];
416 ssize_t ret;
418 while ( (ret = read(__wakeup_pipe[0], &tmpBuf, 10)) == 10 );
419 num_pending--;
422 /* Handle actual IO */
423 if ( num_pending > 0 )
425 EnterCriticalSection( &__winsock_crst );
426 WINSOCK_HandleIO( &__winsock_max_fd, num_pending, io_set, __winsock_io_set );
427 LeaveCriticalSection( &__winsock_crst );
432 /***********************************************************************
433 * WINSOCK_WakeUp
435 * Wake up the winsock thread.
437 static void WINSOCK_WakeUp(void)
439 if ( __winsock_thread == INVALID_HANDLE_VALUE )
441 __winsock_thread = CreateThread( NULL, 0, WINSOCK_Thread, NULL, 0, NULL );
442 __winsock_thread = ConvertToGlobalHandle( __winsock_thread );
445 if (write (__wakeup_pipe[1], "A", 1) != 1)
446 ERR("unable to write in wakeup_pipe\n");
449 /***********************************************************************
450 * EVENT_AddIO
452 static void EVENT_AddIO(int fd, unsigned io_type)
454 EnterCriticalSection( &__winsock_crst );
455 FD_SET( fd, &__winsock_io_set[io_type] );
456 if( __winsock_max_fd <= fd ) __winsock_max_fd = fd + 1;
457 LeaveCriticalSection( &__winsock_crst );
459 WINSOCK_WakeUp();
462 /***********************************************************************
463 * EVENT_DeleteIO
465 static void EVENT_DeleteIO(int fd, unsigned io_type)
467 EnterCriticalSection( &__winsock_crst );
468 FD_CLR( fd, &__winsock_io_set[io_type] );
469 LeaveCriticalSection( &__winsock_crst );
471 WINSOCK_WakeUp();
475 /* ----------------------------------- API -----
477 * Init / cleanup / error checking.
480 /***********************************************************************
481 * WSAStartup16() (WINSOCK.115)
483 * Create socket control struct, attach it to the global list and
484 * update a pointer in the task struct.
486 INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA lpWSAData)
488 WSADATA WINSOCK_data = { 0x0101, 0x0101,
489 "WINE Sockets 1.1",
490 #ifdef linux
491 "Linux/i386",
492 #elif defined(__NetBSD__)
493 "NetBSD/i386",
494 #elif defined(sunos)
495 "SunOS",
496 #elif defined(__FreeBSD__)
497 "FreeBSD",
498 #elif defined(__OpenBSD__)
499 "OpenBSD/i386",
500 #else
501 "Unknown",
502 #endif
503 WS_MAX_SOCKETS_PER_PROCESS,
504 WS_MAX_UDP_DATAGRAM, (SEGPTR)NULL };
505 HTASK16 tid = GetCurrentTask();
506 LPWSINFO pwsi;
508 TRACE("verReq=%x\n", wVersionRequested);
510 if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
511 HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
513 if (!lpWSAData) return WSAEINVAL;
515 /* initialize socket heap */
517 if( !_ws_stub )
519 _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
520 if( !(_ws_stub = WS_ALLOC(0x10)) )
522 ERR("Fatal: failed to create WinSock heap\n");
523 return 0;
526 if( _WSHeap == 0 ) return WSASYSNOTREADY;
528 /* create socket array for this task */
530 pwsi = wsi_find(GetCurrentTask());
531 if( pwsi == NULL )
533 TDB* pTask = (TDB*)GlobalLock16( tid );
535 if( (pwsi = (LPWSINFO)WS_ALLOC( sizeof(WSINFO))) )
537 int i = 0;
538 pwsi->tid = tid;
539 for( i = 0; i < WS_MAX_SOCKETS_PER_PROCESS; i++ )
541 pwsi->sock[i].fd = -1;
542 pwsi->sock[i].flags = i + 1;
544 pwsi->sock[WS_MAX_SOCKETS_PER_PROCESS - 1].flags = -1;
546 else return WSASYSNOTREADY;
548 /* add this control struct to the global list */
550 pwsi->prev = NULL;
551 if( _wsi_list )
552 _wsi_list->prev = pwsi;
553 pwsi->next = _wsi_list;
554 _wsi_list = pwsi;
555 pTask->pwsi = pwsi;
557 else pwsi->num_startup++;
559 /* return winsock information */
561 memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
563 TRACE("succeeded\n");
564 return 0;
567 /***********************************************************************
568 * WSAStartup32() (WSOCK32.115)
570 INT WINAPI WSAStartup(UINT wVersionRequested, LPWSADATA lpWSAData)
572 return WSAStartup16( wVersionRequested, lpWSAData );
575 /***********************************************************************
576 * WSACleanup() (WINSOCK.116)
578 * Cleanup functions of varying impact.
581 INT WINSOCK_DeleteTaskWSI( TDB* pTask, LPWSINFO pwsi )
583 /* WSACleanup() backend, called on task termination as well.
584 * Real DLL would have registered its own signal handler with
585 * TaskSetSignalHandler() and waited until USIG_TERMINATION/USIG_GPF
586 * but this scheme is much more straightforward.
589 int i, j, n;
591 if( --pwsi->num_startup > 0 ) return 0;
593 /* unlink socket control struct */
595 if( pwsi == _wsi_list )
596 _wsi_list = pwsi->next;
597 else
598 pwsi->prev->next = pwsi->next;
599 if( pwsi->next ) pwsi->next->prev = pwsi->prev;
601 if( _wsi_list == NULL )
602 WINSOCK_Shutdown(); /* just in case */
604 if( pwsi->flags & WSI_BLOCKINGCALL )
605 TRACE("\tinside blocking call!\n");
607 /* FIXME: aop_control() doesn't decrement pwsi->num_async_rq
609 * if( pwsi->num_async_rq )
610 * WARN(winsock,"\thave %i outstanding async ops!\n", pwsi->num_async_rq );
613 for(i = 0, j = 0, n = 0; i < WS_MAX_SOCKETS_PER_PROCESS; i++)
614 if( pwsi->sock[i].fd != -1 )
616 if( pwsi->sock[i].psop )
618 n++;
619 WSAAsyncSelect( (SOCKET16)WS_PTR2HANDLE(pwsi->sock + i), 0, 0, 0 );
621 close(pwsi->sock[i].fd); j++;
623 if( j )
624 TRACE("\tclosed %i sockets, killed %i async selects!\n", j, n);
626 /* delete scratch buffers */
628 if( pwsi->buffer ) SEGPTR_FREE(pwsi->buffer);
629 if( pwsi->dbuffer ) SEGPTR_FREE(pwsi->dbuffer);
631 if( pTask )
632 pTask->pwsi = NULL;
633 memset( pwsi, 0, sizeof(WSINFO) );
634 WS_FREE(pwsi);
635 return 0;
638 INT WINAPI WSACleanup(void)
640 HTASK16 hTask = GetCurrentTask();
642 TRACE("(%04x)\n", hTask );
643 if( hTask )
645 LPWSINFO pwsi = wsi_find(hTask);
646 if( pwsi )
647 return WINSOCK_DeleteTaskWSI( (TDB*)GlobalLock16(hTask), pwsi );
648 return SOCKET_ERROR;
650 else
651 WINSOCK_Shutdown(); /* remove all outstanding DNS requests */
652 return 0;
656 /***********************************************************************
657 * WSAGetLastError() (WSOCK32.111)(WINSOCK.111)
659 INT WINAPI WSAGetLastError(void)
661 return GetLastError();
664 /***********************************************************************
665 * WSASetLastError32() (WSOCK32.112)
667 void WINAPI WSASetLastError(INT iError) {
668 SetLastError(iError);
671 /***********************************************************************
672 * WSASetLastError16() (WINSOCK.112)
674 void WINAPI WSASetLastError16(INT16 iError)
676 WSASetLastError(iError);
679 int _check_ws(LPWSINFO pwsi, ws_socket* pws)
681 if( pwsi )
683 if( pwsi->flags & WSI_BLOCKINGCALL ) SetLastError(WSAEINPROGRESS);
684 else if( WSI_CHECK_RANGE(pwsi, pws) ) return 1;
685 else SetLastError(WSAENOTSOCK);
687 return 0;
690 char* _check_buffer(LPWSINFO pwsi, int size)
692 if( pwsi->buffer && pwsi->buflen >= size ) return pwsi->buffer;
693 else SEGPTR_FREE(pwsi->buffer);
695 pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size));
696 return pwsi->buffer;
699 struct ws_hostent* _check_buffer_he(LPWSINFO pwsi, int size)
701 if( pwsi->he && pwsi->helen >= size ) return pwsi->he;
702 else SEGPTR_FREE(pwsi->he);
704 pwsi->he = (struct ws_hostent*)SEGPTR_ALLOC((pwsi->helen = size));
705 return pwsi->he;
708 struct ws_servent* _check_buffer_se(LPWSINFO pwsi, int size)
710 if( pwsi->se && pwsi->selen >= size ) return pwsi->se;
711 else SEGPTR_FREE(pwsi->se);
713 pwsi->se = (struct ws_servent*)SEGPTR_ALLOC((pwsi->selen = size));
714 return pwsi->se;
717 struct ws_protoent* _check_buffer_pe(LPWSINFO pwsi, int size)
719 if( pwsi->pe && pwsi->pelen >= size ) return pwsi->pe;
720 else SEGPTR_FREE(pwsi->pe);
722 pwsi->pe = (struct ws_protoent*)SEGPTR_ALLOC((pwsi->pelen = size));
723 return pwsi->pe;
726 /* ----------------------------------- i/o APIs */
728 /***********************************************************************
729 * accept() (WSOCK32.1)
731 SOCKET WINAPI WINSOCK_accept(SOCKET s, struct sockaddr *addr,
732 INT *addrlen32)
734 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR((SOCKET16)s);
735 LPWSINFO pwsi = wsi_find(GetCurrentTask());
736 #ifdef HAVE_IPX
737 struct ws_sockaddr_ipx* addr2 = (struct ws_sockaddr_ipx *)addr;
738 #endif
740 TRACE("(%08x): socket %04x\n",
741 (unsigned)pwsi, (UINT16)s );
742 if( _check_ws(pwsi, pws) )
744 int sock, fd_flags;
746 fd_flags = fcntl(pws->fd, F_GETFL, 0);
748 if( (sock = accept(pws->fd, addr, addrlen32)) >= 0 )
750 ws_socket* pnew = wsi_alloc_socket(pwsi, sock);
751 if( pnew )
753 s = (SOCKET)WS_PTR2HANDLE(pnew);
754 if( pws->psop && pws->flags & WS_FD_ACCEPT )
756 EVENT_AddIO( pws->fd, EVENT_IO_READ ); /* reenabler */
758 /* async select the accept()'ed socket */
759 WSAAsyncSelect( s, pws->psop->hWnd, pws->psop->uMsg,
760 pws->flags & ~WS_FD_ACCEPT );
762 #ifdef HAVE_IPX
763 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
764 addr = (struct sockaddr *)
765 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
766 memcpy(addr, addr2,
767 addrlen32 ? *addrlen32 : sizeof(*addr2));
768 addr2->sipx_family = WS_AF_IPX;
769 addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
770 addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
771 memcpy(addr2->sipx_node,
772 ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
773 free(addr);
775 #endif
776 return s;
778 else SetLastError(WSAENOBUFS);
779 } else SetLastError(wsaErrno());
781 #ifdef HAVE_IPX
782 if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) {
783 addr = (struct sockaddr *)
784 malloc(addrlen32 ? *addrlen32 : sizeof(*addr2));
785 memcpy(addr, addr2, addrlen32 ? *addrlen32 : sizeof(*addr2));
786 addr2->sipx_family = WS_AF_IPX;
787 addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network;
788 addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port;
789 memcpy(addr2->sipx_node,
790 ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN);
791 free(addr);
793 #endif
794 return INVALID_SOCKET;
797 /***********************************************************************
798 * accept() (WINSOCK.1)
800 SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr,
801 INT16* addrlen16 )
803 INT addrlen32 = addrlen16 ? *addrlen16 : 0;
804 SOCKET retSocket = WINSOCK_accept( s, addr, &addrlen32 );
805 if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
806 return (SOCKET16)retSocket;
809 /***********************************************************************
810 * bind() (WSOCK32.2)
812 INT WINAPI WINSOCK_bind(SOCKET s, struct sockaddr *name, INT namelen)
814 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
815 LPWSINFO pwsi = wsi_find(GetCurrentTask());
816 #ifdef HAVE_IPX
817 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
818 #endif
820 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
821 (unsigned)pwsi, s, (int) name, namelen);
822 #if DEBUG_SOCKADDR
823 dump_sockaddr(name);
824 #endif
826 if ( _check_ws(pwsi, pws) )
828 /* FIXME: what family does this really map to on the Unix side? */
829 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
830 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
831 #ifdef HAVE_IPX
832 else if (name &&
833 ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
835 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
836 memset(name, '\0', sizeof(struct sockaddr_ipx));
837 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
838 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
839 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
840 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
841 name2->sipx_node, IPX_NODE_LEN);
842 namelen = sizeof(struct sockaddr_ipx);
844 #endif
845 if ( namelen >= sizeof(*name) )
847 if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET
848 #ifdef HAVE_IPX
849 || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX
850 #endif
853 if ( bind(pws->fd, name, namelen) < 0 )
855 int loc_errno = errno;
856 WARN("\tfailure - errno = %i\n", errno);
857 errno = loc_errno;
858 switch(errno)
860 case EBADF: SetLastError(WSAENOTSOCK); break;
861 case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break;
862 default: SetLastError(wsaErrno());break;
865 else {
866 #ifdef HAVE_IPX
867 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
868 free(name);
869 #endif
870 return 0; /* success */
872 } else SetLastError(WSAEAFNOSUPPORT);
873 } else SetLastError(WSAEFAULT);
874 #ifdef HAVE_IPX
875 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
876 free(name);
877 #endif
879 return SOCKET_ERROR;
882 /***********************************************************************
883 * bind() (WINSOCK.2)
885 INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
887 return (INT16)WINSOCK_bind( s, name, namelen );
890 /***********************************************************************
891 * closesocket() (WSOCK32.3)
893 INT WINAPI WINSOCK_closesocket(SOCKET s)
895 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
896 LPWSINFO pwsi = wsi_find(GetCurrentTask());
898 TRACE("(%08x): socket %08x\n", (unsigned)pwsi, s);
900 if( _check_ws(pwsi, pws) )
902 int fd = pws->fd;
904 if( pws->psop ) WSAAsyncSelect( s, 0, 0, 0 );
906 pws->fd = -1;
907 pws->flags = (unsigned)pwsi->last_free;
908 pwsi->last_free = pws - &pwsi->sock[0]; /* add to free list */
910 if( close(fd) == 0 )
911 return 0;
912 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
914 return SOCKET_ERROR;
917 /***********************************************************************
918 * closesocket() (WINSOCK.3)
920 INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
922 return (INT16)WINSOCK_closesocket(s);
925 /***********************************************************************
926 * connect() (WSOCK32.4)
928 INT WINAPI WINSOCK_connect(SOCKET s, struct sockaddr *name, INT namelen)
930 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
931 LPWSINFO pwsi = wsi_find(GetCurrentTask());
932 #ifdef HAVE_IPX
933 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
934 #endif
936 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
937 (unsigned)pwsi, s, (int) name, namelen);
938 #if DEBUG_SOCKADDR
939 dump_sockaddr(name);
940 #endif
942 if( _check_ws(pwsi, pws) )
944 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP)
945 ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC;
946 #ifdef HAVE_IPX
947 else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX)
949 name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
950 memset(name, '\0', sizeof(struct sockaddr_ipx));
951 ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX;
952 ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port;
953 ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network;
954 memcpy(((struct sockaddr_ipx *)name)->sipx_node,
955 name2->sipx_node, IPX_NODE_LEN);
956 namelen = sizeof(struct sockaddr_ipx);
958 #endif
959 if (connect(pws->fd, name, namelen) == 0)
961 if( pws->psop && (pws->flags & WS_FD_CONNECT) )
963 /* application did AsyncSelect() but then went
964 * ahead and called connect() without waiting for
965 * notification.
967 * FIXME: Do we have to post a notification message
968 * in this case?
971 if( !(pws->flags & WS_FD_CONNECTED) )
973 if( pws->flags & (WS_FD_READ | WS_FD_CLOSE) )
974 EVENT_AddIO( pws->fd, EVENT_IO_READ );
975 else
976 EVENT_DeleteIO( pws->fd, EVENT_IO_READ );
977 if( pws->flags & WS_FD_WRITE )
978 EVENT_AddIO( pws->fd, EVENT_IO_WRITE );
979 else
980 EVENT_DeleteIO( pws->fd, EVENT_IO_WRITE );
983 pws->flags |= WS_FD_CONNECTED;
984 pws->flags &= ~(WS_FD_INACTIVE | WS_FD_CONNECT | WS_FD_LISTENING);
985 #ifdef HAVE_IPX
986 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
987 free(name);
988 #endif
989 return 0;
991 SetLastError((errno == EINPROGRESS) ? WSAEWOULDBLOCK : wsaErrno());
993 #ifdef HAVE_IPX
994 if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX)
995 free(name);
996 #endif
997 return SOCKET_ERROR;
1000 /***********************************************************************
1001 * connect() (WINSOCK.4)
1003 INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen)
1005 return (INT16)WINSOCK_connect( s, name, namelen );
1008 /***********************************************************************
1009 * getpeername() (WSOCK32.5)
1011 INT WINAPI WINSOCK_getpeername(SOCKET s, struct sockaddr *name,
1012 INT *namelen)
1014 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
1015 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1016 #ifdef HAVE_IPX
1017 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1018 #endif
1020 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1021 (unsigned)pwsi, s, (int) name, *namelen);
1022 if( _check_ws(pwsi, pws) )
1024 if (getpeername(pws->fd, name, namelen) == 0) {
1025 #ifdef HAVE_IPX
1026 if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1027 name = (struct sockaddr *)
1028 malloc(namelen ? *namelen : sizeof(*name2));
1029 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1030 name2->sipx_family = WS_AF_IPX;
1031 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1032 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1033 memcpy(name2->sipx_node,
1034 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1035 free(name);
1037 #endif
1038 return 0;
1040 SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1042 #ifdef HAVE_IPX
1043 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1044 name = (struct sockaddr *) malloc(namelen ? *namelen : sizeof(*name2));
1045 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1046 name2->sipx_family = WS_AF_IPX;
1047 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1048 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1049 memcpy(name2->sipx_node,
1050 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1051 free(name);
1053 #endif
1054 return SOCKET_ERROR;
1057 /***********************************************************************
1058 * getpeername() (WINSOCK.5)
1060 INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name,
1061 INT16 *namelen16)
1063 INT namelen32 = *namelen16;
1064 INT retVal = WINSOCK_getpeername( s, name, &namelen32 );
1066 #if DEBUG_SOCKADDR
1067 dump_sockaddr(name);
1068 #endif
1070 *namelen16 = namelen32;
1071 return (INT16)retVal;
1074 /***********************************************************************
1075 * getsockname() (WSOCK32.6)
1077 INT WINAPI WINSOCK_getsockname(SOCKET s, struct sockaddr *name,
1078 INT *namelen)
1080 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
1081 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1082 #ifdef HAVE_IPX
1083 struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name;
1084 #endif
1086 TRACE("(%08x): socket: %04x, ptr %8x, ptr %8x\n",
1087 (unsigned)pwsi, s, (int) name, (int) *namelen);
1088 if( _check_ws(pwsi, pws) )
1090 if (getsockname(pws->fd, name, namelen) == 0) {
1091 #ifdef HAVE_IPX
1092 if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1093 name = (struct sockaddr *)
1094 malloc(namelen ? *namelen : sizeof(*name2));
1095 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1096 name2->sipx_family = WS_AF_IPX;
1097 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1098 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1099 memcpy(name2->sipx_node,
1100 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1101 free(name);
1103 #endif
1104 return 0;
1106 SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1108 #ifdef HAVE_IPX
1109 if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) {
1110 name = (struct sockaddr *) malloc(namelen ? *namelen : sizeof(*name2));
1111 memcpy(name, name2, namelen ? *namelen : sizeof(*name2));
1112 name2->sipx_family = WS_AF_IPX;
1113 name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network;
1114 name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port;
1115 memcpy(name2->sipx_node,
1116 ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN);
1117 free(name);
1119 #endif
1120 return SOCKET_ERROR;
1123 /***********************************************************************
1124 * getsockname() (WINSOCK.6)
1126 INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name,
1127 INT16 *namelen16)
1129 INT retVal;
1131 if( namelen16 )
1133 INT namelen32 = *namelen16;
1134 retVal = WINSOCK_getsockname( s, name, &namelen32 );
1135 *namelen16 = namelen32;
1137 #if DEBUG_SOCKADDR
1138 dump_sockaddr(name);
1139 #endif
1142 else retVal = SOCKET_ERROR;
1143 return (INT16)retVal;
1147 /***********************************************************************
1148 * getsockopt() (WSOCK32.7)
1150 INT WINAPI WINSOCK_getsockopt(SOCKET s, INT level,
1151 INT optname, char *optval, INT *optlen)
1153 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
1154 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1156 TRACE("(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n",
1157 (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
1158 if( _check_ws(pwsi, pws) )
1160 convert_sockopt(&level, &optname);
1161 if (getsockopt(pws->fd, (int) level, optname, optval, optlen) == 0 )
1162 return 0;
1163 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1165 return SOCKET_ERROR;
1168 /***********************************************************************
1169 * getsockopt() (WINSOCK.7)
1171 INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
1172 INT16 optname, char *optval, INT16 *optlen)
1174 INT optlen32;
1175 INT *p = &optlen32;
1176 INT retVal;
1177 if( optlen ) optlen32 = *optlen; else p = NULL;
1178 retVal = WINSOCK_getsockopt( s, (UINT16)level, optname, optval, p );
1179 if( optlen ) *optlen = optlen32;
1180 return (INT16)retVal;
1183 /***********************************************************************
1184 * htonl() (WINSOCK.8)(WSOCK32.8)
1186 u_long WINAPI WINSOCK_htonl(u_long hostlong) { return( htonl(hostlong) ); }
1187 /***********************************************************************
1188 * htons() (WINSOCK.9)(WSOCK32.9)
1190 u_short WINAPI WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
1191 /***********************************************************************
1192 * inet_addr() (WINSOCK.10)(WSOCK32.10)
1194 u_long WINAPI WINSOCK_inet_addr(char *cp) { return( inet_addr(cp) ); }
1195 /***********************************************************************
1196 * htohl() (WINSOCK.14)(WSOCK32.14)
1198 u_long WINAPI WINSOCK_ntohl(u_long netlong) { return( ntohl(netlong) ); }
1199 /***********************************************************************
1200 * ntohs() (WINSOCK.15)(WSOCK32.15)
1202 u_short WINAPI WINSOCK_ntohs(u_short netshort) { return( ntohs(netshort) ); }
1204 /***********************************************************************
1205 * inet_ntoa() (WINSOCK.11)(WSOCK32.11)
1207 char* WINAPI WINSOCK_inet_ntoa(struct in_addr in)
1209 /* use "buffer for dummies" here because some applications have
1210 * propensity to decode addresses in ws_hostent structure without
1211 * saving them first...
1214 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1216 if( pwsi )
1218 char* s = inet_ntoa(in);
1219 if( s )
1221 if( pwsi->dbuffer == NULL )
1222 if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(32)) == NULL )
1224 SetLastError(WSAENOBUFS);
1225 return NULL;
1227 strncpy(pwsi->dbuffer, s, 32 );
1228 return pwsi->dbuffer;
1230 SetLastError(wsaErrno());
1232 return NULL;
1235 SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
1237 char* retVal = WINSOCK_inet_ntoa(in);
1238 return retVal ? SEGPTR_GET(retVal) : (SEGPTR)NULL;
1241 /***********************************************************************
1242 * ioctlsocket() (WSOCK32.12)
1244 INT WINAPI WINSOCK_ioctlsocket(SOCKET s, UINT cmd, UINT *argp)
1246 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
1247 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1249 TRACE("(%08x): socket %04x, cmd %08x, ptr %8x\n",
1250 (unsigned)pwsi, s, cmd, (unsigned) argp);
1251 if( _check_ws(pwsi, pws) )
1253 long newcmd = cmd;
1255 switch( cmd )
1257 case WS_FIONREAD:
1258 newcmd=FIONREAD;
1259 break;
1261 case WS_FIONBIO:
1262 newcmd=FIONBIO;
1263 if( pws->psop && *argp == 0 )
1265 /* AsyncSelect()'ed sockets are always nonblocking */
1266 SetLastError(WSAEINVAL);
1267 return SOCKET_ERROR;
1269 break;
1271 case WS_SIOCATMARK:
1272 newcmd=SIOCATMARK;
1273 break;
1275 case WS_IOW('f',125,u_long):
1276 WARN("Warning: WS1.1 shouldn't be using async I/O\n");
1277 SetLastError(WSAEINVAL);
1278 return SOCKET_ERROR;
1280 default:
1281 /* Netscape tries hard to use bogus ioctl 0x667e */
1282 WARN("\tunknown WS_IOCTL cmd (%08x)\n", cmd);
1284 if( ioctl(pws->fd, newcmd, (char*)argp ) == 0 ) return 0;
1285 SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1287 return SOCKET_ERROR;
1290 /***********************************************************************
1291 * ioctlsocket() (WINSOCK.12)
1293 INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, UINT cmd, UINT *argp)
1295 return (INT16)WINSOCK_ioctlsocket( s, cmd, argp );
1299 /***********************************************************************
1300 * listen() (WSOCK32.13)
1302 INT WINAPI WINSOCK_listen(SOCKET s, INT backlog)
1304 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
1305 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1307 TRACE("(%08x): socket %04x, backlog %d\n",
1308 (unsigned)pwsi, s, backlog);
1309 if( _check_ws(pwsi, pws) )
1311 if (listen(pws->fd, backlog) == 0)
1313 if( !pws->psop )
1315 int fd_flags = fcntl(pws->fd, F_GETFL, 0);
1316 if( !(fd_flags & O_NONBLOCK) ) pws->flags |= WS_FD_ACCEPT;
1318 pws->flags |= WS_FD_LISTENING;
1319 pws->flags &= ~(WS_FD_INACTIVE | WS_FD_CONNECT | WS_FD_CONNECTED); /* just in case */
1320 return 0;
1322 SetLastError(wsaErrno());
1324 else SetLastError(WSAENOTSOCK);
1325 return SOCKET_ERROR;
1328 /***********************************************************************
1329 * listen() (WINSOCK.13)
1331 INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
1333 return (INT16)WINSOCK_listen( s, backlog );
1337 /***********************************************************************
1338 * recv() (WSOCK32.16)
1340 INT WINAPI WINSOCK_recv(SOCKET s, char *buf, INT len, INT flags)
1342 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
1343 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1345 TRACE("(%08x): socket %04x, buf %8x, len %d, "
1346 "flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1347 len, flags);
1348 if( _check_ws(pwsi, pws) )
1350 INT length;
1351 if ((length = recv(pws->fd, buf, len, flags)) >= 0)
1353 TRACE(" -> %i bytes\n", length);
1355 if( pws->psop && (pws->flags & (WS_FD_READ | WS_FD_CLOSE)) )
1356 EVENT_AddIO( pws->fd, EVENT_IO_READ ); /* reenabler */
1358 return length;
1360 SetLastError(wsaErrno());
1362 else SetLastError(WSAENOTSOCK);
1363 WARN(" -> ERROR\n");
1364 return SOCKET_ERROR;
1367 /***********************************************************************
1368 * recv() (WINSOCK.16)
1370 INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1372 return (INT16)WINSOCK_recv( s, buf, len, flags );
1376 /***********************************************************************
1377 * recvfrom() (WSOCK32.17)
1379 INT WINAPI WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags,
1380 struct sockaddr *from, INT *fromlen32)
1382 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
1383 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1384 #ifdef HAVE_IPX
1385 struct ws_sockaddr_ipx* from2 = (struct ws_sockaddr_ipx *)from;
1386 #endif
1388 TRACE("(%08x): socket %04x, ptr %08x, "
1389 "len %d, flags %d\n", (unsigned)pwsi, s, (unsigned)buf,
1390 len, flags);
1391 #if DEBUG_SOCKADDR
1392 if( from ) dump_sockaddr(from);
1393 else DPRINTF("from = NULL\n");
1394 #endif
1396 if( _check_ws(pwsi, pws) )
1398 int length;
1400 if ((length = recvfrom(pws->fd, buf, len, flags, from, fromlen32)) >= 0)
1402 TRACE(" -> %i bytes\n", length);
1404 if( pws->psop && (pws->flags & (WS_FD_READ | WS_FD_CLOSE)) )
1405 EVENT_AddIO( pws->fd, EVENT_IO_READ ); /* reenabler */
1407 #ifdef HAVE_IPX
1408 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1409 from = (struct sockaddr *)
1410 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1411 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1412 from2->sipx_family = WS_AF_IPX;
1413 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1414 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1415 memcpy(from2->sipx_node,
1416 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1417 free(from);
1419 #endif
1420 return (INT16)length;
1422 SetLastError(wsaErrno());
1424 else SetLastError(WSAENOTSOCK);
1425 WARN(" -> ERROR\n");
1426 #ifdef HAVE_IPX
1427 if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) {
1428 from = (struct sockaddr *)
1429 malloc(fromlen32 ? *fromlen32 : sizeof(*from2));
1430 memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2));
1431 from2->sipx_family = WS_AF_IPX;
1432 from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network;
1433 from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port;
1434 memcpy(from2->sipx_node,
1435 ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN);
1436 free(from);
1438 #endif
1439 return SOCKET_ERROR;
1442 /***********************************************************************
1443 * recvfrom() (WINSOCK.17)
1445 INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1446 struct sockaddr *from, INT16 *fromlen16)
1448 INT fromlen32;
1449 INT *p = &fromlen32;
1450 INT retVal;
1452 if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
1453 retVal = WINSOCK_recvfrom( s, buf, len, flags, from, p );
1454 if( fromlen16 ) *fromlen16 = fromlen32;
1455 return (INT16)retVal;
1458 /***********************************************************************
1459 * select() (WINSOCK.18)(WSOCK32.18)
1461 static INT __ws_select( BOOL b32, void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
1462 struct timeval *timeout )
1464 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1466 TRACE("(%08x): read %8x, write %8x, excp %8x\n",
1467 (unsigned) pwsi, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
1469 if( pwsi )
1471 int highfd = 0;
1472 fd_set readfds, writefds, exceptfds;
1473 fd_set *p_read, *p_write, *p_except;
1475 p_read = fd_set_import(&readfds, pwsi, ws_readfds, &highfd, b32);
1476 p_write = fd_set_import(&writefds, pwsi, ws_writefds, &highfd, b32);
1477 p_except = fd_set_import(&exceptfds, pwsi, ws_exceptfds, &highfd, b32);
1479 if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeout)) > 0 )
1481 fd_set_export(pwsi, &readfds, p_except, ws_readfds, b32);
1482 fd_set_export(pwsi, &writefds, p_except, ws_writefds, b32);
1484 if (p_except && ws_exceptfds)
1486 #define wsfds16 ((ws_fd_set16*)ws_exceptfds)
1487 #define wsfds32 ((ws_fd_set32*)ws_exceptfds)
1488 int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
1490 for (i = j = 0; i < count; i++)
1492 ws_socket *pws = (b32) ? (ws_socket *)WS_HANDLE2PTR(wsfds32->fd_array[i])
1493 : (ws_socket *)WS_HANDLE2PTR(wsfds16->fd_array[i]);
1494 if( _check_ws(pwsi, pws) && FD_ISSET(pws->fd, &exceptfds) )
1496 if( b32 )
1497 wsfds32->fd_array[j++] = wsfds32->fd_array[i];
1498 else
1499 wsfds16->fd_array[j++] = wsfds16->fd_array[i];
1502 if( b32 )
1503 wsfds32->fd_count = j;
1504 else
1505 wsfds16->fd_count = j;
1506 #undef wsfds32
1507 #undef wsfds16
1509 return highfd;
1511 if( ws_readfds ) ((ws_fd_set32*)ws_readfds)->fd_count = 0;
1512 if( ws_writefds ) ((ws_fd_set32*)ws_writefds)->fd_count = 0;
1513 if( ws_exceptfds ) ((ws_fd_set32*)ws_exceptfds)->fd_count = 0;
1515 if( highfd == 0 ) return 0;
1516 SetLastError(wsaErrno());
1518 return SOCKET_ERROR;
1521 INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
1522 ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
1523 struct timeval *timeout)
1525 return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1528 INT WINAPI WINSOCK_select(INT nfds, ws_fd_set32 *ws_readfds,
1529 ws_fd_set32 *ws_writefds, ws_fd_set32 *ws_exceptfds,
1530 struct timeval *timeout)
1532 /* struct timeval is the same for both 32- and 16-bit code */
1533 return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
1537 /***********************************************************************
1538 * send() (WSOCK32.19)
1540 INT WINAPI WINSOCK_send(SOCKET s, char *buf, INT len, INT flags)
1542 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
1543 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1545 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1546 (unsigned)pwsi, s, (unsigned) buf, len, flags);
1547 if( _check_ws(pwsi, pws) )
1549 int length;
1551 if ((length = send(pws->fd, buf, len, flags)) < 0 )
1553 SetLastError(wsaErrno());
1554 if( GetLastError() == WSAEWOULDBLOCK &&
1555 pws->psop && pws->flags & WS_FD_WRITE )
1556 EVENT_AddIO( pws->fd, EVENT_IO_WRITE ); /* reenabler */
1558 else return (INT16)length;
1560 else SetLastError(WSAENOTSOCK);
1561 return SOCKET_ERROR;
1564 /***********************************************************************
1565 * send() (WINSOCK.19)
1567 INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
1569 return WINSOCK_send( s, buf, len, flags );
1572 /***********************************************************************
1573 * sendto() (WSOCK32.20)
1575 INT WINAPI WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags,
1576 struct sockaddr *to, INT tolen)
1578 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
1579 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1580 #ifdef HAVE_IPX
1581 struct ws_sockaddr_ipx* to2 = (struct ws_sockaddr_ipx *)to;
1582 #endif
1584 TRACE("(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
1585 (unsigned)pwsi, s, (unsigned) buf, len, flags);
1586 if( _check_ws(pwsi, pws) )
1588 INT length;
1590 if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP)
1591 ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC;
1592 #ifdef HAVE_IPX
1593 else if (to &&
1594 ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX)
1596 to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx));
1597 memset(to, '\0', sizeof(struct sockaddr_ipx));
1598 ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX;
1599 ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port;
1600 ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network;
1601 memcpy(((struct sockaddr_ipx *)to)->sipx_node,
1602 to2->sipx_node, IPX_NODE_LEN);
1603 tolen = sizeof(struct sockaddr_ipx);
1605 #endif
1606 if ((length = sendto(pws->fd, buf, len, flags, to, tolen)) < 0 )
1608 SetLastError(wsaErrno());
1609 if( GetLastError() == WSAEWOULDBLOCK &&
1610 pws->psop && pws->flags & WS_FD_WRITE )
1611 EVENT_AddIO( pws->fd, EVENT_IO_WRITE ); /* reenabler */
1613 else {
1614 #ifdef HAVE_IPX
1615 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1616 free(to);
1618 #endif
1619 return length;
1622 else SetLastError(WSAENOTSOCK);
1623 #ifdef HAVE_IPX
1624 if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) {
1625 free(to);
1627 #endif
1628 return SOCKET_ERROR;
1631 /***********************************************************************
1632 * sendto() (WINSOCK.20)
1634 INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
1635 struct sockaddr *to, INT16 tolen)
1637 return (INT16)WINSOCK_sendto( s, buf, len, flags, to, tolen );
1640 /***********************************************************************
1641 * setsockopt() (WSOCK32.21)
1643 INT WINAPI WINSOCK_setsockopt(SOCKET16 s, INT level, INT optname,
1644 char *optval, INT optlen)
1646 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
1647 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1649 TRACE("(%08x): socket %04x, lev %d, opt %d, ptr %08x, len %d\n",
1650 (unsigned)pwsi, s, level, optname, (int) optval, optlen);
1651 if( _check_ws(pwsi, pws) )
1653 struct linger linger;
1655 convert_sockopt(&level, &optname);
1656 if (optname == SO_LINGER && optval) {
1657 /* yes, uses unsigned short in both win16/win32 */
1658 linger.l_onoff = ((UINT16*)optval)[0];
1659 linger.l_linger = ((UINT16*)optval)[1];
1660 /* FIXME: what is documented behavior if SO_LINGER optval
1661 is null?? */
1662 optval = (char*)&linger;
1663 optlen = sizeof(struct linger);
1665 if (setsockopt(pws->fd, level, optname, optval, optlen) == 0) return 0;
1666 SetLastError(wsaErrno());
1668 else SetLastError(WSAENOTSOCK);
1669 return SOCKET_ERROR;
1672 /***********************************************************************
1673 * setsockopt() (WINSOCK.21)
1675 INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
1676 char *optval, INT16 optlen)
1678 if( !optval ) return SOCKET_ERROR;
1679 return (INT16)WINSOCK_setsockopt( s, (UINT16)level, optname, optval, optlen );
1683 /***********************************************************************
1684 * shutdown() (WSOCK32.22)
1686 INT WINAPI WINSOCK_shutdown(SOCKET s, INT how)
1688 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
1689 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1691 TRACE("(%08x): socket %04x, how %i\n",
1692 (unsigned)pwsi, s, how );
1693 if( _check_ws(pwsi, pws) )
1695 if( pws->psop )
1696 switch( how )
1698 case 0: /* drop receives */
1699 if( pws->flags & (WS_FD_READ | WS_FD_CLOSE) )
1700 EVENT_DeleteIO( pws->fd, EVENT_IO_READ );
1701 pws->flags &= ~(WS_FD_READ | WS_FD_CLOSE);
1702 #ifdef SHUT_RD
1703 how = SHUT_RD;
1704 #endif
1705 break;
1707 case 1: /* drop sends */
1708 if( pws->flags & WS_FD_WRITE )
1709 EVENT_DeleteIO( pws->fd, EVENT_IO_WRITE );
1710 pws->flags &= ~WS_FD_WRITE;
1711 #ifdef SHUT_WR
1712 how = SHUT_WR;
1713 #endif
1714 break;
1716 case 2: /* drop all */
1717 #ifdef SHUT_RDWR
1718 how = SHUT_RDWR;
1719 #endif
1720 default:
1721 WSAAsyncSelect( s, 0, 0, 0 );
1722 break;
1725 if (shutdown(pws->fd, how) == 0)
1727 if( how > 1 )
1729 pws->flags &= ~(WS_FD_CONNECTED | WS_FD_LISTENING);
1730 pws->flags |= WS_FD_INACTIVE;
1732 return 0;
1734 SetLastError(wsaErrno());
1736 else SetLastError(WSAENOTSOCK);
1737 return SOCKET_ERROR;
1740 /***********************************************************************
1741 * shutdown() (WINSOCK.22)
1743 INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
1745 return (INT16)WINSOCK_shutdown( s, how );
1749 /***********************************************************************
1750 * socket() (WSOCK32.23)
1752 SOCKET WINAPI WINSOCK_socket(INT af, INT type, INT protocol)
1754 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1756 TRACE("(%08x): af=%d type=%d protocol=%d\n",
1757 (unsigned)pwsi, af, type, protocol);
1759 if( pwsi )
1761 int sock;
1763 /* check the socket family */
1764 switch(af)
1766 #ifdef HAVE_IPX
1767 case WS_AF_IPX: af = AF_IPX;
1768 #endif
1769 case AF_INET:
1770 case AF_UNSPEC: break;
1771 default: SetLastError(WSAEAFNOSUPPORT);
1772 return INVALID_SOCKET;
1775 /* check the socket type */
1776 switch(type)
1778 case SOCK_STREAM:
1779 case SOCK_DGRAM:
1780 case SOCK_RAW: break;
1781 default: SetLastError(WSAESOCKTNOSUPPORT);
1782 return INVALID_SOCKET;
1785 /* check the protocol type */
1786 if ( protocol < 0 ) /* don't support negative values */
1787 { SetLastError(WSAEPROTONOSUPPORT); return INVALID_SOCKET; }
1789 if ( af == AF_UNSPEC) /* did they not specify the address family? */
1790 switch(protocol)
1792 case IPPROTO_TCP:
1793 if (type == SOCK_STREAM) { af = AF_INET; break; }
1794 case IPPROTO_UDP:
1795 if (type == SOCK_DGRAM) { af = AF_INET; break; }
1796 default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
1799 if ((sock = socket(af, type, protocol)) >= 0)
1801 ws_socket* pnew = wsi_alloc_socket(pwsi, sock);
1803 TRACE("\tcreated %i (handle %04x)\n", sock, (UINT16)WS_PTR2HANDLE(pnew));
1805 if( pnew )
1807 pnew->flags |= WS_FD_INACTIVE;
1808 return (SOCKET16)WS_PTR2HANDLE(pnew);
1811 close(sock);
1812 SetLastError(WSAENOBUFS);
1813 return INVALID_SOCKET;
1816 if (errno == EPERM) /* raw socket denied */
1818 if (type == SOCK_RAW)
1819 MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
1820 else
1821 MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
1822 SetLastError(WSAESOCKTNOSUPPORT);
1823 } else SetLastError(wsaErrno());
1826 WARN("\t\tfailed!\n");
1827 return INVALID_SOCKET;
1830 /***********************************************************************
1831 * socket() (WINSOCK.23)
1833 SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
1835 return (SOCKET16)WINSOCK_socket( af, type, protocol );
1839 /* ----------------------------------- DNS services
1841 * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
1842 * Also, we have to use wsock32 stubs to convert structures and
1843 * error codes from Unix to WSA, hence there is no direct mapping in
1844 * the relay32/wsock32.spec.
1847 static char* NULL_STRING = "NULL";
1849 /***********************************************************************
1850 * gethostbyaddr() (WINSOCK.51)(WSOCK32.51)
1852 static struct WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
1854 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1856 if( pwsi )
1858 struct hostent* host;
1859 if( (host = gethostbyaddr(addr, len, type)) != NULL )
1860 if( WS_dup_he(pwsi, host, dup_flag) )
1861 return (struct WIN_hostent*)(pwsi->he);
1862 else
1863 SetLastError(WSAENOBUFS);
1864 else
1865 SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1867 return NULL;
1870 SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
1872 struct WIN_hostent* retval;
1873 TRACE("ptr %08x, len %d, type %d\n",
1874 (unsigned) addr, len, type);
1875 retval = __ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR );
1876 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
1879 struct WIN_hostent* WINAPI WINSOCK_gethostbyaddr(const char *addr, INT len,
1880 INT type)
1882 TRACE("ptr %08x, len %d, type %d\n",
1883 (unsigned) addr, len, type);
1884 return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
1887 /***********************************************************************
1888 * gethostbyname() (WINSOCK.52)(WSOCK32.52)
1890 static struct WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
1892 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1894 if( pwsi )
1896 struct hostent* host;
1897 if( (host = gethostbyname(name)) != NULL )
1898 if( WS_dup_he(pwsi, host, dup_flag) )
1899 return (struct WIN_hostent*)(pwsi->he);
1900 else SetLastError(WSAENOBUFS);
1901 else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1903 return NULL;
1906 SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
1908 struct WIN_hostent* retval;
1909 TRACE("%s\n", (name)?name:NULL_STRING);
1910 retval = __ws_gethostbyname( name, WS_DUP_SEGPTR );
1911 return (retval)? SEGPTR_GET(retval) : ((SEGPTR)NULL) ;
1914 struct WIN_hostent* WINAPI WINSOCK_gethostbyname(const char* name)
1916 TRACE("%s\n", (name)?name:NULL_STRING);
1917 return __ws_gethostbyname( name, WS_DUP_LINEAR );
1921 /***********************************************************************
1922 * getprotobyname() (WINSOCK.53)(WSOCK32.53)
1924 static struct WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
1926 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1928 if( pwsi )
1930 struct protoent* proto;
1931 if( (proto = getprotobyname(name)) != NULL )
1932 if( WS_dup_pe(pwsi, proto, dup_flag) )
1933 return (struct WIN_protoent*)(pwsi->pe);
1934 else SetLastError(WSAENOBUFS);
1935 else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
1937 return NULL;
1940 SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
1942 struct WIN_protoent* retval;
1943 TRACE("%s\n", (name)?name:NULL_STRING);
1944 retval = __ws_getprotobyname(name, WS_DUP_SEGPTR);
1945 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
1948 struct WIN_protoent* WINAPI WINSOCK_getprotobyname(const char* name)
1950 TRACE("%s\n", (name)?name:NULL_STRING);
1951 return __ws_getprotobyname(name, WS_DUP_LINEAR);
1955 /***********************************************************************
1956 * getprotobynumber() (WINSOCK.54)(WSOCK32.54)
1958 static struct WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
1960 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1962 if( pwsi )
1964 struct protoent* proto;
1965 if( (proto = getprotobynumber(number)) != NULL )
1966 if( WS_dup_pe(pwsi, proto, dup_flag) )
1967 return (struct WIN_protoent*)(pwsi->pe);
1968 else SetLastError(WSAENOBUFS);
1969 else SetLastError(WSANO_DATA);
1971 return NULL;
1974 SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
1976 struct WIN_protoent* retval;
1977 TRACE("%i\n", number);
1978 retval = __ws_getprotobynumber(number, WS_DUP_SEGPTR);
1979 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
1982 struct WIN_protoent* WINAPI WINSOCK_getprotobynumber(INT number)
1984 TRACE("%i\n", number);
1985 return __ws_getprotobynumber(number, WS_DUP_LINEAR);
1989 /***********************************************************************
1990 * getservbyname() (WINSOCK.55)(WSOCK32.55)
1992 struct WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
1994 LPWSINFO pwsi = wsi_find(GetCurrentTask());
1996 if( pwsi )
1998 struct servent* serv;
1999 int i = wsi_strtolo( pwsi, name, proto );
2001 if( i )
2002 if( (serv = getservbyname(pwsi->buffer, pwsi->buffer + i)) != NULL )
2003 if( WS_dup_se(pwsi, serv, dup_flag) )
2004 return (struct WIN_servent*)(pwsi->se);
2005 else SetLastError(WSAENOBUFS);
2006 else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
2007 else SetLastError(WSAENOBUFS);
2009 return NULL;
2012 SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
2014 struct WIN_servent* retval;
2015 TRACE("'%s', '%s'\n",
2016 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2017 retval = __ws_getservbyname(name, proto, WS_DUP_SEGPTR);
2018 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2021 struct WIN_servent* WINAPI WINSOCK_getservbyname(const char *name, const char *proto)
2023 TRACE("'%s', '%s'\n",
2024 (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
2025 return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
2029 /***********************************************************************
2030 * getservbyport() (WINSOCK.56)(WSOCK32.56)
2032 static struct WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
2034 LPWSINFO pwsi = wsi_find(GetCurrentTask());
2036 if( pwsi )
2038 struct servent* serv;
2039 int i = wsi_strtolo( pwsi, proto, NULL );
2041 if( i )
2042 if( (serv = getservbyport(port, pwsi->buffer)) != NULL )
2043 if( WS_dup_se(pwsi, serv, dup_flag) )
2044 return (struct WIN_servent*)(pwsi->se);
2045 else SetLastError(WSAENOBUFS);
2046 else SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno());
2047 else SetLastError(WSAENOBUFS);
2049 return NULL;
2052 SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
2054 struct WIN_servent* retval;
2055 TRACE("%i, '%s'\n",
2056 (int)port, (proto)?proto:NULL_STRING);
2057 retval = __ws_getservbyport(port, proto, WS_DUP_SEGPTR);
2058 return retval ? SEGPTR_GET(retval) : ((SEGPTR)NULL);
2061 struct WIN_servent* WINAPI WINSOCK_getservbyport(INT port, const char *proto)
2063 TRACE("%i, '%s'\n",
2064 (int)port, (proto)?proto:NULL_STRING);
2065 return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
2069 /***********************************************************************
2070 * gethostname() (WSOCK32.57)
2072 INT WINAPI WINSOCK_gethostname(char *name, INT namelen)
2074 LPWSINFO pwsi = wsi_find(GetCurrentTask());
2076 TRACE("(%08x): name %s, len %d\n",
2077 (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
2078 if( pwsi )
2080 if (gethostname(name, namelen) == 0) return 0;
2081 SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2083 return SOCKET_ERROR;
2086 /***********************************************************************
2087 * gethostname() (WINSOCK.57)
2089 INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
2091 return (INT16)WINSOCK_gethostname(name, namelen);
2095 /* ------------------------------------- Windows sockets extensions -- *
2097 * ------------------------------------------------------------------- */
2098 /***********************************************************************
2099 * WSAAsyncSelect() (WINSOCK.101)(WSOCK32.101)
2102 static ws_select_op* __ws_select_list = NULL;
2104 BOOL WINSOCK_HandleIO( int* max_fd, int num_pending,
2105 fd_set pending_set[3], fd_set event_set[3] )
2107 /* This function is called by the event dispatcher
2108 * with the pending_set[] containing the result of select() and
2109 * the event_set[] containing all fd that are being watched */
2111 ws_select_op* psop = __ws_select_list;
2112 BOOL bPost = FALSE;
2113 DWORD dwEvent, dwErrBytes;
2114 int num_posted;
2116 TRACE("%i pending descriptors\n", num_pending );
2118 for( num_posted = dwEvent = 0 ; psop; psop = psop->next )
2120 unsigned flags = psop->pws->flags;
2121 int fd = psop->pws->fd;
2122 int r, w, e;
2124 w = 0;
2125 if( (r = FD_ISSET( fd, &pending_set[EVENT_IO_READ] )) ||
2126 (w = FD_ISSET( fd, &pending_set[EVENT_IO_WRITE] )) ||
2127 (e = FD_ISSET( fd, &pending_set[EVENT_IO_EXCEPT] )) )
2129 /* This code removes WS_FD flags on one-shot events (WS_FD_CLOSE,
2130 * WS_FD_CONNECT), otherwise it clears descriptors in the io_set.
2131 * Reenabling calls turn them back on.
2134 TRACE("\tchecking psop = 0x%08x\n", (unsigned) psop );
2136 num_pending--;
2138 /* Now figure out what kind of event we've got. The worst problem
2139 * we have to contend with is that some out of control applications
2140 * really want to use mutually exclusive AsyncSelect() flags all at
2141 * the same time.
2144 if((flags & WS_FD_ACCEPT) && (flags & WS_FD_LISTENING))
2146 /* WS_FD_ACCEPT is valid only if the socket is in the
2147 * listening state */
2149 FD_CLR( fd, &event_set[EVENT_IO_WRITE] );
2150 if( r )
2152 FD_CLR( fd, &event_set[EVENT_IO_READ] ); /* reenabled by the next accept() */
2153 dwEvent = WSAMAKESELECTREPLY( WS_FD_ACCEPT, 0 );
2154 bPost = TRUE;
2156 else continue;
2158 else if( flags & WS_FD_CONNECT )
2160 /* connecting socket */
2162 if( w || (w = FD_ISSET( fd, &pending_set[EVENT_IO_WRITE] )) )
2164 /* ready to write means that socket is connected
2166 * FIXME: Netscape calls AsyncSelect( s, ... WS_FD_CONNECT .. )
2167 * right after s = socket() and somehow "s" becomes writeable
2168 * before it goes through connect()!?!?
2171 psop->pws->flags |= WS_FD_CONNECTED;
2172 psop->pws->flags &= ~(WS_FD_CONNECT | WS_FD_INACTIVE);
2173 dwEvent = WSAMAKESELECTREPLY( WS_FD_CONNECT, 0 );
2175 if( flags & (WS_FD_READ | WS_FD_CLOSE))
2176 FD_SET( fd, &event_set[EVENT_IO_READ] );
2177 else
2178 FD_CLR( fd, &event_set[EVENT_IO_READ] );
2179 if( flags & WS_FD_WRITE )
2180 FD_SET( fd, &event_set[EVENT_IO_WRITE] );
2181 else
2182 FD_CLR( fd, &event_set[EVENT_IO_WRITE] );
2183 bPost = TRUE;
2185 else if( r )
2187 /* failure - do read() to get correct errno */
2189 if( read( fd, &dwErrBytes, sizeof(dwErrBytes) ) == -1 )
2191 dwEvent = WSAMAKESELECTREPLY( WS_FD_CONNECT, wsaErrno() );
2192 bPost = TRUE;
2195 /* otherwise bPost stays FALSE, should probably clear event_set */
2197 else
2199 /* connected socket, no WS_FD_OOB code for now. */
2201 if( flags & WS_FD_WRITE &&
2202 (w || (w = FD_ISSET( fd, &pending_set[EVENT_IO_WRITE] ))) )
2204 /* this will be reenabled when send() or sendto() fail with
2205 * WSAEWOULDBLOCK */
2207 if( PostMessageA( psop->hWnd, psop->uMsg, (WPARAM)WS_PTR2HANDLE(psop->pws),
2208 (LPARAM)WSAMAKESELECTREPLY( WS_FD_WRITE, 0 ) ) )
2210 TRACE("\t hwnd %04x - %04x, %08x\n",
2211 psop->hWnd, psop->uMsg, (unsigned)MAKELONG(WS_FD_WRITE, 0) );
2212 FD_CLR( fd, &event_set[EVENT_IO_WRITE] );
2213 num_posted++;
2217 if( r && (flags & (WS_FD_READ | WS_FD_CLOSE)) )
2219 int val = (flags & WS_FD_RAW);
2221 /* WS_FD_RAW is set by the WSAAsyncSelect() init */
2223 bPost = TRUE;
2224 if( !val && ioctl( fd, FIONREAD, (char*)&dwErrBytes) == -1 )
2226 /* weirdness */
2228 dwEvent = WSAMAKESELECTREPLY( WS_FD_READ, wsaErrno() );
2230 else if( val || dwErrBytes )
2232 /* got pending data, will be reenabled by recv() or recvfrom() */
2234 FD_CLR( fd, &event_set[EVENT_IO_READ] );
2235 dwEvent = WSAMAKESELECTREPLY( WS_FD_READ, 0 );
2237 else
2239 /* 0 bytes to read - connection reset by peer? */
2242 val = read( fd, (char*)&dwErrBytes, sizeof(dwErrBytes));
2243 while( errno == EINTR );
2244 if( errno != EWOULDBLOCK )
2246 switch( val )
2248 case 0: errno = ENETDOWN; /* soft reset, fall through */
2249 case -1: /* hard reset */
2250 dwEvent = WSAMAKESELECTREPLY( WS_FD_CLOSE, wsaErrno() );
2251 break;
2253 default: bPost = FALSE;
2254 continue; /* FIXME: this is real bad */
2257 else { bPost = FALSE; continue; } /* more weirdness */
2259 /* this is it, this socket is closed */
2261 psop->pws->flags &= ~(WS_FD_READ | WS_FD_CLOSE | WS_FD_WRITE);
2262 FD_CLR( fd, &event_set[EVENT_IO_READ] );
2263 FD_CLR( fd, &event_set[EVENT_IO_WRITE] );
2265 if( *max_fd == (fd + 1) ) (*max_fd)--;
2270 if( bPost )
2272 TRACE("\t hwnd %04x - %04x, %08x\n",
2273 psop->hWnd, psop->uMsg, (unsigned)dwEvent );
2274 PostMessageA( psop->hWnd, psop->uMsg,
2275 (WPARAM)WS_PTR2HANDLE(psop->pws), (LPARAM)dwEvent );
2276 bPost = FALSE;
2277 num_posted++;
2280 if( num_pending <= 0 ) break;
2283 TRACE("\tdone, %i posted events\n", num_posted );
2284 return ( num_posted ) ? TRUE : FALSE;
2287 INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, UINT lEvent)
2289 ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s);
2290 LPWSINFO pwsi = wsi_find(GetCurrentTask());
2292 TRACE("(%08x): %04x, hWnd %04x, uMsg %08x, event %08x\n",
2293 (unsigned)pwsi, (SOCKET16)s, (HWND16)hWnd, uMsg, (unsigned)lEvent );
2294 if( _check_ws(pwsi, pws) )
2296 ws_select_op* psop;
2298 if( (psop = pws->psop) )
2300 /* delete previous control struct */
2302 if( psop == __ws_select_list )
2303 __ws_select_list = psop->next;
2304 else
2305 psop->prev->next = psop->next;
2306 if( psop->next ) psop->next->prev = psop->prev;
2308 if( pws->flags & (WS_FD_ACCEPT | WS_FD_CONNECT | WS_FD_READ | WS_FD_CLOSE) )
2309 EVENT_DeleteIO( pws->fd, EVENT_IO_READ );
2310 if( pws->flags & (WS_FD_CONNECT | WS_FD_WRITE) )
2311 EVENT_DeleteIO( pws->fd, EVENT_IO_WRITE );
2313 TRACE("\tremoving psop = 0x%08x\n", (unsigned) psop );
2315 WS_FREE( pws->psop );
2316 pws->flags &= ~(WS_FD_RAW | WS_FD_ACCEPT | WS_FD_CONNECT |
2317 WS_FD_READ | WS_FD_WRITE | WS_FD_CLOSE);
2318 pws->psop = NULL;
2321 if( lEvent )
2323 psop = (ws_select_op*)WS_ALLOC(sizeof(ws_select_op));
2324 if( psop )
2326 int sock_type, bytes = sizeof(int);
2328 WINSOCK_unblock_io( pws->fd, TRUE );
2330 psop->prev = NULL;
2331 psop->next = __ws_select_list;
2332 if( __ws_select_list )
2333 __ws_select_list->prev = psop;
2334 __ws_select_list = psop;
2336 psop->pws = pws;
2337 psop->hWnd = hWnd;
2338 psop->uMsg = uMsg;
2340 pws->psop = psop;
2341 pws->flags |= (0x0000FFFF & lEvent);
2342 getsockopt(pws->fd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &bytes);
2343 if( sock_type == SOCK_RAW ) pws->flags |= WS_FD_RAW;
2345 if( lEvent & (WS_FD_ACCEPT | WS_FD_CONNECT | WS_FD_READ | WS_FD_CLOSE) )
2346 EVENT_AddIO( pws->fd, EVENT_IO_READ );
2347 if( lEvent & (WS_FD_CONNECT | WS_FD_WRITE) )
2348 EVENT_AddIO( pws->fd, EVENT_IO_WRITE );
2350 /* TODO: handle WS_FD_ACCEPT right away if the socket is readable */
2352 TRACE("\tcreating psop = 0x%08x\n", (unsigned)psop );
2354 return 0; /* success */
2356 else SetLastError(WSAENOBUFS);
2358 else return 0;
2360 else SetLastError(WSAEINVAL);
2361 return SOCKET_ERROR;
2364 INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, UINT lEvent)
2366 return (INT16)WSAAsyncSelect( s, hWnd, wMsg, lEvent );
2370 /***********************************************************************
2371 * __WSAFDIsSet() (WINSOCK.151)
2373 INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
2375 int i = set->fd_count;
2377 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2379 while (i--)
2380 if (set->fd_array[i] == s) return 1;
2381 return 0;
2384 /***********************************************************************
2385 * __WSAFDIsSet() (WSOCK32.151)
2387 INT WINAPI __WSAFDIsSet(SOCKET s, ws_fd_set32 *set)
2389 int i = set->fd_count;
2391 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
2393 while (i--)
2394 if (set->fd_array[i] == s) return 1;
2395 return 0;
2398 /***********************************************************************
2399 * WSAIsBlocking() (WINSOCK.114)(WSOCK32.114)
2401 BOOL WINAPI WSAIsBlocking(void)
2403 /* By default WinSock should set all its sockets to non-blocking mode
2404 * and poll in PeekMessage loop when processing "blocking" ones. This
2405 * function is supposed to tell if the program is in this loop. Our
2406 * blocking calls are truly blocking so we always return FALSE.
2408 * Note: It is allowed to call this function without prior WSAStartup().
2411 TRACE("\n");
2412 return FALSE;
2415 /***********************************************************************
2416 * WSACancelBlockingCall() (WINSOCK.113)(WSOCK32.113)
2418 INT WINAPI WSACancelBlockingCall(void)
2420 LPWSINFO pwsi = wsi_find(GetCurrentTask());
2422 TRACE("(%08x)\n", (unsigned)pwsi);
2424 if( pwsi ) return 0;
2425 return SOCKET_ERROR;
2429 /***********************************************************************
2430 * WSASetBlockingHook16() (WINSOCK.109)
2432 FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
2434 FARPROC16 prev;
2435 LPWSINFO pwsi = wsi_find(GetCurrentTask());
2437 TRACE("(%08x): hook %08x\n",
2438 (unsigned)pwsi, (unsigned) lpBlockFunc);
2439 if( pwsi )
2441 prev = (FARPROC16)pwsi->blocking_hook;
2442 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2443 pwsi->flags &= ~WSI_BLOCKINGHOOK;
2444 return prev;
2446 return 0;
2450 /***********************************************************************
2451 * WSASetBlockingHook32()
2453 FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
2455 FARPROC prev;
2456 LPWSINFO pwsi = wsi_find(GetCurrentTask());
2458 TRACE("(%08x): hook %08x\n",
2459 (unsigned)pwsi, (unsigned) lpBlockFunc);
2460 if( pwsi ) {
2461 prev = (FARPROC)pwsi->blocking_hook;
2462 pwsi->blocking_hook = (DWORD)lpBlockFunc;
2463 pwsi->flags |= WSI_BLOCKINGHOOK;
2464 return prev;
2466 return NULL;
2470 /***********************************************************************
2471 * WSAUnhookBlockingHook16() (WINSOCK.110)
2473 INT16 WINAPI WSAUnhookBlockingHook16(void)
2475 LPWSINFO pwsi = wsi_find(GetCurrentTask());
2477 TRACE("(%08x)\n", (unsigned)pwsi);
2478 if( pwsi ) return (INT16)(pwsi->blocking_hook = 0);
2479 return SOCKET_ERROR;
2483 /***********************************************************************
2484 * WSAUnhookBlockingHook32()
2486 INT WINAPI WSAUnhookBlockingHook(void)
2488 LPWSINFO pwsi = wsi_find(GetCurrentTask());
2490 TRACE("(%08x)\n", (unsigned)pwsi);
2491 if( pwsi )
2493 pwsi->blocking_hook = 0;
2494 pwsi->flags &= ~WSI_BLOCKINGHOOK;
2495 return 0;
2497 return SOCKET_ERROR;
2501 * TCP/IP action codes.
2505 #define WSCNTL_TCPIP_QUERY_INFO 0x00000000
2506 #define WSCNTL_TCPIP_SET_INFO 0x00000001
2507 #define WSCNTL_TCPIP_ICMP_ECHO 0x00000002
2508 #define WSCNTL_TCPIP_TEST 0x00000003
2511 /***********************************************************************
2512 * WsControl()
2514 * WsControl seems to be an undocumented Win95 function. A lot of
2515 * discussion about WsControl can be found on the net, e.g.
2516 * Subject: Re: WSOCK32.DLL WsControl Exported Function
2517 * From: "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
2518 * Date: 1997/08/17
2521 DWORD WINAPI WsControl(DWORD protocoll,DWORD action,
2522 LPVOID inbuf,LPDWORD inbuflen,
2523 LPVOID outbuf,LPDWORD outbuflen)
2526 switch (action) {
2527 case WSCNTL_TCPIP_ICMP_ECHO:
2529 unsigned int addr = *(unsigned int*)inbuf;
2530 #if 0
2531 int timeout= *(unsigned int*)(inbuf+4);
2532 short x1 = *(unsigned short*)(inbuf+8);
2533 short sendbufsize = *(unsigned short*)(inbuf+10);
2534 char x2 = *(unsigned char*)(inbuf+12);
2535 char ttl = *(unsigned char*)(inbuf+13);
2536 char service = *(unsigned char*)(inbuf+14);
2537 char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
2538 #endif
2540 FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr);
2541 break;
2543 default:
2544 FIXME("(%lx,%lx,%p,%p,%p,%p) stub\n",
2545 protocoll,action,inbuf,inbuflen,outbuf,outbuflen);
2547 return FALSE;
2549 /*********************************************************
2550 * WS_s_perror WSOCK32.1108
2552 void WINAPI WS_s_perror(LPCSTR message)
2554 FIXME("(%s): stub\n",message);
2555 return;
2559 /* ----------------------------------- end of API stuff */
2561 /* ----------------------------------- helper functions -
2563 * TODO: Merge WS_dup_..() stuff into one function that
2564 * would operate with a generic structure containing internal
2565 * pointers (via a template of some kind).
2568 static int list_size(char** l, int item_size)
2570 int i,j = 0;
2571 if(l)
2572 { for(i=0;l[i];i++)
2573 j += (item_size) ? item_size : strlen(l[i]) + 1;
2574 j += (i + 1) * sizeof(char*); }
2575 return j;
2578 static int list_dup(char** l_src, char* ref, char* base, int item_size)
2580 /* base is either either equal to ref or 0 or SEGPTR */
2582 char* p = ref;
2583 char** l_to = (char**)ref;
2584 int i,j,k;
2586 for(j=0;l_src[j];j++) ;
2587 p += (j + 1) * sizeof(char*);
2588 for(i=0;i<j;i++)
2589 { l_to[i] = base + (p - ref);
2590 k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
2591 memcpy(p, l_src[i], k); p += k; }
2592 l_to[i] = NULL;
2593 return (p - ref);
2596 /* ----- hostent */
2598 static int hostent_size(struct hostent* p_he)
2600 int size = 0;
2601 if( p_he )
2602 { size = sizeof(struct hostent);
2603 size += strlen(p_he->h_name) + 1;
2604 size += list_size(p_he->h_aliases, 0);
2605 size += list_size(p_he->h_addr_list, p_he->h_length ); }
2606 return size;
2609 int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
2611 /* Convert hostent structure into ws_hostent so that the data fits
2612 * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or
2613 * relative to pwsi->buffer depending on "flag" value. Returns size
2614 * of the data copied (also in the pwsi->buflen).
2617 int size = hostent_size(p_he);
2619 if( size )
2621 struct ws_hostent* p_to;
2622 char* p_name,*p_aliases,*p_addr,*p_base,*p;
2624 _check_buffer_he(pwsi, size);
2625 p_to = (struct ws_hostent*)pwsi->he;
2626 p = (char*)pwsi->he;
2627 p_base = (flag & WS_DUP_OFFSET) ? NULL
2628 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2629 p += sizeof(struct ws_hostent);
2630 p_name = p;
2631 strcpy(p, p_he->h_name); p += strlen(p) + 1;
2632 p_aliases = p;
2633 p += list_dup(p_he->h_aliases, p, p_base + (p - (char*)pwsi->he), 0);
2634 p_addr = p;
2635 list_dup(p_he->h_addr_list, p, p_base + (p - (char*)pwsi->he), p_he->h_length);
2637 p_to->h_addrtype = (INT16)p_he->h_addrtype;
2638 p_to->h_length = (INT16)p_he->h_length;
2639 p_to->h_name = (SEGPTR)(p_base + (p_name - (char*)pwsi->he));
2640 p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - (char*)pwsi->he));
2641 p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - (char*)pwsi->he));
2643 size += (sizeof(struct ws_hostent) - sizeof(struct hostent));
2645 return size;
2648 /* ----- protoent */
2650 static int protoent_size(struct protoent* p_pe)
2652 int size = 0;
2653 if( p_pe )
2654 { size = sizeof(struct protoent);
2655 size += strlen(p_pe->p_name) + 1;
2656 size += list_size(p_pe->p_aliases, 0); }
2657 return size;
2660 int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
2662 int size = protoent_size(p_pe);
2663 if( size )
2665 struct ws_protoent* p_to;
2666 char* p_name,*p_aliases,*p_base,*p;
2668 _check_buffer_pe(pwsi, size);
2669 p_to = (struct ws_protoent*)pwsi->pe;
2670 p = (char*)pwsi->pe;
2671 p_base = (flag & WS_DUP_OFFSET) ? NULL
2672 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2673 p += sizeof(struct ws_protoent);
2674 p_name = p;
2675 strcpy(p, p_pe->p_name); p += strlen(p) + 1;
2676 p_aliases = p;
2677 list_dup(p_pe->p_aliases, p, p_base + (p - (char*)pwsi->pe), 0);
2679 p_to->p_proto = (INT16)p_pe->p_proto;
2680 p_to->p_name = (SEGPTR)(p_base) + (p_name - (char*)pwsi->pe);
2681 p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - (char*)pwsi->pe));
2683 size += (sizeof(struct ws_protoent) - sizeof(struct protoent));
2685 return size;
2688 /* ----- servent */
2690 static int servent_size(struct servent* p_se)
2692 int size = 0;
2693 if( p_se )
2694 { size += sizeof(struct servent);
2695 size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
2696 size += list_size(p_se->s_aliases, 0); }
2697 return size;
2700 int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
2702 int size = servent_size(p_se);
2703 if( size )
2705 struct ws_servent* p_to;
2706 char* p_name,*p_aliases,*p_proto,*p_base,*p;
2708 _check_buffer_se(pwsi, size);
2709 p_to = (struct ws_servent*)pwsi->se;
2710 p = (char*)pwsi->se;
2711 p_base = (flag & WS_DUP_OFFSET) ? NULL
2712 : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
2713 p += sizeof(struct ws_servent);
2714 p_name = p;
2715 strcpy(p, p_se->s_name); p += strlen(p) + 1;
2716 p_proto = p;
2717 strcpy(p, p_se->s_proto); p += strlen(p) + 1;
2718 p_aliases = p;
2719 list_dup(p_se->s_aliases, p, p_base + (p - (char*)pwsi->se), 0);
2721 p_to->s_port = (INT16)p_se->s_port;
2722 p_to->s_name = (SEGPTR)(p_base + (p_name - (char*)pwsi->se));
2723 p_to->s_proto = (SEGPTR)(p_base + (p_proto - (char*)pwsi->se));
2724 p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - (char*)pwsi->se));
2726 size += (sizeof(struct ws_servent) - sizeof(struct servent));
2728 return size;
2731 /* ----------------------------------- error handling */
2733 UINT16 wsaErrno(void)
2735 int loc_errno = errno;
2736 #ifdef HAVE_STRERROR
2737 WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
2738 #else
2739 WARN("errno %d\n", loc_errno);
2740 #endif
2742 switch(loc_errno)
2744 case EINTR: return WSAEINTR;
2745 case EBADF: return WSAEBADF;
2746 case EACCES: return WSAEACCES;
2747 case EFAULT: return WSAEFAULT;
2748 case EINVAL: return WSAEINVAL;
2749 case EMFILE: return WSAEMFILE;
2750 case EWOULDBLOCK: return WSAEWOULDBLOCK;
2751 case EINPROGRESS: return WSAEINPROGRESS;
2752 case EALREADY: return WSAEALREADY;
2753 case ENOTSOCK: return WSAENOTSOCK;
2754 case EDESTADDRREQ: return WSAEDESTADDRREQ;
2755 case EMSGSIZE: return WSAEMSGSIZE;
2756 case EPROTOTYPE: return WSAEPROTOTYPE;
2757 case ENOPROTOOPT: return WSAENOPROTOOPT;
2758 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
2759 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
2760 case EOPNOTSUPP: return WSAEOPNOTSUPP;
2761 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
2762 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
2763 case EADDRINUSE: return WSAEADDRINUSE;
2764 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
2765 case ENETDOWN: return WSAENETDOWN;
2766 case ENETUNREACH: return WSAENETUNREACH;
2767 case ENETRESET: return WSAENETRESET;
2768 case ECONNABORTED: return WSAECONNABORTED;
2769 case EPIPE:
2770 case ECONNRESET: return WSAECONNRESET;
2771 case ENOBUFS: return WSAENOBUFS;
2772 case EISCONN: return WSAEISCONN;
2773 case ENOTCONN: return WSAENOTCONN;
2774 case ESHUTDOWN: return WSAESHUTDOWN;
2775 case ETOOMANYREFS: return WSAETOOMANYREFS;
2776 case ETIMEDOUT: return WSAETIMEDOUT;
2777 case ECONNREFUSED: return WSAECONNREFUSED;
2778 case ELOOP: return WSAELOOP;
2779 case ENAMETOOLONG: return WSAENAMETOOLONG;
2780 case EHOSTDOWN: return WSAEHOSTDOWN;
2781 case EHOSTUNREACH: return WSAEHOSTUNREACH;
2782 case ENOTEMPTY: return WSAENOTEMPTY;
2783 #ifdef EPROCLIM
2784 case EPROCLIM: return WSAEPROCLIM;
2785 #endif
2786 #ifdef EUSERS
2787 case EUSERS: return WSAEUSERS;
2788 #endif
2789 #ifdef EDQUOT
2790 case EDQUOT: return WSAEDQUOT;
2791 #endif
2792 #ifdef ESTALE
2793 case ESTALE: return WSAESTALE;
2794 #endif
2795 #ifdef EREMOTE
2796 case EREMOTE: return WSAEREMOTE;
2797 #endif
2799 /* just in case we ever get here and there are no problems */
2800 case 0: return 0;
2801 default:
2802 WARN("Unknown errno %d!\n", loc_errno);
2803 return WSAEOPNOTSUPP;
2807 UINT16 wsaHerrno(void)
2809 int loc_errno = h_errno;
2811 WARN("h_errno %d.\n", loc_errno);
2813 switch(loc_errno)
2815 case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND;
2816 case TRY_AGAIN: return WSATRY_AGAIN;
2817 case NO_RECOVERY: return WSANO_RECOVERY;
2818 case NO_DATA: return WSANO_DATA;
2820 case 0: return 0;
2821 default:
2822 WARN("Unknown h_errno %d!\n", loc_errno);
2823 return WSAEOPNOTSUPP;