#define NONAMELESSUNION
#define NONAMELESSSTRUCT
-#include "wine/winbase16.h"
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
+#include "winnls.h"
#include "winsock2.h"
+#include "mswsock.h"
#include "ws2tcpip.h"
#include "wsipx.h"
-#include "wine/winsock16.h"
#include "winnt.h"
-#include "wownt32.h"
#include "iphlpapi.h"
#include "thread.h"
#include "wine/server.h"
#include "wine/debug.h"
+#ifdef HAVE_IPX
+# include "wsnwlink.h"
+#endif
+
+
#ifdef __FreeBSD__
# define sipx_network sipx_addr.x_net
# define sipx_node sipx_addr.x_host.c_host
/* critical section to protect some non-rentrant net function */
extern CRITICAL_SECTION csWSgetXXXbyYYY;
-#define DEBUG_SOCKADDR 0
-#define dump_sockaddr(a) \
- DPRINTF("sockaddr_in: family %d, address %s, port %d\n", \
- ((struct sockaddr_in *)a)->sin_family, \
- inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
- ntohs(((struct sockaddr_in *)a)->sin_port))
+inline static const char *debugstr_sockaddr( const struct WS_sockaddr *a )
+{
+ if (!a) return "(nil)";
+ return wine_dbg_sprintf("{ family %d, address %s, port %d }",
+ ((struct sockaddr_in *)a)->sin_family,
+ inet_ntoa(((struct sockaddr_in *)a)->sin_addr),
+ ntohs(((struct sockaddr_in *)a)->sin_port));
+}
/* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
#define SOCKET2HANDLE(s) ((HANDLE)(s))
/* ws_... struct conversion flags */
-#define WS_DUP_LINEAR 0x0001
-#define WS_DUP_SEGPTR 0x0002 /* internal pointers are SEGPTRs */
- /* by default, internal pointers are linear */
typedef struct /* WSAAsyncSelect() control struct */
{
HANDLE service, event, sock;
#define WS_MAX_UDP_DATAGRAM 1024
static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
-static void *he_buffer; /* typecast for Win16/32 ws_hostent */
-static SEGPTR he_buffer_seg;
-static void *se_buffer; /* typecast for Win16/32 ws_servent */
-static SEGPTR se_buffer_seg;
-static void *pe_buffer; /* typecast for Win16/32 ws_protoent */
-static SEGPTR pe_buffer_seg;
-static char* local_buffer;
-static SEGPTR dbuffer_seg;
+static struct WS_hostent *he_buffer; /* typecast for Win32 ws_hostent */
+static struct WS_servent *se_buffer; /* typecast for Win32 ws_servent */
+static struct WS_protoent *pe_buffer; /* typecast for Win32 ws_protoent */
static INT num_startup; /* reference counter */
static FARPROC blocking_hook = WSA_DefaultBlockingHook;
/* function prototypes */
-static int WS_dup_he(struct hostent* p_he, int flag);
-static int WS_dup_pe(struct protoent* p_pe, int flag);
-static int WS_dup_se(struct servent* p_se, int flag);
-
-typedef void WIN_hostent;
-typedef void WIN_protoent;
-typedef void WIN_servent;
+static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
+static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe);
+static struct WS_servent *WS_dup_se(const struct servent* p_se);
int WSAIOCTL_GetInterfaceCount(void);
int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
-UINT16 wsaErrno(void);
-UINT16 wsaHerrno(int errnr);
-
-static HANDLE _WSHeap = 0;
-
-#define WS_ALLOC(size) \
- HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
-#define WS_FREE(ptr) \
- HeapFree(_WSHeap, 0, (ptr) )
+UINT wsaErrno(void);
+UINT wsaHerrno(int errnr);
#define MAP_OPTION(opt) { WS_##opt, opt }
MAP_OPTION( IP_ADD_MEMBERSHIP ),
MAP_OPTION( IP_DROP_MEMBERSHIP ),
MAP_OPTION( IP_OPTIONS ),
+#ifdef IP_HDRINCL
MAP_OPTION( IP_HDRINCL ),
+#endif
MAP_OPTION( IP_TOS ),
MAP_OPTION( IP_TTL ),
{ 0, 0 }
};
-static DWORD opentype_tls_index = -1; /* TLS index for SO_OPENTYPE flag */
+static DWORD opentype_tls_index = TLS_OUT_OF_INDEXES; /* TLS index for SO_OPENTYPE flag */
inline static DWORD NtStatusToWSAError ( const DWORD status )
{
return err;
}
-static char* check_buffer(int size);
-
-inline static int _get_sock_fd(SOCKET s)
+inline static int get_sock_fd( SOCKET s, DWORD access, int *flags )
{
int fd;
-
- if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), GENERIC_READ, &fd, NULL, NULL ) ))
+ if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, flags ) ))
return -1;
return fd;
}
-inline static int _get_sock_fd_type( SOCKET s, DWORD access, enum fd_type *type, int *flags )
+inline static void release_sock_fd( SOCKET s, int fd )
{
- int fd;
- if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, type, flags ) )) return -1;
- if ( ( (access & GENERIC_READ) && (*flags & FD_FLAG_RECV_SHUTDOWN ) ) ||
- ( (access & GENERIC_WRITE) && (*flags & FD_FLAG_SEND_SHUTDOWN ) ) )
- {
- close (fd);
- WSASetLastError ( WSAESHUTDOWN );
- return -1;
- }
- return fd;
+ wine_server_release_fd( SOCKET2HANDLE(s), fd );
}
static void _enable_event( HANDLE s, unsigned int event,
{
/* delete scratch buffers */
- UnMapLS( he_buffer_seg );
- UnMapLS( se_buffer_seg );
- UnMapLS( pe_buffer_seg );
- UnMapLS( dbuffer_seg );
if (he_buffer) HeapFree( GetProcessHeap(), 0, he_buffer );
if (se_buffer) HeapFree( GetProcessHeap(), 0, se_buffer );
if (pe_buffer) HeapFree( GetProcessHeap(), 0, pe_buffer );
- if (local_buffer) HeapFree( GetProcessHeap(), 0, local_buffer );
he_buffer = NULL;
se_buffer = NULL;
pe_buffer = NULL;
- local_buffer = NULL;
- he_buffer_seg = 0;
- se_buffer_seg = 0;
- pe_buffer_seg = 0;
- dbuffer_seg = 0;
num_startup = 0;
}
return 0;
}
+static inline BOOL is_timeout_option( int optname )
+{
+#ifdef SO_RCVTIMEO
+ if (optname == SO_RCVTIMEO) return TRUE;
+#endif
+#ifdef SO_SNDTIMEO
+ if (optname == SO_SNDTIMEO) return TRUE;
+#endif
+ return FALSE;
+}
+
/* ----------------------------------- Per-thread info (or per-process?) */
-static int wsi_strtolo(const char* name, const char* opt)
+static char *strdup_lower(const char *str)
{
- /* Stuff a lowercase copy of the string into the local buffer */
-
- int i = strlen(name) + 2;
- char* p = check_buffer(i + ((opt)?strlen(opt):0));
+ int i;
+ char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
- if( p )
+ if (ret)
{
- do *p++ = tolower(*name); while(*name++);
- i = (p - local_buffer);
- if( opt ) do *p++ = tolower(*opt); while(*opt++);
- return i;
+ for (i = 0; str[i]; i++) ret[i] = tolower(str[i]);
+ ret[i] = 0;
}
- return 0;
+ else SetLastError(WSAENOBUFS);
+ return ret;
}
-static fd_set* fd_set_import( fd_set* fds, void* wsfds, int* highfd, int lfd[], BOOL b32 )
+static fd_set* fd_set_import( fd_set* fds, const WS_fd_set* wsfds, int access, int* highfd, int lfd[] )
{
/* translate Winsock fd set into local fd set */
-
if( wsfds )
{
-#define wsfds16 ((ws_fd_set16*)wsfds)
-#define wsfds32 ((WS_fd_set*)wsfds)
- int i, count;
-
- FD_ZERO(fds);
- count = b32 ? wsfds32->fd_count : wsfds16->fd_count;
+ unsigned int i;
- for( i = 0; i < count; i++ )
- {
- int s = (b32) ? wsfds32->fd_array[i]
- : wsfds16->fd_array[i];
- int fd = _get_sock_fd(s);
- if (fd != -1)
- {
- lfd[ i ] = fd;
- if( fd > *highfd ) *highfd = fd;
- FD_SET(fd, fds);
- }
- else lfd[ i ] = -1;
- }
-#undef wsfds32
-#undef wsfds16
- return fds;
+ FD_ZERO(fds);
+ for( i = 0; i < wsfds->fd_count; i++ )
+ {
+ int s = wsfds->fd_array[i];
+ int fd = get_sock_fd( s, access, NULL );
+ if (fd != -1)
+ {
+ lfd[ i ] = fd;
+ if( fd > *highfd ) *highfd = fd;
+ FD_SET(fd, fds);
+ }
+ else lfd[ i ] = -1;
+ }
+ return fds;
}
return NULL;
}
return optval != 0;
}
-static int fd_set_export( fd_set* fds, fd_set* exceptfds, void* wsfds, int lfd[], BOOL b32 )
+static int fd_set_export( const fd_set* fds, fd_set* exceptfds, WS_fd_set* wsfds, int lfd[] )
{
int num_err = 0;
if( wsfds )
{
-#define wsfds16 ((ws_fd_set16*)wsfds)
-#define wsfds32 ((WS_fd_set*)wsfds)
- int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
+ int i, j, count = wsfds->fd_count;
for( i = 0, j = 0; i < count; i++ )
{
- if( lfd[i] >= 0 )
- {
- int fd = lfd[i];
- if( FD_ISSET(fd, fds) )
- {
- if ( exceptfds && sock_error_p(fd) )
- {
- FD_SET(fd, exceptfds);
- num_err++;
- }
- else if( b32 )
- wsfds32->fd_array[j++] = wsfds32->fd_array[i];
- else
- wsfds16->fd_array[j++] = wsfds16->fd_array[i];
- }
- close(fd);
- lfd[i] = -1;
- }
+ int fd = lfd[i];
+ SOCKET s = wsfds->fd_array[i];
+ if (fd == -1) continue;
+ if( FD_ISSET(fd, fds) )
+ {
+ if ( exceptfds && sock_error_p(fd) )
+ {
+ FD_SET(fd, exceptfds);
+ num_err++;
+ }
+ else wsfds->fd_array[j++] = s;
+ }
+ release_sock_fd( s, fd );
}
-
- if( b32 ) wsfds32->fd_count = j;
- else wsfds16->fd_count = j;
-
- TRACE("\n");
-#undef wsfds32
-#undef wsfds16
+ wsfds->fd_count = j;
}
return num_err;
}
-static void fd_set_unimport( void* wsfds, int lfd[], BOOL b32 )
+static void fd_set_unimport( WS_fd_set* wsfds, int lfd[] )
{
if ( wsfds )
{
-#define wsfds16 ((ws_fd_set16*)wsfds)
-#define wsfds32 ((WS_fd_set*)wsfds)
- int i, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
+ unsigned int i;
- for( i = 0; i < count; i++ )
- if ( lfd[i] >= 0 )
- close(lfd[i]);
-
- TRACE("\n");
-#undef wsfds32
-#undef wsfds16
+ for( i = 0; i < wsfds->fd_count; i++ )
+ if ( lfd[i] >= 0 ) release_sock_fd( wsfds->fd_array[i], lfd[i] );
+ wsfds->fd_count = 0;
}
}
+/* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option
+ * from an fd and return the value converted to milli seconds
+ * or -1 if there is an infinite time out */
+static inline int get_rcvsnd_timeo( int fd, int optname)
+{
+ struct timeval tv;
+ int len = sizeof(tv);
+ int ret = getsockopt(fd, SOL_SOCKET, optname, &tv, &len);
+ if( ret >= 0)
+ ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+ if( ret <= 0 ) /* tv == {0,0} means infinite time out */
+ return -1;
+ return ret;
+}
+
+/* macro wrappers for portability */
+#ifdef SO_RCVTIMEO
+#define GET_RCVTIMEO(fd) get_rcvsnd_timeo( (fd), SO_RCVTIMEO)
+#else
+#define GET_RCVTIMEO(fd) (-1)
+#endif
+
+#ifdef SO_SNDTIMEO
+#define GET_SNDTIMEO(fd) get_rcvsnd_timeo( (fd), SO_SNDTIMEO)
+#else
+#define GET_SNDTIMEO(fd) (-1)
+#endif
+
/* utility: given an fd, will block until one of the events occurs */
-static inline int do_block( int fd, int events )
+static inline int do_block( int fd, int events, int timeout )
{
struct pollfd pfd;
+ int ret;
pfd.fd = fd;
pfd.events = events;
- poll(&pfd, 1, -1);
- return pfd.revents;
-}
-void* __ws_memalloc( int size )
-{
- return WS_ALLOC(size);
-}
-
-void __ws_memfree(void* ptr)
-{
- WS_FREE(ptr);
+ while ((ret = poll(&pfd, 1, timeout)) < 0)
+ {
+ if (errno != EINTR)
+ return -1;
+ }
+ if( ret == 0 )
+ return 0;
+ return pfd.revents;
}
* Init / cleanup / error checking.
*/
-/***********************************************************************
- * WSAStartup (WINSOCK.115)
- *
- * Create socket control struct, attach it to the global list and
- * update a pointer in the task struct.
- */
-INT16 WINAPI WSAStartup16(UINT16 wVersionRequested, LPWSADATA16 lpWSAData)
-{
- static const WSADATA16 data =
- {
- 0x0101, 0x0101,
- "WINE Sockets 1.1",
-#ifdef linux
- "Linux/i386",
-#elif defined(__NetBSD__)
- "NetBSD/i386",
-#elif defined(sunos)
- "SunOS",
-#elif defined(__FreeBSD__)
- "FreeBSD",
-#elif defined(__OpenBSD__)
- "OpenBSD/i386",
-#else
- "Unknown",
-#endif
- WS_MAX_SOCKETS_PER_PROCESS,
- WS_MAX_UDP_DATAGRAM,
- 0
- };
-
- TRACE("verReq=%x\n", wVersionRequested);
-
- if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
- HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
-
- if (!lpWSAData) return WSAEINVAL;
-
- /* initialize socket heap */
-
- if( !_WSHeap )
- {
- _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
- if( !_WSHeap )
- {
- ERR("Fatal: failed to create WinSock heap\n");
- return 0;
- }
- }
- if( _WSHeap == 0 ) return WSASYSNOTREADY;
-
- num_startup++;
-
- /* return winsock information */
-
- memcpy(lpWSAData, &data, sizeof(data));
-
- TRACE("succeeded\n");
- return 0;
-}
-
/***********************************************************************
* WSAStartup (WS2_32.115)
*/
if (!lpWSAData) return WSAEINVAL;
- /* initialize socket heap */
-
- if( !_WSHeap )
- {
- _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
- if( !_WSHeap )
- {
- ERR("Fatal: failed to create WinSock heap\n");
- return 0;
- }
- }
- if( _WSHeap == 0 ) return WSASYSNOTREADY;
-
num_startup++;
/* that's the whole of the negotiation for now */
/***********************************************************************
- * WSACleanup (WINSOCK.116)
* WSACleanup (WS2_32.116)
*/
INT WINAPI WSACleanup(void)
SetLastError(iError);
}
-/***********************************************************************
- * WSASetLastError (WINSOCK.112)
- */
-void WINAPI WSASetLastError16(INT16 iError)
-{
- WSASetLastError(iError);
-}
-
-static char* check_buffer(int size)
-{
- static int local_buflen;
-
- if (local_buffer)
- {
- if (local_buflen >= size ) return local_buffer;
- HeapFree( GetProcessHeap(), 0, local_buffer );
- }
- local_buffer = HeapAlloc( GetProcessHeap(), 0, (local_buflen = size) );
- return local_buffer;
-}
-
-static struct ws_hostent* check_buffer_he(int size)
+static struct WS_hostent *check_buffer_he(int size)
{
static int he_len;
if (he_buffer)
{
if (he_len >= size ) return he_buffer;
- UnMapLS( he_buffer_seg );
HeapFree( GetProcessHeap(), 0, he_buffer );
}
he_buffer = HeapAlloc( GetProcessHeap(), 0, (he_len = size) );
- he_buffer_seg = MapLS( he_buffer );
+ if (!he_buffer) SetLastError(WSAENOBUFS);
return he_buffer;
}
-static void* check_buffer_se(int size)
+static struct WS_servent *check_buffer_se(int size)
{
static int se_len;
if (se_buffer)
{
if (se_len >= size ) return se_buffer;
- UnMapLS( se_buffer_seg );
HeapFree( GetProcessHeap(), 0, se_buffer );
}
se_buffer = HeapAlloc( GetProcessHeap(), 0, (se_len = size) );
- se_buffer_seg = MapLS( se_buffer );
+ if (!se_buffer) SetLastError(WSAENOBUFS);
return se_buffer;
}
-static struct ws_protoent* check_buffer_pe(int size)
+static struct WS_protoent *check_buffer_pe(int size)
{
static int pe_len;
if (pe_buffer)
{
if (pe_len >= size ) return pe_buffer;
- UnMapLS( pe_buffer_seg );
HeapFree( GetProcessHeap(), 0, pe_buffer );
}
pe_buffer = HeapAlloc( GetProcessHeap(), 0, (pe_len = size) );
- pe_buffer_seg = MapLS( he_buffer );
+ if (!pe_buffer) SetLastError(WSAENOBUFS);
return pe_buffer;
}
*uaddrlen=sizeof(struct sockaddr_ipx);
uipx=malloc(*uaddrlen);
+ memset(uipx,0,sizeof(*uipx));
uipx->sipx_family=AF_IPX;
uipx->sipx_port=wsipx->sa_socket;
/* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
#ifdef IPX_FRAME_NONE
uipx->sipx_type=IPX_FRAME_NONE;
#endif
- memset(&uipx->sipx_zero,0,sizeof(uipx->sipx_zero));
return (const struct sockaddr*)uipx;
}
#endif
{
struct msghdr hdr;
int n;
- TRACE ( "fd %d, iovec %p, count %d addr %p, len %p, flags %lx\n",
- fd, iov, count, lpFrom, lpFromlen, *lpFlags);
+ TRACE ( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
+ fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
hdr.msg_name = NULL;
if ( lpFrom )
{
-#if DEBUG_SOCKADDR
- dump_sockaddr (lpFrom);
-#endif
-
hdr.msg_namelen = *lpFromlen;
hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
if ( !hdr.msg_name )
{
struct msghdr hdr;
int n = -1;
- TRACE ( "fd %d, iovec %p, count %d addr %p, len %d, flags %lx\n",
- fd, iov, count, to, tolen, dwFlags);
+ TRACE ( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
+ fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
hdr.msg_name = NULL;
if ( to )
{
-#if DEBUG_SOCKADDR
- dump_sockaddr (to);
-#endif
hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
if ( !hdr.msg_name )
{
WSASetLastError ( WSAEFAULT );
goto out;
}
+
+#ifdef HAVE_IPX
+ if(to->sa_family == WS_AF_IPX)
+ {
+#ifdef SOL_IPX
+ struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
+ int val=0;
+ int len=sizeof(int);
+
+ /* The packet type is stored at the ipx socket level; Atleast the linux kernel seems
+ * to do something with it in case hdr.msg_name is NULL. Nonetheless can we use it to store
+ * the packet type and then we can retrieve it using getsockopt. After that we can set the
+ * ipx type in the sockaddr_opx structure with the stored value.
+ */
+ if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1)
+ {
+ TRACE("ptype: %d (fd:%d)\n", val, fd);
+ uipx->sipx_type = val;
+ }
+#endif
+ }
+#endif
+
}
else
hdr.msg_namelen = 0;
SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
int *addrlen32)
{
- int fd = _get_sock_fd(s);
+ SOCKET as;
- TRACE("socket %04x\n", (UINT16)s );
- if (fd != -1)
+ TRACE("socket %04x\n", s );
+ if (_is_blocking(s))
{
- SOCKET as;
- if (_is_blocking(s))
- {
- /* block here */
- do_block(fd, POLLIN);
- _sync_sock_state(s); /* let wineserver notice connection */
- /* retrieve any error codes from it */
- SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
- /* FIXME: care about the error? */
- }
- close(fd);
- SERVER_START_REQ( accept_socket )
- {
- req->lhandle = SOCKET2HANDLE(s);
- req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
- req->inherit = TRUE;
- set_error( wine_server_call( req ) );
- as = HANDLE2SOCKET( reply->handle );
- }
- SERVER_END_REQ;
- if (as)
- {
- if (addr)
- WS_getpeername(as, addr, addrlen32);
- return as;
- }
+ int fd = get_sock_fd( s, GENERIC_READ, NULL );
+ if (fd == -1) return INVALID_SOCKET;
+ /* block here */
+ do_block(fd, POLLIN, -1);
+ _sync_sock_state(s); /* let wineserver notice connection */
+ release_sock_fd( s, fd );
+ /* retrieve any error codes from it */
+ SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
+ /* FIXME: care about the error? */
+ }
+ SERVER_START_REQ( accept_socket )
+ {
+ req->lhandle = SOCKET2HANDLE(s);
+ req->access = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
+ req->inherit = TRUE;
+ set_error( wine_server_call( req ) );
+ as = HANDLE2SOCKET( reply->handle );
}
- else
+ SERVER_END_REQ;
+ if (as)
{
- SetLastError(WSAENOTSOCK);
+ if (addr) WS_getpeername(as, addr, addrlen32);
+ return as;
}
return INVALID_SOCKET;
}
-/***********************************************************************
- * accept (WINSOCK.1)
- */
-SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct WS_sockaddr* addr,
- INT16* addrlen16 )
-{
- INT addrlen32 = addrlen16 ? *addrlen16 : 0;
- SOCKET retSocket = WS_accept( s, addr, &addrlen32 );
- if( addrlen16 ) *addrlen16 = (INT16)addrlen32;
- return (SOCKET16)retSocket;
-}
-
/***********************************************************************
* bind (WS2_32.2)
*/
int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
{
- int fd = _get_sock_fd(s);
- int res;
+ int fd = get_sock_fd( s, 0, NULL );
+ int res = SOCKET_ERROR;
- TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
-#if DEBUG_SOCKADDR
- dump_sockaddr(name);
-#endif
+ TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
- res=SOCKET_ERROR;
if (fd != -1)
{
if (!name || !SUPPORTED_PF(name->sa_family))
}
else
{
- int on = 1;
- /* The game GrandPrixLegends binds more than one time, but does
- * not do a SO_REUSEADDR - Stevens says this is ok */
- TRACE( "Setting WS_SO_REUSEADDR on socket before we bind it\n");
- WS_setsockopt( s, WS_SOL_SOCKET, WS_SO_REUSEADDR, (char*)&on, sizeof(on) );
-
if (bind(fd, uaddr, uaddrlen) < 0)
{
int loc_errno = errno;
ws_sockaddr_free(uaddr,name);
}
}
- close(fd);
- }
- else
- {
- SetLastError(WSAENOTSOCK);
+ release_sock_fd( s, fd );
}
return res;
}
-/***********************************************************************
- * bind (WINSOCK.2)
- */
-INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
-{
- return (INT16)WS_bind( s, name, namelen );
-}
-
/***********************************************************************
* closesocket (WS2_32.3)
*/
int WINAPI WS_closesocket(SOCKET s)
{
- TRACE("socket %08x\n", s);
+ TRACE("socket %04x\n", s);
if (CloseHandle(SOCKET2HANDLE(s))) return 0;
return SOCKET_ERROR;
}
-/***********************************************************************
- * closesocket (WINSOCK.3)
- */
-INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s)
-{
- return (INT16)WS_closesocket(s);
-}
-
/***********************************************************************
* connect (WS2_32.4)
*/
int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
{
- int fd = _get_sock_fd(s);
+ int fd = get_sock_fd( s, GENERIC_READ, NULL );
- TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen);
-#if DEBUG_SOCKADDR
- dump_sockaddr(name);
-#endif
+ TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
if (fd != -1)
{
{
int result;
/* block here */
- do_block(fd, POLLIN | POLLOUT );
+ do_block(fd, POLLIN | POLLOUT, -1);
_sync_sock_state(s); /* let wineserver notice connection */
/* retrieve any error codes from it */
result = _get_sock_error(s, FD_CONNECT_BIT);
{
SetLastError(wsaErrno());
}
- close(fd);
- }
- else
- {
- SetLastError(WSAENOTSOCK);
+ release_sock_fd( s, fd );
}
return SOCKET_ERROR;
connect_success:
- close(fd);
+ release_sock_fd( s, fd );
_enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
FD_WINE_CONNECTED|FD_READ|FD_WRITE,
FD_CONNECT|FD_WINE_LISTENING);
return 0;
}
-/***********************************************************************
- * connect (WINSOCK.4)
- */
-INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct WS_sockaddr *name, INT16 namelen)
-{
- return (INT16)WS_connect( s, name, namelen );
-}
-
/***********************************************************************
* WSAConnect (WS2_32.30)
*/
int fd;
int res;
- TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
+ TRACE("socket: %04x, ptr %p, len %08x\n", s, name, *namelen);
/* Check if what we've received is valid. Should we use IsBadReadPtr? */
if( (name == NULL) || (namelen == NULL) )
return SOCKET_ERROR;
}
- fd = _get_sock_fd(s);
+ fd = get_sock_fd( s, 0, NULL );
res = SOCKET_ERROR;
if (fd != -1)
res=0;
}
ws_sockaddr_free(uaddr,name);
- close(fd);
- }
- else
- {
- SetLastError(WSAENOTSOCK);
+ release_sock_fd( s, fd );
}
return res;
}
-/***********************************************************************
- * getpeername (WINSOCK.5)
- */
-INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct WS_sockaddr *name,
- INT16 *namelen16)
-{
- INT namelen32 = *namelen16;
- INT retVal = WS_getpeername( s, name, &namelen32 );
-
-#if DEBUG_SOCKADDR
- dump_sockaddr(name);
-#endif
-
- *namelen16 = namelen32;
- return (INT16)retVal;
-}
-
/***********************************************************************
* getsockname (WS2_32.6)
*/
return SOCKET_ERROR;
}
- fd = _get_sock_fd(s);
+ fd = get_sock_fd( s, 0, NULL );
res = SOCKET_ERROR;
if (fd != -1)
{
res=0;
}
- close(fd);
- }
- else
- {
- SetLastError(WSAENOTSOCK);
+ release_sock_fd( s, fd );
}
return res;
}
-/***********************************************************************
- * getsockname (WINSOCK.6)
- */
-INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct WS_sockaddr *name,
- INT16 *namelen16)
-{
- INT retVal;
-
- if( namelen16 )
- {
- INT namelen32 = *namelen16;
- retVal = WS_getsockname( s, name, &namelen32 );
- *namelen16 = namelen32;
-
-#if DEBUG_SOCKADDR
- dump_sockaddr(name);
-#endif
-
- }
- else retVal = SOCKET_ERROR;
- return (INT16)retVal;
-}
-
-
/***********************************************************************
* getsockopt (WS2_32.7)
*/
INT optname, char *optval, INT *optlen)
{
int fd;
+ INT ret = 0;
TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
(int) optname, (int) optval, (int) *optlen);
return 0;
}
- fd = _get_sock_fd(s);
- if (fd != -1)
+#ifdef HAVE_IPX
+ if(level == NSPROTO_IPX)
{
- if (!convert_sockopt(&level, &optname)) {
- SetLastError(WSAENOPROTOOPT); /* Unknown option */
- } else {
- if (getsockopt(fd, (int) level, optname, optval, optlen) == 0 )
- {
- close(fd);
+ struct WS_sockaddr_ipx addr;
+ IPX_ADDRESS_DATA *data;
+ int namelen;
+ switch(optname)
+ {
+ case IPX_PTYPE:
+ fd = get_sock_fd( s, 0, NULL );
+#ifdef SOL_IPX
+ if(getsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
+ {
+ return SOCKET_ERROR;
+ }
+#else
+ {
+ struct ipx val;
+ socklen_t len=sizeof(struct ipx);
+
+ if(getsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, &len) == -1 )
+ return SOCKET_ERROR;
+ *optval = (int)val.ipx_pt;
+ }
+#endif
+ TRACE("ptype: %d (fd: %d)\n", *(int*)optval, fd);
+ release_sock_fd( s, fd );
+
return 0;
- }
- SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
+ case IPX_ADDRESS:
+ /*
+ * On a Win2000 system with one network card there are useally three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
+ * Using this call you can then retrieve info about this all. In case of Linux it is a bit different. Useally you have
+ * only "one" device active and further it is not possible to query things like the linkspeed.
+ */
+ FIXME("IPX_ADDRESS\n");
+ namelen = sizeof(struct WS_sockaddr);
+ memset(&addr, 0, sizeof(struct WS_sockaddr));
+ WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
+
+ data = (IPX_ADDRESS_DATA*)optval;
+ memcpy(data->nodenum,&addr.sa_nodenum,sizeof(data->nodenum));
+ memcpy(data->netnum,&addr.sa_netnum,sizeof(data->netnum));
+ data->adapternum = 0;
+ data->wan = FALSE; /* We are not on a wan for now .. */
+ data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
+ data->maxpkt = 1467; /* This value is the default one on atleast Win2k/WinXP */
+ data->linkspeed = 100000; /* Set the line speed in 100bit/s to 10 Mbit; note 1MB = 1000kB in this case */
+ return 0;
+ case IPX_MAX_ADAPTER_NUM:
+ FIXME("IPX_MAX_ADAPTER_NUM\n");
+ *(int*)optval = 1; /* As noted under IPX_ADDRESS we have just one card. */
+
+ return 0;
+ default:
+ FIXME("IPX optname:%x\n", optname);
+ return SOCKET_ERROR;
}
- close(fd);
}
- return SOCKET_ERROR;
-}
+#endif
+ if( (fd = get_sock_fd( s, 0, NULL )) == -1)
+ return SOCKET_ERROR;
-/***********************************************************************
- * getsockopt (WINSOCK.7)
- */
-INT16 WINAPI WINSOCK_getsockopt16(SOCKET16 s, INT16 level,
- INT16 optname, char *optval, INT16 *optlen)
-{
- INT optlen32;
- INT *p = &optlen32;
- INT retVal;
- if( optlen ) optlen32 = *optlen; else p = NULL;
- retVal = WS_getsockopt( s, (UINT16)level, optname, optval, p );
- if( optlen ) *optlen = optlen32;
- return (INT16)retVal;
+ if (!convert_sockopt(&level, &optname)) {
+ SetLastError(WSAENOPROTOOPT); /* Unknown option */
+ ret = SOCKET_ERROR;
+ } else {
+ struct timeval tv;
+ struct linger lingval;
+ INT len, *plen = optlen;
+ char *pval = optval;
+ if(level == SOL_SOCKET && is_timeout_option(optname)) {
+ len = sizeof(tv);
+ plen = &len;
+ pval = (char *) &tv;
+ } else if( level == SOL_SOCKET && optname == SO_LINGER) {
+ len = sizeof(lingval);
+ plen = &len;
+ pval = (char *) &lingval;
+ }
+ if (getsockopt(fd, (int) level, optname, pval, plen) != 0 ) {
+ SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
+ ret = SOCKET_ERROR;
+ } else if(level == SOL_SOCKET && is_timeout_option(optname)) {
+ if( *optlen >= sizeof(INT) ) {
+ *optlen = sizeof(INT);
+ *(INT*)optval = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+ } else {
+ SetLastError(WSAEFAULT);
+ ret = SOCKET_ERROR;
+ }
+ } else if( level == SOL_SOCKET && optname == SO_LINGER) {
+ if( *optlen >= sizeof( LINGER) ) {
+ (( LINGER *) optval)->l_onoff = lingval.l_onoff;
+ (( LINGER *) optval)->l_linger = lingval.l_linger;
+ } else {
+ SetLastError(WSAEFAULT);
+ ret = SOCKET_ERROR;
+ }
+ }
+ }
+ release_sock_fd( s, fd );
+ return ret;
}
return htons(hostshort);
}
+/***********************************************************************
+ * WSAHtonl (WS2_32.46)
+ * From MSDN decription of error codes, this function should also
+ * check if WinSock has been initialized and the socket is a valid
+ * socket. But why? This function only translates a host byte order
+ * u_long into a network byte order u_long...
+ */
+int WINAPI WSAHtonl(SOCKET s, u_long hostlong, u_long *lpnetlong)
+{
+ if (lpnetlong)
+ {
+ *lpnetlong = htonl(hostlong);
+ return 0;
+ }
+ WSASetLastError(WSAEFAULT);
+ return SOCKET_ERROR;
+}
+
+/***********************************************************************
+ * WSAHtons (WS2_32.47)
+ * From MSDN decription of error codes, this function should also
+ * check if WinSock has been initialized and the socket is a valid
+ * socket. But why? This function only translates a host byte order
+ * u_short into a network byte order u_short...
+ */
+int WINAPI WSAHtons(SOCKET s, u_short hostshort, u_short *lpnetshort)
+{
+
+ if (lpnetshort)
+ {
+ *lpnetshort = htons(hostshort);
+ return 0;
+ }
+ WSASetLastError(WSAEFAULT);
+ return SOCKET_ERROR;
+}
+
/***********************************************************************
* inet_addr (WINSOCK.10)
return NULL;
}
-/***********************************************************************
- * inet_ntoa (WINSOCK.11)
- */
-SEGPTR WINAPI WINSOCK_inet_ntoa16(struct in_addr in)
-{
- char* retVal;
- if (!(retVal = WS_inet_ntoa(*((struct WS_in_addr*)&in)))) return 0;
- if (!dbuffer_seg) dbuffer_seg = MapLS( retVal );
- return dbuffer_seg;
-}
-
-
/**********************************************************************
* WSAIoctl (WS2_32.50)
*
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
- int fd = _get_sock_fd(s);
+ int fd = get_sock_fd( s, 0, NULL );
+
+ if (fd == -1) return SOCKET_ERROR;
- if (fd != -1)
+ TRACE("%d, 0x%08lx, %p, %ld, %p, %ld, %p, %p, %p\n",
+ s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpbOutBuffer,
+ cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
+
+ switch( dwIoControlCode )
{
- switch( dwIoControlCode )
- {
- case SIO_GET_INTERFACE_LIST:
- {
- INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
- DWORD size, numInt, apiReturn;
+ case SIO_GET_INTERFACE_LIST:
+ {
+ INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
+ DWORD size, numInt, apiReturn;
- TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
+ TRACE ("-> SIO_GET_INTERFACE_LIST request\n");
- if (!lpbOutBuffer)
- {
- close(fd);
+ if (!lpbOutBuffer)
+ {
+ release_sock_fd( s, fd );
WSASetLastError(WSAEFAULT);
return SOCKET_ERROR;
- }
- if (!lpcbBytesReturned)
- {
- close(fd);
+ }
+ if (!lpcbBytesReturned)
+ {
+ release_sock_fd( s, fd );
WSASetLastError(WSAEFAULT);
return SOCKET_ERROR;
- }
+ }
- apiReturn = GetAdaptersInfo(NULL, &size);
- if (apiReturn == ERROR_NO_DATA)
- {
+ apiReturn = GetAdaptersInfo(NULL, &size);
+ if (apiReturn == ERROR_NO_DATA)
+ {
numInt = 0;
- }
- else if (apiReturn == ERROR_BUFFER_OVERFLOW)
- {
+ }
+ else if (apiReturn == ERROR_BUFFER_OVERFLOW)
+ {
PIP_ADAPTER_INFO table = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(),0,size);
if (table)
{
PIP_ADAPTER_INFO ptr;
- if (size > cbOutBuffer)
+ if (size*sizeof(INTERFACE_INFO)/sizeof(IP_ADAPTER_INFO) > cbOutBuffer)
{
+ WARN("Buffer too small = %lu, cbOutBuffer = %lu\n", size, cbOutBuffer);
HeapFree(GetProcessHeap(),0,table);
- close(fd);
+ release_sock_fd( s, fd );
WSASetLastError(WSAEFAULT);
return (SOCKET_ERROR);
}
{
ERR ("Error obtaining status flags for socket!\n");
HeapFree(GetProcessHeap(),0,table);
- close(fd);
+ release_sock_fd( s, fd );
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
}
intArray->iiFlags = 0;
if (ifInfo.ifr_flags & IFF_BROADCAST)
intArray->iiFlags |= WS_IFF_BROADCAST;
+#ifdef IFF_POINTOPOINT
if (ifInfo.ifr_flags & IFF_POINTOPOINT)
intArray->iiFlags |= WS_IFF_POINTTOPOINT;
+#endif
if (ifInfo.ifr_flags & IFF_LOOPBACK)
intArray->iiFlags |= WS_IFF_LOOPBACK;
if (ifInfo.ifr_flags & IFF_UP)
intArray->iiFlags |= WS_IFF_UP;
+ if (ifInfo.ifr_flags & IFF_MULTICAST)
+ intArray->iiFlags |= WS_IFF_MULTICAST;
}
addr = inet_addr(ptr->IpAddressList.IpAddress.String);
else
{
ERR ("Unable to get interface table!\n");
- close(fd);
+ release_sock_fd( s, fd );
HeapFree(GetProcessHeap(),0,table);
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
}
else
{
- close(fd);
+ release_sock_fd( s, fd );
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
}
- }
- else
- {
+ }
+ else
+ {
ERR ("Unable to get interface table!\n");
- close(fd);
+ release_sock_fd( s, fd );
WSASetLastError(WSAEINVAL);
return (SOCKET_ERROR);
- }
- /* Calculate the size of the array being returned */
- *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
- break;
- }
-
- default:
- {
- WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
- close(fd);
- WSASetLastError(WSAEOPNOTSUPP);
- return (SOCKET_ERROR);
- }
- }
-
- /* Function executed with no errors */
- close(fd);
- return (0);
- }
- else
- {
- WSASetLastError(WSAENOTSOCK);
- return (SOCKET_ERROR);
+ }
+ /* Calculate the size of the array being returned */
+ *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
+ break;
+ }
+
+ case SIO_ADDRESS_LIST_CHANGE:
+ FIXME("-> SIO_ADDRESS_LIST_CHANGE request: stub\n");
+ /* FIXME: error and return code depend on whether socket was created
+ * with WSA_FLAG_OVERLAPPED, but there is no easy way to get this */
+ break;
+
+ default:
+ WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
+ release_sock_fd( s, fd );
+ WSASetLastError(WSAEOPNOTSUPP);
+ return (SOCKET_ERROR);
}
+
+ /* Function executed with no errors */
+ release_sock_fd( s, fd );
+ return (0);
}
*/
int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
{
- int fd = _get_sock_fd(s);
+ int fd;
+ long newcmd = cmd;
- TRACE("socket %04x, cmd %08lx, ptr %8x\n", s, cmd, (unsigned) argp);
- if (fd != -1)
- {
- long newcmd = cmd;
+ TRACE("socket %04x, cmd %08lx, ptr %p\n", s, cmd, argp);
switch( cmd )
{
- case WS_FIONREAD:
- newcmd=FIONREAD;
- break;
-
- case WS_FIONBIO:
- newcmd=FIONBIO;
- if( _get_sock_mask(s) )
- {
- /* AsyncSelect()'ed sockets are always nonblocking */
- if (*argp) {
- close(fd);
- return 0;
- }
- SetLastError(WSAEINVAL);
- close(fd);
- return SOCKET_ERROR;
- }
- close(fd);
- if (*argp)
- _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
- else
- _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
- return 0;
+ case WS_FIONREAD:
+ newcmd=FIONREAD;
+ break;
- case WS_SIOCATMARK:
- newcmd=SIOCATMARK;
- break;
+ case WS_FIONBIO:
+ if( _get_sock_mask(s) )
+ {
+ /* AsyncSelect()'ed sockets are always nonblocking */
+ if (*argp) return 0;
+ SetLastError(WSAEINVAL);
+ return SOCKET_ERROR;
+ }
+ fd = get_sock_fd( s, 0, NULL );
+ if (fd != -1)
+ {
+ int ret;
+ if (*argp)
+ {
+ _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
+ ret = fcntl( fd, F_SETFL, O_NONBLOCK );
+ }
+ else
+ {
+ _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
+ ret = fcntl( fd, F_SETFL, 0 );
+ }
+ release_sock_fd( s, fd );
+ if (!ret) return 0;
+ SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
+ }
+ return SOCKET_ERROR;
- case WS__IOW('f',125,u_long):
- WARN("Warning: WS1.1 shouldn't be using async I/O\n");
- SetLastError(WSAEINVAL);
- return SOCKET_ERROR;
+ case WS_SIOCATMARK:
+ newcmd=SIOCATMARK;
+ break;
- case SIOCGIFBRDADDR:
- case SIOCGIFNETMASK:
- case SIOCGIFADDR:
- /* These don't need any special handling. They are used by
- WsControl, and are here to suppress an unecessary warning. */
- break;
+ case WS__IOW('f',125,u_long):
+ WARN("Warning: WS1.1 shouldn't be using async I/O\n");
+ SetLastError(WSAEINVAL);
+ return SOCKET_ERROR;
+ case SIOCGIFBRDADDR:
+ case SIOCGIFNETMASK:
+ case SIOCGIFADDR:
+ /* These don't need any special handling. They are used by
+ WsControl, and are here to suppress an unecessary warning. */
+ break;
- default:
- /* Netscape tries hard to use bogus ioctl 0x667e */
- WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
+ default:
+ /* Netscape tries hard to use bogus ioctl 0x667e */
+ WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
+ break;
}
- if( ioctl(fd, newcmd, (char*)argp ) == 0 )
+
+ fd = get_sock_fd( s, 0, NULL );
+ if (fd != -1)
{
- close(fd);
- return 0;
+ if( ioctl(fd, newcmd, (char*)argp ) == 0 )
+ {
+ release_sock_fd( s, fd );
+ return 0;
+ }
+ SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
+ release_sock_fd( s, fd );
}
- SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
- close(fd);
- }
- return SOCKET_ERROR;
-}
-
-/***********************************************************************
- * ioctlsocket (WINSOCK.12)
- */
-INT16 WINAPI WINSOCK_ioctlsocket16(SOCKET16 s, LONG cmd, ULONG *argp)
-{
- return (INT16)WS_ioctlsocket( s, cmd, argp );
+ return SOCKET_ERROR;
}
-
/***********************************************************************
* listen (WS2_32.13)
*/
int WINAPI WS_listen(SOCKET s, int backlog)
{
- int fd = _get_sock_fd(s);
+ int fd = get_sock_fd( s, GENERIC_READ, NULL );
TRACE("socket %04x, backlog %d\n", s, backlog);
if (fd != -1)
{
if (listen(fd, backlog) == 0)
{
- close(fd);
+ release_sock_fd( s, fd );
_enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
FD_WINE_LISTENING,
FD_CONNECT|FD_WINE_CONNECTED);
return 0;
}
SetLastError(wsaErrno());
+ release_sock_fd( s, fd );
}
- else SetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
}
-/***********************************************************************
- * listen (WINSOCK.13)
- */
-INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
-{
- return (INT16)WS_listen( s, backlog );
-}
-
-
/***********************************************************************
* recv (WS2_32.16)
*/
return n;
}
-/***********************************************************************
- * recv (WINSOCK.16)
- */
-INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
-{
- return (INT16)WS_recv( s, buf, len, flags );
-}
-
-
/***********************************************************************
* recvfrom (WS2_32.17)
*/
}
/***********************************************************************
- * recvfrom (WINSOCK.17)
- */
-INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
- struct WS_sockaddr *from, INT16 *fromlen16)
-{
- INT fromlen32;
- INT *p = &fromlen32;
- INT retVal;
-
- if( fromlen16 ) fromlen32 = *fromlen16; else p = NULL;
- retVal = WS_recvfrom( s, buf, len, flags, from, p );
- if( fromlen16 ) *fromlen16 = fromlen32;
- return (INT16)retVal;
-}
-
-/***********************************************************************
- * __ws_select
+ * select (WS2_32.18)
*/
-static int __ws_select(BOOL b32,
- void *ws_readfds, void *ws_writefds, void *ws_exceptfds,
- const struct WS_timeval *ws_timeout)
+int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
+ WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
+ const struct WS_timeval* ws_timeout)
{
int highfd = 0;
fd_set readfds, writefds, exceptfds;
TRACE("read %p, write %p, excp %p timeout %p\n",
ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
- p_read = fd_set_import(&readfds, ws_readfds, &highfd, readfd, b32);
- p_write = fd_set_import(&writefds, ws_writefds, &highfd, writefd, b32);
- p_except = fd_set_import(&exceptfds, ws_exceptfds, &highfd, exceptfd, b32);
+ p_read = fd_set_import(&readfds, ws_readfds, GENERIC_READ, &highfd, readfd);
+ p_write = fd_set_import(&writefds, ws_writefds, GENERIC_WRITE, &highfd, writefd);
+ p_except = fd_set_import(&exceptfds, ws_exceptfds, 0, &highfd, exceptfd);
if (ws_timeout)
{
timeoutaddr = &timeout;
if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
{
- fd_set_export(&readfds, p_except, ws_readfds, readfd, b32);
- fd_set_export(&writefds, p_except, ws_writefds, writefd, b32);
+ fd_set_export(&readfds, p_except, ws_readfds, readfd);
+ fd_set_export(&writefds, p_except, ws_writefds, writefd);
if (p_except && ws_exceptfds)
{
-#define wsfds16 ((ws_fd_set16*)ws_exceptfds)
-#define wsfds32 ((WS_fd_set*)ws_exceptfds)
- int i, j, count = (b32) ? wsfds32->fd_count : wsfds16->fd_count;
+ unsigned int i, j;
- for (i = j = 0; i < count; i++)
+ for (i = j = 0; i < ws_exceptfds->fd_count; i++)
{
int fd = exceptfd[i];
- if( fd >= 0 && FD_ISSET(fd, &exceptfds) )
- {
- if( b32 )
- wsfds32->fd_array[j++] = wsfds32->fd_array[i];
- else
- wsfds16->fd_array[j++] = wsfds16->fd_array[i];
- }
- if( fd >= 0 ) close(fd);
- exceptfd[i] = -1;
+ SOCKET s = ws_exceptfds->fd_array[i];
+ if (fd == -1) continue;
+ if (FD_ISSET(fd, &exceptfds)) ws_exceptfds->fd_array[j++] = s;
+ release_sock_fd( s, fd );
}
- if( b32 )
- wsfds32->fd_count = j;
- else
- wsfds16->fd_count = j;
-#undef wsfds32
-#undef wsfds16
+ ws_exceptfds->fd_count = j;
}
return highfd;
}
- fd_set_unimport(ws_readfds, readfd, b32);
- fd_set_unimport(ws_writefds, writefd, b32);
- fd_set_unimport(ws_exceptfds, exceptfd, b32);
- if( ws_readfds ) ((WS_fd_set*)ws_readfds)->fd_count = 0;
- if( ws_writefds ) ((WS_fd_set*)ws_writefds)->fd_count = 0;
- if( ws_exceptfds ) ((WS_fd_set*)ws_exceptfds)->fd_count = 0;
+ fd_set_unimport(ws_readfds, readfd);
+ fd_set_unimport(ws_writefds, writefd);
+ fd_set_unimport(ws_exceptfds, exceptfd);
if( highfd == 0 ) return 0;
SetLastError(wsaErrno());
return SOCKET_ERROR;
}
-/***********************************************************************
- * select (WINSOCK.18)
- */
-INT16 WINAPI WINSOCK_select16(INT16 nfds, ws_fd_set16 *ws_readfds,
- ws_fd_set16 *ws_writefds, ws_fd_set16 *ws_exceptfds,
- struct WS_timeval* timeout)
-{
- return (INT16)__ws_select( FALSE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
-}
-
-/***********************************************************************
- * select (WS2_32.18)
- */
-int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
- WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
- const struct WS_timeval* timeout)
-{
- /* struct timeval is the same for both 32- and 16-bit code */
- return (INT)__ws_select( TRUE, ws_readfds, ws_writefds, ws_exceptfds, timeout );
-}
-
/***********************************************************************
* send (WS2_32.19)
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
{
- int i, n, fd, err = WSAENOTSOCK, flags, ret;
+ unsigned int i;
+ int n, fd, err = WSAENOTSOCK, flags, ret;
struct iovec* iovec;
struct ws2_async *wsa;
- enum fd_type type;
TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
s, lpBuffers, dwBufferCount, dwFlags,
to, tolen, lpOverlapped, lpCompletionRoutine);
- fd = _get_sock_fd_type( s, GENERIC_WRITE, &type, &flags );
- TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
+ fd = get_sock_fd( s, GENERIC_WRITE, &flags );
+ TRACE ( "fd=%d, flags=%x\n", fd, flags );
- if ( fd == -1 )
+ if ( fd == -1 ) return SOCKET_ERROR;
+
+ if (flags & FD_FLAG_SEND_SHUTDOWN)
{
- err = WSAGetLastError ();
- goto error;
+ WSASetLastError ( WSAESHUTDOWN );
+ goto err_close;
}
if ( !lpNumberOfBytesSent )
{
err = WSAEFAULT;
- goto error;
+ goto err_close;
}
iovec = HeapAlloc (GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
if (_is_blocking(s))
{
/* FIXME: exceptfds? */
- do_block(fd, POLLOUT);
+ int timeout = GET_SNDTIMEO(fd);
+ if( !do_block(fd, POLLOUT, timeout)) {
+ err = WSAETIMEDOUT;
+ goto err_free; /* msdn says a timeout in send is fatal */
+ }
}
n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
*lpNumberOfBytesSent = n;
HeapFree ( GetProcessHeap(), 0, iovec );
- close ( fd );
+ release_sock_fd( s, fd );
return 0;
err_free:
HeapFree ( GetProcessHeap(), 0, iovec );
err_close:
- close ( fd );
+ release_sock_fd( s, fd );
error:
WARN (" -> ERROR %d\n", err);
return SOCKET_ERROR;
}
-/***********************************************************************
- * send (WINSOCK.19)
- */
-INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
-{
- return WS_send( s, buf, len, flags );
-}
-
/***********************************************************************
* sendto (WS2_32.20)
*/
return n;
}
-/***********************************************************************
- * sendto (WINSOCK.20)
- */
-INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags,
- struct WS_sockaddr *to, INT16 tolen)
-{
- return (INT16)WS_sendto( s, buf, len, flags, to, tolen );
-}
-
/***********************************************************************
* setsockopt (WS2_32.21)
*/
const char *optval, int optlen)
{
int fd;
+ int woptval;
+ struct linger linger;
+ struct timeval tval;
+
+ TRACE("socket: %04x, level %d, name %d, ptr %p, len %d\n",
+ s, level, optname, optval, optlen);
- TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
- (int) optname, (int) optval, optlen);
/* SO_OPENTYPE does not require a valid socket handle. */
if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
{
return 0;
}
-
- fd = _get_sock_fd(s);
- if (fd != -1)
+#ifdef HAVE_IPX
+ if(level == NSPROTO_IPX)
{
- struct linger linger;
- int woptval;
- struct timeval tval;
-
- /* Is a privileged and useless operation, so we don't. */
- if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET)) {
- FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
- return 0;
+ switch(optname)
+ {
+ case IPX_PTYPE:
+ fd = get_sock_fd( s, 0, NULL );
+ TRACE("trying to set IPX_PTYPE: %d (fd: %d)\n", *(int*)optval, fd);
+
+ /* We try to set the ipx type on ipx socket level. */
+#ifdef SOL_IPX
+ if(setsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
+ {
+ ERR("IPX: could not set ipx option type; expect weird behaviour\n");
+ return SOCKET_ERROR;
+ }
+#else
+ {
+ struct ipx val;
+ /* Should we retrieve val using a getsockopt call and then
+ * set the modified one? */
+ val.ipx_pt = *optval;
+ setsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, sizeof(struct ipx));
+ }
+#endif
+ release_sock_fd( s, fd );
+ return 0;
+ case IPX_FILTERPTYPE:
+ /* Sets the receive filter packet type, at the moment we don't support it */
+ FIXME("IPX_FILTERPTYPE: %x\n", *optval);
+
+ /* Returning 0 is better for now than returning a SOCKET_ERROR */
+ return 0;
+ break;
+ default:
+ FIXME("opt_name:%x\n", optname);
+ return SOCKET_ERROR;
}
+ return 0;
+ }
+#endif
+
+ /* Is a privileged and useless operation, so we don't. */
+ if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET))
+ {
+ FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
+ return 0;
+ }
- if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
- /* This is unique to WinSock and takes special conversion */
- linger.l_onoff = *((int*)optval) ? 0: 1;
- linger.l_linger = 0;
- optname=SO_LINGER;
+ if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
+ /* This is unique to WinSock and takes special conversion */
+ linger.l_onoff = *((int*)optval) ? 0: 1;
+ linger.l_linger = 0;
+ optname=SO_LINGER;
+ optval = (char*)&linger;
+ optlen = sizeof(struct linger);
+ level = SOL_SOCKET;
+ }
+ else
+ {
+ if (!convert_sockopt(&level, &optname)) {
+ ERR("Invalid level (%d) or optname (%d)\n", level, optname);
+ SetLastError(WSAENOPROTOOPT);
+ return SOCKET_ERROR;
+ }
+ if (optname == SO_LINGER && optval) {
+ linger.l_onoff = ((LINGER*)optval)->l_onoff;
+ linger.l_linger = ((LINGER*)optval)->l_linger;
+ /* FIXME: what is documented behavior if SO_LINGER optval
+ is null?? */
optval = (char*)&linger;
optlen = sizeof(struct linger);
- level = SOL_SOCKET;
- }else{
- if (!convert_sockopt(&level, &optname)) {
- ERR("Invalid level (%d) or optname (%d)\n", level, optname);
- SetLastError(WSAENOPROTOOPT);
- close(fd);
- return SOCKET_ERROR;
- }
- if (optname == SO_LINGER && optval) {
- /* yes, uses unsigned short in both win16/win32 */
- linger.l_onoff = ((UINT16*)optval)[0];
- linger.l_linger = ((UINT16*)optval)[1];
- /* FIXME: what is documented behavior if SO_LINGER optval
- is null?? */
- optval = (char*)&linger;
- optlen = sizeof(struct linger);
- } else if (optval && optlen < sizeof(int)){
- woptval= *((INT16 *) optval);
- optval= (char*) &woptval;
- optlen=sizeof(int);
+ }
+ else if (optval && optlen < sizeof(int))
+ {
+ woptval= *((INT16 *) optval);
+ optval= (char*) &woptval;
+ optlen=sizeof(int);
+ }
+ if (level == SOL_SOCKET && is_timeout_option(optname))
+ {
+ if (optlen == sizeof(UINT32)) {
+ /* WinSock passes miliseconds instead of struct timeval */
+ tval.tv_usec = (*(PUINT32)optval % 1000) * 1000;
+ tval.tv_sec = *(PUINT32)optval / 1000;
+ /* min of 500 milisec */
+ if (tval.tv_sec == 0 && tval.tv_usec < 500000)
+ tval.tv_usec = 500000;
+ optlen = sizeof(struct timeval);
+ optval = (char*)&tval;
+ } else if (optlen == sizeof(struct timeval)) {
+ WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
+ } else {
+ WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
+ return 0;
}
-#ifdef SO_RCVTIMEO
- if (level == SOL_SOCKET && optname == SO_RCVTIMEO) {
- if (optlen == sizeof(UINT32)) {
- /* WinSock passes miliseconds instead of struct timeval */
- tval.tv_usec = *(PUINT32)optval % 1000;
- tval.tv_sec = *(PUINT32)optval / 1000;
- /* min of 500 milisec */
- if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
- optlen = sizeof(struct timeval);
- optval = (char*)&tval;
- } else if (optlen == sizeof(struct timeval)) {
- WARN("SO_RCVTIMEO for %d bytes: assuming unixism\n", optlen);
- } else {
- WARN("SO_RCVTIMEO for %d bytes is weird: ignored\n", optlen);
- close(fd);
- return 0;
- }
- }
-#endif
-#ifdef SO_SNDTIMEO
- if (level == SOL_SOCKET && optname == SO_SNDTIMEO) {
- if (optlen == sizeof(UINT32)) {
- /* WinSock passes miliseconds instead of struct timeval */
- tval.tv_usec = *(PUINT32)optval % 1000;
- tval.tv_sec = *(PUINT32)optval / 1000;
- /* min of 500 milisec */
- if (tval.tv_sec == 0 && tval.tv_usec < 500) tval.tv_usec = 500;
- optlen = sizeof(struct timeval);
- optval = (char*)&tval;
- } else if (optlen == sizeof(struct timeval)) {
- WARN("SO_SNDTIMEO for %d bytes: assuming unixism\n", optlen);
- } else {
- WARN("SO_SNDTIMEO for %d bytes is weird: ignored\n", optlen);
- close(fd);
- return 0;
- }
- }
-#endif
- }
- if(optname == SO_RCVBUF && *(int*)optval < 2048) {
+ }
+ if (level == SOL_SOCKET && optname == SO_RCVBUF && *(int*)optval < 2048)
+ {
WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
- close( fd);
return 0;
}
+ }
- if (setsockopt(fd, level, optname, optval, optlen) == 0)
- {
- close(fd);
- return 0;
- }
- TRACE("Setting socket error, %d\n", wsaErrno());
- SetLastError(wsaErrno());
- close(fd);
+
+ fd = get_sock_fd( s, 0, NULL );
+ if (fd == -1) return SOCKET_ERROR;
+
+ if (setsockopt(fd, level, optname, optval, optlen) == 0)
+ {
+ release_sock_fd( s, fd );
+ return 0;
}
- else SetLastError(WSAENOTSOCK);
+ TRACE("Setting socket error, %d\n", wsaErrno());
+ SetLastError(wsaErrno());
+ release_sock_fd( s, fd );
return SOCKET_ERROR;
}
-/***********************************************************************
- * setsockopt (WINSOCK.21)
- */
-INT16 WINAPI WINSOCK_setsockopt16(SOCKET16 s, INT16 level, INT16 optname,
- char *optval, INT16 optlen)
-{
- if( !optval ) return SOCKET_ERROR;
- return (INT16)WS_setsockopt( s, (UINT16)level, optname, optval, optlen );
-}
-
-
/***********************************************************************
* shutdown (WS2_32.22)
*/
int WINAPI WS_shutdown(SOCKET s, int how)
{
int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
- enum fd_type type;
unsigned int clear_flags = 0;
- fd = _get_sock_fd_type ( s, 0, &type, &flags );
- TRACE("socket %04x, how %i %d %d \n", s, how, type, flags );
+ fd = get_sock_fd( s, 0, &flags );
+ TRACE("socket %04x, how %i %x\n", s, how, flags );
if (fd == -1)
return SOCKET_ERROR;
case SD_BOTH:
default:
fd0 = fd;
- fd1 = _get_sock_fd ( s );
+ fd1 = get_sock_fd ( s, 0, NULL );
+ break;
}
if ( fd0 != -1 )
err = WS2_register_async_shutdown ( s, fd0, ASYNC_TYPE_READ );
if ( err )
{
- close ( fd0 );
+ release_sock_fd( s, fd0 );
goto error;
}
}
err = WS2_register_async_shutdown ( s, fd1, ASYNC_TYPE_WRITE );
if ( err )
{
- close ( fd1 );
+ release_sock_fd( s, fd1 );
goto error;
}
}
if ( shutdown( fd, how ) )
{
err = wsaErrno ();
- close ( fd );
+ release_sock_fd( s, fd );
goto error;
}
- close(fd);
+ release_sock_fd( s, fd );
}
_enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
return SOCKET_ERROR;
}
-/***********************************************************************
- * shutdown (WINSOCK.22)
- */
-INT16 WINAPI WINSOCK_shutdown16(SOCKET16 s, INT16 how)
-{
- return (INT16)WS_shutdown( s, how );
-}
-
-
/***********************************************************************
* socket (WS2_32.23)
*/
(TlsGetValue(opentype_tls_index) ? 0 : WSA_FLAG_OVERLAPPED) );
}
-/***********************************************************************
- * socket (WINSOCK.23)
- */
-SOCKET16 WINAPI WINSOCK_socket16(INT16 af, INT16 type, INT16 protocol)
-{
- return (SOCKET16)WS_socket( af, type, protocol );
-}
-
-
-/* ----------------------------------- DNS services
- *
- * IMPORTANT: 16-bit API structures have SEGPTR pointers inside them.
- * Also, we have to use wsock32 stubs to convert structures and
- * error codes from Unix to WSA, hence there is no direct mapping in
- * the relay32/wsock32.spec.
- */
-
/***********************************************************************
- * __ws_gethostbyaddr
+ * gethostbyaddr (WS2_32.51)
*/
-static WIN_hostent* __ws_gethostbyaddr(const char *addr, int len, int type, int dup_flag)
+struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
{
- WIN_hostent *retval = NULL;
-
+ struct WS_hostent *retval = NULL;
struct hostent* host;
+
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
char *extrabuf;
int ebufsize=1024;
host = gethostbyaddr(addr, len, type);
if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
#endif
- if( host != NULL )
- {
- if( WS_dup_he(host, dup_flag) )
- retval = he_buffer;
- else
- SetLastError(WSAENOBUFS);
- }
+ if( host != NULL ) retval = WS_dup_he(host);
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
HeapFree(GetProcessHeap(),0,extrabuf);
#else
LeaveCriticalSection( &csWSgetXXXbyYYY );
#endif
+ TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
return retval;
}
/***********************************************************************
- * gethostbyaddr (WINSOCK.51)
- */
-SEGPTR WINAPI WINSOCK_gethostbyaddr16(const char *addr, INT16 len, INT16 type)
-{
- TRACE("ptr %p, len %d, type %d\n", addr, len, type);
- if (!__ws_gethostbyaddr( addr, len, type, WS_DUP_SEGPTR )) return 0;
- return he_buffer_seg;
-}
-
-/***********************************************************************
- * gethostbyaddr (WS2_32.51)
- */
-struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len,
- int type)
-{
- TRACE("ptr %08x, len %d, type %d\n",
- (unsigned) addr, len, type);
- return __ws_gethostbyaddr(addr, len, type, WS_DUP_LINEAR);
-}
-
-/***********************************************************************
- * __ws_gethostbyname
+ * gethostbyname (WS2_32.52)
*/
-static WIN_hostent * __ws_gethostbyname(const char *name, int dup_flag)
+struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
{
- WIN_hostent *retval = NULL;
+ struct WS_hostent *retval = NULL;
struct hostent* host;
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
char *extrabuf;
host = gethostbyname(name);
if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
#endif
- if( host != NULL )
- {
- if( WS_dup_he(host, dup_flag) )
- retval = he_buffer;
- else SetLastError(WSAENOBUFS);
- }
+ if (host) retval = WS_dup_he(host);
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
HeapFree(GetProcessHeap(),0,extrabuf);
#else
LeaveCriticalSection( &csWSgetXXXbyYYY );
#endif
+ TRACE( "%s ret %p\n", debugstr_a(name), retval );
return retval;
}
-/***********************************************************************
- * gethostbyname (WINSOCK.52)
- */
-SEGPTR WINAPI WINSOCK_gethostbyname16(const char *name)
-{
- TRACE( "%s\n", debugstr_a(name) );
- if (!__ws_gethostbyname( name, WS_DUP_SEGPTR )) return 0;
- return he_buffer_seg;
-}
/***********************************************************************
- * gethostbyname (WS2_32.52)
- */
-struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
-{
- TRACE( "%s\n", debugstr_a(name) );
- return __ws_gethostbyname( name, WS_DUP_LINEAR );
-}
-
-
-/***********************************************************************
- * __ws_getprotobyname
+ * getprotobyname (WS2_32.53)
*/
-static WIN_protoent* __ws_getprotobyname(const char *name, int dup_flag)
+struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
{
- WIN_protoent* retval = NULL;
+ struct WS_protoent* retval = NULL;
#ifdef HAVE_GETPROTOBYNAME
struct protoent* proto;
EnterCriticalSection( &csWSgetXXXbyYYY );
if( (proto = getprotobyname(name)) != NULL )
{
- if( WS_dup_pe(proto, dup_flag) )
- retval = pe_buffer;
- else SetLastError(WSAENOBUFS);
+ retval = WS_dup_pe(proto);
}
else {
MESSAGE("protocol %s not found; You might want to add "
}
LeaveCriticalSection( &csWSgetXXXbyYYY );
#endif
+ TRACE( "%s ret %p\n", debugstr_a(name), retval );
return retval;
}
-/***********************************************************************
- * getprotobyname (WINSOCK.53)
- */
-SEGPTR WINAPI WINSOCK_getprotobyname16(const char *name)
-{
- TRACE( "%s\n", debugstr_a(name) );
- if (!__ws_getprotobyname(name, WS_DUP_SEGPTR)) return 0;
- return pe_buffer_seg;
-}
-
-/***********************************************************************
- * getprotobyname (WS2_32.53)
- */
-struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
-{
- TRACE( "%s\n", debugstr_a(name) );
- return __ws_getprotobyname(name, WS_DUP_LINEAR);
-}
-
/***********************************************************************
- * __ws_getprotobynumber
+ * getprotobynumber (WS2_32.54)
*/
-static WIN_protoent* __ws_getprotobynumber(int number, int dup_flag)
+struct WS_protoent* WINAPI WS_getprotobynumber(int number)
{
- WIN_protoent* retval = NULL;
+ struct WS_protoent* retval = NULL;
#ifdef HAVE_GETPROTOBYNUMBER
struct protoent* proto;
EnterCriticalSection( &csWSgetXXXbyYYY );
if( (proto = getprotobynumber(number)) != NULL )
{
- if( WS_dup_pe(proto, dup_flag) )
- retval = pe_buffer;
- else SetLastError(WSAENOBUFS);
+ retval = WS_dup_pe(proto);
}
else {
MESSAGE("protocol number %d not found; You might want to add "
}
LeaveCriticalSection( &csWSgetXXXbyYYY );
#endif
+ TRACE("%i ret %p\n", number, retval);
return retval;
}
-/***********************************************************************
- * getprotobynumber (WINSOCK.54)
- */
-SEGPTR WINAPI WINSOCK_getprotobynumber16(INT16 number)
-{
- TRACE("%i\n", number);
- if (!__ws_getprotobynumber(number, WS_DUP_SEGPTR)) return 0;
- return pe_buffer_seg;
-}
-
-/***********************************************************************
- * getprotobynumber (WS2_32.54)
- */
-struct WS_protoent* WINAPI WS_getprotobynumber(int number)
-{
- TRACE("%i\n", number);
- return __ws_getprotobynumber(number, WS_DUP_LINEAR);
-}
-
/***********************************************************************
- * __ws_getservbyname
+ * getservbyname (WS2_32.55)
*/
-static WIN_servent* __ws_getservbyname(const char *name, const char *proto, int dup_flag)
+struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
{
- WIN_servent* retval = NULL;
+ struct WS_servent* retval = NULL;
struct servent* serv;
- int i = wsi_strtolo( name, proto );
+ char *name_str;
+ char *proto_str = NULL;
+
+ if (!(name_str = strdup_lower(name))) return NULL;
- if( i ) {
- EnterCriticalSection( &csWSgetXXXbyYYY );
- serv = getservbyname(local_buffer,
- proto && *proto ? (local_buffer + i) : NULL);
- if( serv != NULL )
+ if (proto && *proto)
+ {
+ if (!(proto_str = strdup_lower(proto)))
{
- if( WS_dup_se(serv, dup_flag) )
- retval = se_buffer;
- else SetLastError(WSAENOBUFS);
- }
- else {
- MESSAGE("service %s protocol %s not found; You might want to add "
- "this to /etc/services\n", debugstr_a(local_buffer),
- proto ? debugstr_a(local_buffer+i):"*");
- SetLastError(WSANO_DATA);
+ HeapFree( GetProcessHeap(), 0, name_str );
+ return NULL;
}
- LeaveCriticalSection( &csWSgetXXXbyYYY );
}
- else SetLastError(WSAENOBUFS);
- return retval;
-}
-
-/***********************************************************************
- * getservbyname (WINSOCK.55)
- */
-SEGPTR WINAPI WINSOCK_getservbyname16(const char *name, const char *proto)
-{
- TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
- if (!__ws_getservbyname(name, proto, WS_DUP_SEGPTR)) return 0;
- return se_buffer_seg;
-}
-/***********************************************************************
- * getservbyname (WS2_32.55)
- */
-struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
-{
- TRACE( "%s, %s\n", debugstr_a(name), debugstr_a(proto) );
- return __ws_getservbyname(name, proto, WS_DUP_LINEAR);
+ EnterCriticalSection( &csWSgetXXXbyYYY );
+ serv = getservbyname(name_str, proto_str);
+ if( serv != NULL )
+ {
+ retval = WS_dup_se(serv);
+ }
+ else SetLastError(WSANO_DATA);
+ LeaveCriticalSection( &csWSgetXXXbyYYY );
+ if (proto_str) HeapFree( GetProcessHeap(), 0, proto_str );
+ HeapFree( GetProcessHeap(), 0, name_str );
+ TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
+ return retval;
}
/***********************************************************************
- * __ws_getservbyport
+ * getservbyport (WS2_32.56)
*/
-static WIN_servent* __ws_getservbyport(int port, const char* proto, int dup_flag)
+struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
{
- WIN_servent* retval = NULL;
+ struct WS_servent* retval = NULL;
#ifdef HAVE_GETSERVBYPORT
struct servent* serv;
- if (!proto || wsi_strtolo( proto, NULL )) {
- EnterCriticalSection( &csWSgetXXXbyYYY );
- if( (serv = getservbyport(port, proto && *proto ? local_buffer :
- NULL)) != NULL ) {
- if( WS_dup_se(serv, dup_flag) )
- retval = se_buffer;
- else SetLastError(WSAENOBUFS);
- }
- else {
- MESSAGE("service on port %lu protocol %s not found; You might want to add "
- "this to /etc/services\n", (unsigned long)ntohl(port),
- proto ? debugstr_a(local_buffer) : "*");
- SetLastError(WSANO_DATA);
- }
- LeaveCriticalSection( &csWSgetXXXbyYYY );
+ char *proto_str = NULL;
+
+ if (proto && *proto)
+ {
+ if (!(proto_str = strdup_lower(proto))) return NULL;
}
- else SetLastError(WSAENOBUFS);
+ EnterCriticalSection( &csWSgetXXXbyYYY );
+ if( (serv = getservbyport(port, proto_str)) != NULL ) {
+ retval = WS_dup_se(serv);
+ }
+ else SetLastError(WSANO_DATA);
+ LeaveCriticalSection( &csWSgetXXXbyYYY );
+ if (proto_str) HeapFree( GetProcessHeap(), 0, proto_str );
#endif
+ TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
return retval;
}
-/***********************************************************************
- * getservbyport (WINSOCK.56)
- */
-SEGPTR WINAPI WINSOCK_getservbyport16(INT16 port, const char *proto)
-{
- TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
- if (!__ws_getservbyport(port, proto, WS_DUP_SEGPTR)) return 0;
- return se_buffer_seg;
-}
-
-/***********************************************************************
- * getservbyport (WS2_32.56)
- */
-struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
-{
- TRACE("%d (i.e. port %d), %s\n", (int)port, (int)ntohl(port), debugstr_a(proto));
- return __ws_getservbyport(port, proto, WS_DUP_LINEAR);
-}
-
/***********************************************************************
* gethostname (WS2_32.57)
return SOCKET_ERROR;
}
-/***********************************************************************
- * gethostname (WINSOCK.57)
- */
-INT16 WINAPI WINSOCK_gethostname16(char *name, INT16 namelen)
-{
- return (INT16)WS_gethostname(name, namelen);
-}
-
/* ------------------------------------- Windows sockets extensions -- *
* *
{
DWORD r;
- TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
+ TRACE ( "socket %04x ovl %p trans %p, wait %d flags %p\n",
s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
if ( !(lpOverlapped && lpOverlapped->hEvent) )
return SOCKET_ERROR;
}
-/***********************************************************************
- * WSAAsyncSelect (WINSOCK.101)
- */
-INT16 WINAPI WSAAsyncSelect16(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, LONG lEvent)
-{
- return (INT16)WSAAsyncSelect( s, HWND_32(hWnd), wMsg, lEvent );
-}
-
-/***********************************************************************
- * WSARecvEx (WINSOCK.1107)
- *
- * See description for WSARecvEx()
- */
-INT16 WINAPI WSARecvEx16(SOCKET16 s, char *buf, INT16 len, INT16 *flags)
-{
- FIXME("(WSARecvEx16) partial packet return value not set \n");
-
- return WINSOCK_recv16(s, buf, len, *flags);
-}
-
-
/***********************************************************************
* WSACreateEvent (WS2_32.31)
*
return INVALID_SOCKET;
}
-
/***********************************************************************
- * __WSAFDIsSet (WINSOCK.151)
+ * WSAJoinLeaf (WS2_32.58)
+ *
*/
-INT16 WINAPI __WSAFDIsSet16(SOCKET16 s, ws_fd_set16 *set)
-{
- int i = set->fd_count;
-
- TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
-
- while (i--)
- if (set->fd_array[i] == s) return 1;
- return 0;
+SOCKET WINAPI WSAJoinLeaf(
+ SOCKET s,
+ const struct WS_sockaddr *addr,
+ int addrlen,
+ LPWSABUF lpCallerData,
+ LPWSABUF lpCalleeData,
+ LPQOS lpSQOS,
+ LPQOS lpGQOS,
+ DWORD dwFlags)
+{
+ FIXME("stub.\n");
+ return INVALID_SOCKET;
}
/***********************************************************************
}
-/***********************************************************************
- * WSASetBlockingHook (WINSOCK.109)
- */
-FARPROC16 WINAPI WSASetBlockingHook16(FARPROC16 lpBlockFunc)
-{
- FARPROC16 prev = (FARPROC16)blocking_hook;
- blocking_hook = (FARPROC)lpBlockFunc;
- TRACE("hook %p\n", lpBlockFunc);
- return prev;
-}
-
-
/***********************************************************************
* WSASetBlockingHook (WS2_32.109)
*/
}
-/***********************************************************************
- * WSAUnhookBlockingHook (WINSOCK.110)
- */
-INT16 WINAPI WSAUnhookBlockingHook16(void)
-{
- blocking_hook = WSA_DefaultBlockingHook;
- return 0;
-}
-
-
/***********************************************************************
* WSAUnhookBlockingHook (WS2_32.110)
*/
return j;
}
-static int list_dup(char** l_src, char* ref, char* base, int item_size)
+static int list_dup(char** l_src, char** l_to, int item_size)
{
- /* base is either either equal to ref or 0 or SEGPTR */
-
- char* p = ref;
- char** l_to = (char**)ref;
- int i,j,k;
-
- for(j=0;l_src[j];j++) ;
- p += (j + 1) * sizeof(char*);
- for(i=0;i<j;i++)
- { l_to[i] = base + (p - ref);
- k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
- memcpy(p, l_src[i], k); p += k; }
+ char *p;
+ int i;
+
+ for (i = 0; l_src[i]; i++) ;
+ p = (char *)(l_to + i + 1);
+ for (i = 0; l_src[i]; i++)
+ {
+ int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
+ memcpy(p, l_src[i], count);
+ l_to[i] = p;
+ p += count;
+ }
l_to[i] = NULL;
- return (p - ref);
+ return (p - (char *)l_to);
}
/* ----- hostent */
-static int hostent_size(struct hostent* p_he)
-{
- int size = 0;
- if( p_he )
- { size = sizeof(struct hostent);
- size += strlen(p_he->h_name) + 1;
- size += list_size(p_he->h_aliases, 0);
- size += list_size(p_he->h_addr_list, p_he->h_length ); }
- return size;
-}
-
/* duplicate hostent entry
* and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
* Dito for protoent and servent.
*/
-static int WS_dup_he(struct hostent* p_he, int flag)
+static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
{
- /* Convert hostent structure into ws_hostent so that the data fits
- * into local_buffer. Internal pointers can be linear, SEGPTR, or
- * relative to local_buffer depending on "flag" value. Returns size
- * of the data copied.
- */
-
- int size = hostent_size(p_he);
- if( size )
- {
- char *p_name,*p_aliases,*p_addr,*p_base,*p;
- char *p_to;
- struct ws_hostent16 *p_to16;
- struct WS_hostent *p_to32;
-
- check_buffer_he(size);
- p_to = he_buffer;
- p_to16 = he_buffer;
- p_to32 = he_buffer;
-
- p = p_to;
- p_base = (flag & WS_DUP_SEGPTR) ? (char*)he_buffer_seg : he_buffer;
- p += (flag & WS_DUP_SEGPTR) ?
- sizeof(struct ws_hostent16) : sizeof(struct WS_hostent);
- p_name = p;
- strcpy(p, p_he->h_name); p += strlen(p) + 1;
- p_aliases = p;
- p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0);
- p_addr = p;
- list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length);
-
- if (flag & WS_DUP_SEGPTR) /* Win16 */
- {
- p_to16->h_addrtype = (INT16)p_he->h_addrtype;
- p_to16->h_length = (INT16)p_he->h_length;
- p_to16->h_name = (SEGPTR)(p_base + (p_name - p_to));
- p_to16->h_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
- p_to16->h_addr_list = (SEGPTR)(p_base + (p_addr - p_to));
- size += (sizeof(struct ws_hostent16) - sizeof(struct hostent));
- }
- else /* Win32 */
- {
- p_to32->h_addrtype = p_he->h_addrtype;
- p_to32->h_length = p_he->h_length;
- p_to32->h_name = (p_base + (p_name - p_to));
- p_to32->h_aliases = (char **)(p_base + (p_aliases - p_to));
- p_to32->h_addr_list = (char **)(p_base + (p_addr - p_to));
- size += (sizeof(struct WS_hostent) - sizeof(struct hostent));
- }
- }
- return size;
+ char *p;
+ struct WS_hostent *p_to;
+
+ int size = (sizeof(*p_he) +
+ strlen(p_he->h_name) + 1 +
+ list_size(p_he->h_aliases, 0) +
+ list_size(p_he->h_addr_list, p_he->h_length));
+
+ if (!(p_to = check_buffer_he(size))) return NULL;
+ p_to->h_addrtype = p_he->h_addrtype;
+ p_to->h_length = p_he->h_length;
+
+ p = (char *)(p_to + 1);
+ p_to->h_name = p;
+ strcpy(p, p_he->h_name);
+ p += strlen(p) + 1;
+
+ p_to->h_aliases = (char **)p;
+ p += list_dup(p_he->h_aliases, p_to->h_aliases, 0);
+
+ p_to->h_addr_list = (char **)p;
+ list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length);
+ return p_to;
}
/* ----- protoent */
-static int protoent_size(struct protoent* p_pe)
+static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe)
{
- int size = 0;
- if( p_pe )
- { size = sizeof(struct protoent);
- size += strlen(p_pe->p_name) + 1;
- size += list_size(p_pe->p_aliases, 0); }
- return size;
-}
+ char *p;
+ struct WS_protoent *p_to;
-static int WS_dup_pe(struct protoent* p_pe, int flag)
-{
- int size = protoent_size(p_pe);
- if( size )
- {
- char *p_to;
- struct ws_protoent16 *p_to16;
- struct WS_protoent *p_to32;
- char *p_name,*p_aliases,*p_base,*p;
-
- check_buffer_pe(size);
- p_to = pe_buffer;
- p_to16 = pe_buffer;
- p_to32 = pe_buffer;
- p = p_to;
- p_base = (flag & WS_DUP_SEGPTR) ? (char*)pe_buffer_seg : pe_buffer;
- p += (flag & WS_DUP_SEGPTR) ?
- sizeof(struct ws_protoent16) : sizeof(struct WS_protoent);
- p_name = p;
- strcpy(p, p_pe->p_name); p += strlen(p) + 1;
- p_aliases = p;
- list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0);
-
- if (flag & WS_DUP_SEGPTR) /* Win16 */
- {
- p_to16->p_proto = (INT16)p_pe->p_proto;
- p_to16->p_name = (SEGPTR)(p_base) + (p_name - p_to);
- p_to16->p_aliases = (SEGPTR)((p_base) + (p_aliases - p_to));
- size += (sizeof(struct ws_protoent16) - sizeof(struct protoent));
- }
- else /* Win32 */
- {
- p_to32->p_proto = p_pe->p_proto;
- p_to32->p_name = (p_base) + (p_name - p_to);
- p_to32->p_aliases = (char **)((p_base) + (p_aliases - p_to));
- size += (sizeof(struct WS_protoent) - sizeof(struct protoent));
- }
- }
- return size;
+ int size = (sizeof(*p_pe) +
+ strlen(p_pe->p_name) + 1 +
+ list_size(p_pe->p_aliases, 0));
+
+ if (!(p_to = check_buffer_pe(size))) return NULL;
+ p_to->p_proto = p_pe->p_proto;
+
+ p = (char *)(p_to + 1);
+ p_to->p_name = p;
+ strcpy(p, p_pe->p_name);
+ p += strlen(p) + 1;
+
+ p_to->p_aliases = (char **)p;
+ list_dup(p_pe->p_aliases, p_to->p_aliases, 0);
+ return p_to;
}
/* ----- servent */
-static int servent_size(struct servent* p_se)
+static struct WS_servent *WS_dup_se(const struct servent* p_se)
{
- int size = 0;
- if( p_se )
- { size += sizeof(struct servent);
- size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
- size += list_size(p_se->s_aliases, 0); }
- return size;
-}
+ char *p;
+ struct WS_servent *p_to;
-static int WS_dup_se(struct servent* p_se, int flag)
-{
- int size = servent_size(p_se);
- if( size )
- {
- char *p_name,*p_aliases,*p_proto,*p_base,*p;
- char *p_to;
- struct ws_servent16 *p_to16;
- struct WS_servent *p_to32;
-
- check_buffer_se(size);
- p_to = se_buffer;
- p_to16 = se_buffer;
- p_to32 = se_buffer;
- p = p_to;
- p_base = (flag & WS_DUP_SEGPTR) ? (char*)se_buffer_seg : se_buffer;
- p += (flag & WS_DUP_SEGPTR) ?
- sizeof(struct ws_servent16) : sizeof(struct WS_servent);
- p_name = p;
- strcpy(p, p_se->s_name); p += strlen(p) + 1;
- p_proto = p;
- strcpy(p, p_se->s_proto); p += strlen(p) + 1;
- p_aliases = p;
- list_dup(p_se->s_aliases, p, p_base + (p - p_to), 0);
-
- if (flag & WS_DUP_SEGPTR) /* Win16 */
- {
- p_to16->s_port = (INT16)p_se->s_port;
- p_to16->s_name = (SEGPTR)(p_base + (p_name - p_to));
- p_to16->s_proto = (SEGPTR)(p_base + (p_proto - p_to));
- p_to16->s_aliases = (SEGPTR)(p_base + (p_aliases - p_to));
- size += (sizeof(struct ws_servent16) - sizeof(struct servent));
- }
- else /* Win32 */
- {
- p_to32->s_port = p_se->s_port;
- p_to32->s_name = (p_base + (p_name - p_to));
- p_to32->s_proto = (p_base + (p_proto - p_to));
- p_to32->s_aliases = (char **)(p_base + (p_aliases - p_to));
- size += (sizeof(struct WS_servent) - sizeof(struct servent));
- }
- }
- return size;
+ int size = (sizeof(*p_se) +
+ strlen(p_se->s_proto) + 1 +
+ strlen(p_se->s_name) + 1 +
+ list_size(p_se->s_aliases, 0));
+
+ if (!(p_to = check_buffer_se(size))) return NULL;
+ p_to->s_port = p_se->s_port;
+
+ p = (char *)(p_to + 1);
+ p_to->s_name = p;
+ strcpy(p, p_se->s_name);
+ p += strlen(p) + 1;
+
+ p_to->s_proto = p;
+ strcpy(p, p_se->s_proto);
+ p += strlen(p) + 1;
+
+ p_to->s_aliases = (char **)p;
+ list_dup(p_se->s_aliases, p_to->s_aliases, 0);
+ return p_to;
}
/* ----------------------------------- error handling */
-UINT16 wsaErrno(void)
+UINT wsaErrno(void)
{
int loc_errno = errno;
WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
}
}
-UINT16 wsaHerrno(int loc_errno)
+UINT wsaHerrno(int loc_errno)
{
WARN("h_errno %d.\n", loc_errno);
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
{
- int i, n, fd, err = WSAENOTSOCK, flags, ret;
+ unsigned int i;
+ int n, fd, err = WSAENOTSOCK, flags, ret;
struct iovec* iovec;
struct ws2_async *wsa;
- enum fd_type type;
TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
(lpFromlen ? *lpFromlen : -1L),
lpOverlapped, lpCompletionRoutine);
- fd = _get_sock_fd_type( s, GENERIC_READ, &type, &flags );
- TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );
+ fd = get_sock_fd( s, GENERIC_READ, &flags );
+ TRACE ( "fd=%d, flags=%x\n", fd, flags );
- if (fd == -1)
+ if (fd == -1) return SOCKET_ERROR;
+
+ if (flags & FD_FLAG_RECV_SHUTDOWN)
{
- err = WSAGetLastError ();
- goto error;
+ WSASetLastError ( WSAESHUTDOWN );
+ goto err_close;
}
iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
{
/* block here */
/* FIXME: OOB and exceptfds? */
- do_block(fd, POLLIN);
+ int timeout = GET_RCVTIMEO(fd);
+ if( !do_block(fd, POLLIN, timeout)) {
+ err = WSAETIMEDOUT;
+ /* a timeout is not fatal */
+ _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
+ goto err_free;
+ }
}
n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
*lpNumberOfBytesRecvd = n;
HeapFree (GetProcessHeap(), 0, iovec);
- close(fd);
+ release_sock_fd( s, fd );
_enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
return 0;
HeapFree (GetProcessHeap(), 0, iovec);
err_close:
- close (fd);
+ release_sock_fd( s, fd );
error:
WARN(" -> ERROR %d\n", err);
SOCKET cs;
SOCKADDR src_addr, dst_addr;
- TRACE("Socket %u, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
+ TRACE("Socket %04x, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
s, addr, addrlen, lpfnCondition, dwCallbackData);
}
}
-/***********************************************************************
- * WSAEnumProtocolsA (WS2_32.37)
- */
-int WINAPI WSAEnumProtocolsA(LPINT lpiProtocols, LPWSAPROTOCOL_INFOA lpProtocolBuffer, LPDWORD lpdwBufferLength)
-{
- FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
- return 0;
-}
-
-/***********************************************************************
- * WSAEnumProtocolsW (WS2_32.38)
- */
-int WINAPI WSAEnumProtocolsW(LPINT lpiProtocols, LPWSAPROTOCOL_INFOW lpProtocolBuffer, LPDWORD lpdwBufferLength)
-{
- FIXME("(%p,%p,%p): stub\n", lpiProtocols,lpProtocolBuffer, lpdwBufferLength);
- return 0;
-}
-
/***********************************************************************
* WSADuplicateSocketA (WS2_32.32)
*/
WSASetLastError(WSATYPE_NOT_FOUND);
return SOCKET_ERROR;
}
+
+/***********************************************************************
+ * WSAStringToAddressA (WS2_32.80)
+ */
+INT WINAPI WSAStringToAddressA(LPSTR AddressString,
+ INT AddressFamily,
+ LPWSAPROTOCOL_INFOA lpProtocolInfo,
+ LPSOCKADDR lpAddress,
+ LPINT lpAddressLength)
+{
+ INT res=0;
+ LONG inetaddr;
+ LPSTR workBuffer=NULL,ptrPort;
+
+ if (AddressString)
+ {
+ workBuffer = HeapAlloc( GetProcessHeap(), 0, strlen(AddressString)+1 );
+ if (workBuffer)
+ {
+ strcpy(workBuffer,AddressString);
+ switch (AddressFamily)
+ {
+ case AF_INET:
+ /* caller wants to know the size of the socket buffer */
+ if (*lpAddressLength < sizeof(SOCKADDR_IN))
+ {
+ *lpAddressLength = sizeof(SOCKADDR_IN);
+ res = WSAEFAULT;
+ }
+ else
+ {
+ /* caller wants to translate an AdressString into a SOCKADDR */
+ if (lpAddress)
+ {
+ memset(lpAddress,0,sizeof(SOCKADDR_IN));
+ ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET;
+ ptrPort = strchr(workBuffer,':');
+ if (ptrPort)
+ {
+ ((LPSOCKADDR_IN)lpAddress)->sin_port = (u_short)atoi(ptrPort+1);
+ *ptrPort = '\0';
+ }
+ else
+ ((LPSOCKADDR_IN)lpAddress)->sin_port = 0;
+ inetaddr = inet_addr(workBuffer);
+ if (inetaddr != INADDR_NONE)
+ {
+ ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr;
+ res = 0;
+ }
+ else
+ res = WSAEINVAL;
+ }
+ }
+ if (lpProtocolInfo)
+ FIXME("(%s, %x, %p, %p, %p) - ProtocolInfo not implemented!\n",
+ AddressString, AddressFamily,
+ lpProtocolInfo, lpAddress, lpAddressLength);
+
+ break;
+ default:
+ FIXME("(%s, %x, %p, %p, %p) - AddressFamiliy not implemented!\n",
+ AddressString, AddressFamily,
+ lpProtocolInfo, lpAddress, lpAddressLength);
+ }
+ HeapFree( GetProcessHeap(), 0, workBuffer );
+ }
+ else
+ res = WSA_NOT_ENOUGH_MEMORY;
+ }
+ else
+ res = WSAEINVAL;
+
+ if (!res) return 0;
+ WSASetLastError(res);
+ return SOCKET_ERROR;
+}
+
+/***********************************************************************
+ * WSAStringToAddressW (WS2_32.81)
+ *
+ * Does anybody know if this functions allows to use hebrew/arabic/chinese... digits?
+ * If this should be the case, it would be required to map these digits
+ * to Unicode digits (0-9) using FoldString first.
+ */
+INT WINAPI WSAStringToAddressW(LPWSTR AddressString,
+ INT AddressFamily,
+ LPWSAPROTOCOL_INFOW lpProtocolInfo,
+ LPSOCKADDR lpAddress,
+ LPINT lpAddressLength)
+{
+ INT sBuffer,res=0;
+ LPSTR workBuffer=NULL;
+ WSAPROTOCOL_INFOA infoA;
+ LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL;
+
+ /* if ProtocolInfo is available - convert to ANSI variant */
+ if (lpProtocolInfo)
+ {
+ lpProtoInfoA = &infoA;
+ memcpy( lpProtoInfoA, lpProtocolInfo, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
+
+ if (!WideCharToMultiByte( CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
+ lpProtoInfoA->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL ))
+ {
+ WSASetLastError( WSAEINVAL);
+ return SOCKET_ERROR;
+ }
+ }
+
+ if (AddressString)
+ {
+ /* Translate AddressString to ANSI code page - assumes that only
+ standard digits 0-9 are used with this API call */
+ sBuffer = WideCharToMultiByte( CP_ACP, 0, AddressString, -1, NULL, 0, NULL, NULL );
+ workBuffer = HeapAlloc( GetProcessHeap(), 0, sBuffer );
+
+ if (workBuffer)
+ {
+ WideCharToMultiByte( CP_ACP, 0, AddressString, -1, workBuffer, sBuffer, NULL, NULL );
+ res = WSAStringToAddressA(workBuffer,AddressFamily,lpProtoInfoA,
+ lpAddress,lpAddressLength);
+ HeapFree( GetProcessHeap(), 0, workBuffer );
+ return res;
+ }
+ else
+ res = WSA_NOT_ENOUGH_MEMORY;
+ }
+ else
+ res = WSAEINVAL;
+
+ WSASetLastError(res);
+ return SOCKET_ERROR;
+}
+
+/***********************************************************************
+ * WSALookupServiceBeginA (WS2_32.59)
+ */
+INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
+ DWORD dwControlFlags,
+ LPHANDLE lphLookup)
+{
+ FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
+ lphLookup);
+ WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
+ return SOCKET_ERROR;
+}
+
+/***********************************************************************
+ * WSALookupServiceBeginW (WS2_32.60)
+ */
+INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
+ DWORD dwControlFlags,
+ LPHANDLE lphLookup)
+{
+ FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
+ lphLookup);
+ WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
+ return SOCKET_ERROR;
+}
+
+INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
+{
+ FIXME("(%p) Stub!\n", lpProviderId);
+
+ return NO_ERROR;
+}