2 * based on Windows Sockets 1.1 specs
3 * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
5 * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
7 * NOTE: If you make any changes to fix a particular app, make sure
8 * they don't break something else like Netscape or telnet and ftp
9 * clients and servers (www.winsite.com got a lot of those).
16 #include <sys/types.h>
18 #include <sys/ioctl.h>
19 #ifdef HAVE_SYS_FILIO_H
20 # include <sys/filio.h>
22 #if defined(__svr4__) || defined(__sun)
23 #include <sys/ioccom.h>
24 #include <sys/sockio.h>
28 # include <sys/so_ioctl.h>
31 #ifdef HAVE_SYS_PARAM_H
32 # include <sys/param.h>
37 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <netinet/tcp.h>
40 #include <arpa/inet.h>
44 #ifdef HAVE_SYS_ERRNO_H
45 #include <sys/errno.h>
50 #ifdef HAVE_ARPA_NAMESER_H
51 # include <arpa/nameser.h>
57 #include "wine/winbase16.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
,
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
,
112 static INT _ws_tcp_ops
[] = {
118 static int _px_tcp_ops
[] = {
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
)
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;
140 /***********************************************************************
143 * Converts socket flags from Windows format.
145 static void convert_sockopt(INT
*level
, INT
*optname
)
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
);
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
);
167 /* ----------------------------------- Per-thread info (or per-process?) */
169 static LPWSINFO
wsi_find(HTASK16 hTask
)
171 TDB
* pTask
= (TDB
*)GlobalLock16(hTask
);
174 if( pTask
->pwsi
) return pTask
->pwsi
;
177 LPWSINFO pwsi
= _wsi_list
;
178 while( pwsi
&& pwsi
->tid
!= hTask
) pwsi
= pwsi
->next
;
180 WARN("(pwsi=0x%08x,task=0x%04x):Loose wsi struct! \n",
181 (unsigned)pwsi
, hTask
);
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
];
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));
213 do *p
++ = tolower(*name
); while(*name
++);
214 i
= (p
- (char*)(pwsi
->buffer
));
215 if( opt
) do *p
++ = tolower(*opt
); while(*opt
++);
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 */
227 #define wsfds16 ((ws_fd_set16*)wsfds)
228 #define wsfds32 ((ws_fd_set32*)wsfds)
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
);
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
);
262 static int fd_set_export( LPWSINFO pwsi
, fd_set
* fds
, fd_set
* exceptfds
, void* wsfds
, BOOL b32
)
266 /* translate local fd set into Winsock fd set, adding
267 * errors to exceptfds (only if app requested it) */
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
) )
283 if( FD_ISSET(fd
, fds
) )
285 if ( exceptfds
&& sock_error_p(fd
) )
287 FD_SET(fd
, exceptfds
);
291 wsfds32
->fd_array
[j
++] = wsfds32
->fd_array
[i
];
293 wsfds16
->fd_array
[j
++] = wsfds16
->fd_array
[i
];
298 if( b32
) wsfds32
->fd_count
= j
;
299 else wsfds16
->fd_count
= j
;
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
)
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 /***********************************************************************
347 * Initialize network IO.
349 BOOL
WINSOCK_Init(void)
352 for( i
= 0; i
< 3; i
++ )
353 FD_ZERO( __winsock_io_set
+ i
);
355 /* pipe used to wake up the winsock thread */
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];
366 /* Inititalize critical section */
367 InitializeCriticalSection( &__winsock_crst
);
368 MakeCriticalSectionGlobal( &__winsock_crst
);
373 /***********************************************************************
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 /***********************************************************************
390 static DWORD CALLBACK
WINSOCK_Thread( LPVOID arg
)
394 int num_pending
, max_fd
;
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 */
412 /* Flush the wake-up pipe */
413 if ( FD_ISSET( __wakeup_pipe
[0], &io_set
[EVENT_IO_READ
] ) )
418 while ( (ret
= read(__wakeup_pipe
[0], &tmpBuf
, 10)) == 10 );
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 /***********************************************************************
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 /***********************************************************************
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
);
462 /***********************************************************************
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
);
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,
492 #elif defined(__NetBSD__)
496 #elif defined(__FreeBSD__)
498 #elif defined(__OpenBSD__)
503 WS_MAX_SOCKETS_PER_PROCESS
,
504 WS_MAX_UDP_DATAGRAM
, (SEGPTR
)NULL
};
505 HTASK16 tid
= GetCurrentTask();
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 */
519 _WSHeap
= HeapCreate(HEAP_ZERO_MEMORY
, 8120, 32768);
520 if( !(_ws_stub
= WS_ALLOC(0x10)) )
522 ERR("Fatal: failed to create WinSock heap\n");
526 if( _WSHeap
== 0 ) return WSASYSNOTREADY
;
528 /* create socket array for this task */
530 pwsi
= wsi_find(GetCurrentTask());
533 TDB
* pTask
= (TDB
*)GlobalLock16( tid
);
535 if( (pwsi
= (LPWSINFO
)WS_ALLOC( sizeof(WSINFO
))) )
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 */
552 _wsi_list
->prev
= pwsi
;
553 pwsi
->next
= _wsi_list
;
557 else pwsi
->num_startup
++;
559 /* return winsock information */
561 memcpy(lpWSAData
, &WINSOCK_data
, sizeof(WINSOCK_data
));
563 TRACE("succeeded\n");
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.
591 if( --pwsi
->num_startup
> 0 ) return 0;
593 /* unlink socket control struct */
595 if( pwsi
== _wsi_list
)
596 _wsi_list
= pwsi
->next
;
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
)
619 WSAAsyncSelect( (SOCKET16
)WS_PTR2HANDLE(pwsi
->sock
+ i
), 0, 0, 0 );
621 close(pwsi
->sock
[i
].fd
); 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
);
633 memset( pwsi
, 0, sizeof(WSINFO
) );
638 INT WINAPI
WSACleanup(void)
640 HTASK16 hTask
= GetCurrentTask();
642 TRACE("(%04x)\n", hTask
);
645 LPWSINFO pwsi
= wsi_find(hTask
);
647 return WINSOCK_DeleteTaskWSI( (TDB
*)GlobalLock16(hTask
), pwsi
);
651 WINSOCK_Shutdown(); /* remove all outstanding DNS requests */
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
)
683 if( pwsi
->flags
& WSI_BLOCKINGCALL
) SetLastError(WSAEINPROGRESS
);
684 else if( WSI_CHECK_RANGE(pwsi
, pws
) ) return 1;
685 else SetLastError(WSAENOTSOCK
);
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
));
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
));
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
));
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
));
726 /* ----------------------------------- i/o APIs */
728 /***********************************************************************
729 * accept() (WSOCK32.1)
731 SOCKET WINAPI
WINSOCK_accept(SOCKET s
, struct sockaddr
*addr
,
734 ws_socket
* pws
= (ws_socket
*)WS_HANDLE2PTR((SOCKET16
)s
);
735 LPWSINFO pwsi
= wsi_find(GetCurrentTask());
737 struct ws_sockaddr_ipx
* addr2
= (struct ws_sockaddr_ipx
*)addr
;
740 TRACE("(%08x): socket %04x\n",
741 (unsigned)pwsi
, (UINT16
)s
);
742 if( _check_ws(pwsi
, pws
) )
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
);
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
);
763 if (addr
&& ((struct sockaddr_ipx
*)addr
)->sipx_family
== AF_IPX
) {
764 addr
= (struct sockaddr
*)
765 malloc(addrlen32
? *addrlen32
: sizeof(*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
);
778 else SetLastError(WSAENOBUFS
);
779 } else SetLastError(wsaErrno());
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
);
794 return INVALID_SOCKET
;
797 /***********************************************************************
798 * accept() (WINSOCK.1)
800 SOCKET16 WINAPI
WINSOCK_accept16(SOCKET16 s
, struct sockaddr
* addr
,
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 /***********************************************************************
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());
817 struct ws_sockaddr_ipx
* name2
= (struct ws_sockaddr_ipx
*)name
;
820 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
821 (unsigned)pwsi
, s
, (int) name
, namelen
);
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
;
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
);
845 if ( namelen
>= sizeof(*name
) )
847 if ( name
&& (((struct ws_sockaddr_in
*)name
)->sin_family
== AF_INET
849 || ((struct sockaddr_ipx
*)name
)->sipx_family
== AF_IPX
853 if ( bind(pws
->fd
, name
, namelen
) < 0 )
855 int loc_errno
= errno
;
856 WARN("\tfailure - errno = %i\n", errno
);
860 case EBADF
: SetLastError(WSAENOTSOCK
); break;
861 case EADDRNOTAVAIL
: SetLastError(WSAEINVAL
); break;
862 default: SetLastError(wsaErrno());break;
867 if (((struct sockaddr_ipx
*)name
)->sipx_family
== AF_IPX
)
870 return 0; /* success */
872 } else SetLastError(WSAEAFNOSUPPORT
);
873 } else SetLastError(WSAEFAULT
);
875 if (name
&& ((struct sockaddr_ipx
*)name
)->sipx_family
== AF_IPX
)
882 /***********************************************************************
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
) )
904 if( pws
->psop
) WSAAsyncSelect( s
, 0, 0, 0 );
907 pws
->flags
= (unsigned)pwsi
->last_free
;
908 pwsi
->last_free
= pws
- &pwsi
->sock
[0]; /* add to free list */
912 SetLastError((errno
== EBADF
) ? WSAENOTSOCK
: wsaErrno());
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());
933 struct ws_sockaddr_ipx
* name2
= (struct ws_sockaddr_ipx
*)name
;
936 TRACE("(%08x): socket %04x, ptr %8x, length %d\n",
937 (unsigned)pwsi
, s
, (int) name
, namelen
);
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
;
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
);
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
967 * FIXME: Do we have to post a notification message
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
);
976 EVENT_DeleteIO( pws
->fd
, EVENT_IO_READ
);
977 if( pws
->flags
& WS_FD_WRITE
)
978 EVENT_AddIO( pws
->fd
, EVENT_IO_WRITE
);
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
);
986 if (((struct sockaddr_ipx
*)name
)->sipx_family
== AF_IPX
)
991 SetLastError((errno
== EINPROGRESS
) ? WSAEWOULDBLOCK
: wsaErrno());
994 if (name
&& ((struct sockaddr_ipx
*)name
)->sipx_family
== AF_IPX
)
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
,
1014 ws_socket
* pws
= (ws_socket
*)WS_HANDLE2PTR(s
);
1015 LPWSINFO pwsi
= wsi_find(GetCurrentTask());
1017 struct ws_sockaddr_ipx
* name2
= (struct ws_sockaddr_ipx
*)name
;
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) {
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
);
1040 SetLastError((h_errno
< 0) ? wsaErrno() : wsaHerrno());
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
);
1054 return SOCKET_ERROR
;
1057 /***********************************************************************
1058 * getpeername() (WINSOCK.5)
1060 INT16 WINAPI
WINSOCK_getpeername16(SOCKET16 s
, struct sockaddr
*name
,
1063 INT namelen32
= *namelen16
;
1064 INT retVal
= WINSOCK_getpeername( s
, name
, &namelen32
);
1067 dump_sockaddr(name
);
1070 *namelen16
= namelen32
;
1071 return (INT16
)retVal
;
1074 /***********************************************************************
1075 * getsockname() (WSOCK32.6)
1077 INT WINAPI
WINSOCK_getsockname(SOCKET s
, struct sockaddr
*name
,
1080 ws_socket
* pws
= (ws_socket
*)WS_HANDLE2PTR(s
);
1081 LPWSINFO pwsi
= wsi_find(GetCurrentTask());
1083 struct ws_sockaddr_ipx
* name2
= (struct ws_sockaddr_ipx
*)name
;
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) {
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
);
1106 SetLastError((h_errno
< 0) ? wsaErrno() : wsaHerrno());
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
);
1120 return SOCKET_ERROR
;
1123 /***********************************************************************
1124 * getsockname() (WINSOCK.6)
1126 INT16 WINAPI
WINSOCK_getsockname16(SOCKET16 s
, struct sockaddr
*name
,
1133 INT namelen32
= *namelen16
;
1134 retVal
= WINSOCK_getsockname( s
, name
, &namelen32
);
1135 *namelen16
= namelen32
;
1138 dump_sockaddr(name
);
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 )
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
)
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());
1218 char* s
= inet_ntoa(in
);
1221 if( pwsi
->dbuffer
== NULL
)
1222 if((pwsi
->dbuffer
= (char*) SEGPTR_ALLOC(32)) == NULL
)
1224 SetLastError(WSAENOBUFS
);
1227 strncpy(pwsi
->dbuffer
, s
, 32 );
1228 return pwsi
->dbuffer
;
1230 SetLastError(wsaErrno());
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
) )
1263 if( pws
->psop
&& *argp
== 0 )
1265 /* AsyncSelect()'ed sockets are always nonblocking */
1266 SetLastError(WSAEINVAL
);
1267 return SOCKET_ERROR
;
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
;
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)
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 */
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
,
1348 if( _check_ws(pwsi
, pws
) )
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 */
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());
1385 struct ws_sockaddr_ipx
* from2
= (struct ws_sockaddr_ipx
*)from
;
1388 TRACE("(%08x): socket %04x, ptr %08x, "
1389 "len %d, flags %d\n", (unsigned)pwsi
, s
, (unsigned)buf
,
1392 if( from
) dump_sockaddr(from
);
1393 else DPRINTF("from = NULL\n");
1396 if( _check_ws(pwsi
, pws
) )
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 */
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
);
1420 return (INT16
)length
;
1422 SetLastError(wsaErrno());
1424 else SetLastError(WSAENOTSOCK
);
1425 WARN(" -> ERROR\n");
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
);
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
)
1449 INT
*p
= &fromlen32
;
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
);
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
) )
1497 wsfds32
->fd_array
[j
++] = wsfds32
->fd_array
[i
];
1499 wsfds16
->fd_array
[j
++] = wsfds16
->fd_array
[i
];
1503 wsfds32
->fd_count
= j
;
1505 wsfds16
->fd_count
= j
;
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
) )
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());
1581 struct ws_sockaddr_ipx
* to2
= (struct ws_sockaddr_ipx
*)to
;
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
) )
1590 if (to
&& ((struct ws_sockaddr_ipx
*)to
)->sipx_family
== WS_AF_PUP
)
1591 ((struct ws_sockaddr_ipx
*)to
)->sipx_family
= AF_UNSPEC
;
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
);
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 */
1615 if (to
&& ((struct sockaddr_ipx
*)to
)->sipx_family
== AF_IPX
) {
1622 else SetLastError(WSAENOTSOCK
);
1624 if (to
&& ((struct sockaddr_ipx
*)to
)->sipx_family
== AF_IPX
) {
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
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
) )
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
);
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
;
1716 case 2: /* drop all */
1721 WSAAsyncSelect( s
, 0, 0, 0 );
1725 if (shutdown(pws
->fd
, how
) == 0)
1729 pws
->flags
&= ~(WS_FD_CONNECTED
| WS_FD_LISTENING
);
1730 pws
->flags
|= WS_FD_INACTIVE
;
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
);
1763 /* check the socket family */
1767 case WS_AF_IPX
: af
= AF_IPX
;
1770 case AF_UNSPEC
: break;
1771 default: SetLastError(WSAEAFNOSUPPORT
);
1772 return INVALID_SOCKET
;
1775 /* check the socket type */
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? */
1793 if (type
== SOCK_STREAM
) { af
= AF_INET
; break; }
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
));
1807 pnew
->flags
|= WS_FD_INACTIVE
;
1808 return (SOCKET16
)WS_PTR2HANDLE(pnew
);
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");
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());
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
);
1863 SetLastError(WSAENOBUFS
);
1865 SetLastError((h_errno
< 0) ? wsaErrno() : wsaHerrno());
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
,
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());
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());
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());
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());
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());
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
);
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());
1998 struct servent
* serv
;
1999 int i
= wsi_strtolo( pwsi
, name
, proto
);
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
);
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());
2038 struct servent
* serv
;
2039 int i
= wsi_strtolo( pwsi
, proto
, NULL
);
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
);
2052 SEGPTR WINAPI
WINSOCK_getservbyport16(INT16 port
, const char *proto
)
2054 struct WIN_servent
* retval
;
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
)
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
);
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
;
2113 DWORD dwEvent
, dwErrBytes
;
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
;
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
);
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
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
] );
2152 FD_CLR( fd
, &event_set
[EVENT_IO_READ
] ); /* reenabled by the next accept() */
2153 dwEvent
= WSAMAKESELECTREPLY( WS_FD_ACCEPT
, 0 );
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
] );
2178 FD_CLR( fd
, &event_set
[EVENT_IO_READ
] );
2179 if( flags
& WS_FD_WRITE
)
2180 FD_SET( fd
, &event_set
[EVENT_IO_WRITE
] );
2182 FD_CLR( fd
, &event_set
[EVENT_IO_WRITE
] );
2187 /* failure - do read() to get correct errno */
2189 if( read( fd
, &dwErrBytes
, sizeof(dwErrBytes
) ) == -1 )
2191 dwEvent
= WSAMAKESELECTREPLY( WS_FD_CONNECT
, wsaErrno() );
2195 /* otherwise bPost stays FALSE, should probably clear event_set */
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
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
] );
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 */
2224 if( !val
&& ioctl( fd
, FIONREAD
, (char*)&dwErrBytes
) == -1 )
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 );
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
)
2248 case 0: errno
= ENETDOWN
; /* soft reset, fall through */
2249 case -1: /* hard reset */
2250 dwEvent
= WSAMAKESELECTREPLY( WS_FD_CLOSE
, wsaErrno() );
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
)--;
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
);
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
) )
2298 if( (psop
= pws
->psop
) )
2300 /* delete previous control struct */
2302 if( psop
== __ws_select_list
)
2303 __ws_select_list
= psop
->next
;
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
);
2323 psop
= (ws_select_op
*)WS_ALLOC(sizeof(ws_select_op
));
2326 int sock_type
, bytes
= sizeof(int);
2328 WINSOCK_unblock_io( pws
->fd
, TRUE
);
2331 psop
->next
= __ws_select_list
;
2332 if( __ws_select_list
)
2333 __ws_select_list
->prev
= psop
;
2334 __ws_select_list
= 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
);
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
);
2380 if (set
->fd_array
[i
] == s
) return 1;
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
);
2394 if (set
->fd_array
[i
] == s
) return 1;
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().
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
)
2435 LPWSINFO pwsi
= wsi_find(GetCurrentTask());
2437 TRACE("(%08x): hook %08x\n",
2438 (unsigned)pwsi
, (unsigned) lpBlockFunc
);
2441 prev
= (FARPROC16
)pwsi
->blocking_hook
;
2442 pwsi
->blocking_hook
= (DWORD
)lpBlockFunc
;
2443 pwsi
->flags
&= ~WSI_BLOCKINGHOOK
;
2450 /***********************************************************************
2451 * WSASetBlockingHook32()
2453 FARPROC WINAPI
WSASetBlockingHook(FARPROC lpBlockFunc
)
2456 LPWSINFO pwsi
= wsi_find(GetCurrentTask());
2458 TRACE("(%08x): hook %08x\n",
2459 (unsigned)pwsi
, (unsigned) lpBlockFunc
);
2461 prev
= (FARPROC
)pwsi
->blocking_hook
;
2462 pwsi
->blocking_hook
= (DWORD
)lpBlockFunc
;
2463 pwsi
->flags
|= WSI_BLOCKINGHOOK
;
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
);
2493 pwsi
->blocking_hook
= 0;
2494 pwsi
->flags
&= ~WSI_BLOCKINGHOOK
;
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 /***********************************************************************
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>
2521 DWORD WINAPI
WsControl(DWORD protocoll
,DWORD action
,
2522 LPVOID inbuf
,LPDWORD inbuflen
,
2523 LPVOID outbuf
,LPDWORD outbuflen
)
2527 case WSCNTL_TCPIP_ICMP_ECHO
:
2529 unsigned int addr
= *(unsigned int*)inbuf
;
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*/
2540 FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr
);
2544 FIXME("(%lx,%lx,%p,%p,%p,%p) stub\n",
2545 protocoll
,action
,inbuf
,inbuflen
,outbuf
,outbuflen
);
2549 /*********************************************************
2550 * WS_s_perror WSOCK32.1108
2552 void WINAPI
WS_s_perror(LPCSTR message
)
2554 FIXME("(%s): stub\n",message
);
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
)
2573 j
+= (item_size
) ? item_size
: strlen(l
[i
]) + 1;
2574 j
+= (i
+ 1) * sizeof(char*); }
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 */
2583 char** l_to
= (char**)ref
;
2586 for(j
=0;l_src
[j
];j
++) ;
2587 p
+= (j
+ 1) * sizeof(char*);
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
; }
2598 static int hostent_size(struct hostent
* 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
); }
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
);
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
);
2631 strcpy(p
, p_he
->h_name
); p
+= strlen(p
) + 1;
2633 p
+= list_dup(p_he
->h_aliases
, p
, p_base
+ (p
- (char*)pwsi
->he
), 0);
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
));
2648 /* ----- protoent */
2650 static int protoent_size(struct protoent
* p_pe
)
2654 { size
= sizeof(struct protoent
);
2655 size
+= strlen(p_pe
->p_name
) + 1;
2656 size
+= list_size(p_pe
->p_aliases
, 0); }
2660 int WS_dup_pe(LPWSINFO pwsi
, struct protoent
* p_pe
, int flag
)
2662 int size
= protoent_size(p_pe
);
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
);
2675 strcpy(p
, p_pe
->p_name
); p
+= strlen(p
) + 1;
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
));
2690 static int servent_size(struct servent
* 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); }
2700 int WS_dup_se(LPWSINFO pwsi
, struct servent
* p_se
, int flag
)
2702 int size
= servent_size(p_se
);
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
);
2715 strcpy(p
, p_se
->s_name
); p
+= strlen(p
) + 1;
2717 strcpy(p
, p_se
->s_proto
); p
+= strlen(p
) + 1;
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
));
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
));
2739 WARN("errno %d\n", 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
;
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
;
2784 case EPROCLIM
: return WSAEPROCLIM
;
2787 case EUSERS
: return WSAEUSERS
;
2790 case EDQUOT
: return WSAEDQUOT
;
2793 case ESTALE
: return WSAESTALE
;
2796 case EREMOTE
: return WSAEREMOTE
;
2799 /* just in case we ever get here and there are no problems */
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
);
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
;
2822 WARN("Unknown h_errno %d!\n", loc_errno
);
2823 return WSAEOPNOTSUPP
;