Index: include/winsock.h =================================================================== RCS file: /home/wine/wine/include/winsock.h,v retrieving revision 1.34 diff -u -r1.34 winsock.h --- include/winsock.h 2001/08/24 19:14:56 1.34 +++ include/winsock.h 2001/09/12 18:23:10 @@ -441,17 +441,6 @@ #define WS_AF_MAX 27 -#include "pshpack1.h" - -struct ws_sockaddr_ipx -{ - SHORT sipx_family; - UINT sipx_network; - CHAR sipx_node[6]; - WORD sipx_port; -}; - -#include "poppack.h" #ifdef __cplusplus } Index: include/wsipx.h =================================================================== RCS file: /home/wine/wine/include/wsipx.h,v retrieving revision 1.1 diff -u -r1.1 wsipx.h --- include/wsipx.h 2001/01/12 23:15:55 1.1 +++ include/wsipx.h 2001/09/12 18:23:10 @@ -1,13 +1,21 @@ /* WCIPX.H */ -#ifndef _WINE_WCIPX_ -#define _WINE_WCIPX_ +#ifndef _WINE_WSIPX_ +#define _WINE_WSIPX_ #ifdef __cplusplus extern "C" { #endif /* defined(__cplusplus) */ +typedef struct ws_sockaddr_ipx +{ + short sa_family; + char sa_netnum[4]; + char sa_nodenum[6]; + unsigned short sa_socket; +} SOCKADDR_IPX, *PSOCKADDR_IPX, *LPSOCKADDR_IPX; + /* * constants */ @@ -20,4 +28,4 @@ } /* extern "C" */ #endif /* defined(__cplusplus) */ -#endif /* _WINE_WCIPX_ */ +#endif /* _WINE_WSIPX_ */ Index: dlls/winsock/socket.c =================================================================== RCS file: /home/wine/wine/dlls/winsock/socket.c,v retrieving revision 1.60 diff -u -r1.60 socket.c --- dlls/winsock/socket.c 2001/09/07 15:26:18 1.60 +++ dlls/winsock/socket.c 2001/09/12 18:22:55 @@ -91,6 +91,7 @@ #include "wingdi.h" #include "winuser.h" #include "winsock2.h" +#include "wsipx.h" #include "wine/winsock16.h" #include "winnt.h" #include "heap.h" @@ -153,6 +154,7 @@ int WS_dup_he(struct hostent* p_he, int flag); int WS_dup_pe(struct protoent* p_pe, int flag); int WS_dup_se(struct servent* p_se, int flag); +int WINAPI WSOCK32_getpeername(SOCKET s, ws_sockaddr *name, int *namelen); typedef void WIN_hostent; typedef void WIN_protoent; @@ -736,10 +738,13 @@ /* ----------------------------------- i/o APIs */ -/*********************************************************************** - * accept (WS2_32.1) - */ -static void WSOCK32_async_accept(SOCKET s, SOCKET as) +#ifdef HAVE_IPX +#define SUPPORTED_PF(pf) ((pf)==AF_INET || (pf)== AF_IPX) +#else +#define SUPPORTED_PF(pf) ((pf)==AF_INET) +#endif + +static void ws2_async_accept(SOCKET s, SOCKET as) { int q; /* queue socket for WSAAsyncSelect */ @@ -755,13 +760,131 @@ } /**********************************************************************/ + +/* Returns the converted address if successful, NULL if it was too small to + * start with. Note that the returned pointer may be the original pointer + * if no conversion is necessary. + */ +const struct sockaddr* ws_sockaddr_ws2u(const ws_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen) +{ + switch (wsaddr->sa_family) + { +#ifdef HAVE_IPX + case WS_AF_IPX: + { + struct ws_sockaddr_ipx* wsipx=(struct ws_sockaddr_ipx*)wsaddr; + struct sockaddr_ipx* uipx; + + if (wsaddrlensipx_family=AF_IPX; + uipx->sipx_port=wsipx->sa_socket; + /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node + * in one go + */ + memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node)); + uipx->sipx_type=IPX_FRAME_NONE; + uipx->sipx_zero=0; + return (const struct sockaddr*)uipx; + } +#endif + + default: + if (wsaddrlensa_family) + { #ifdef HAVE_IPX - struct ws_sockaddr_ipx* addr2 = (struct ws_sockaddr_ipx *)addr; + case AF_IPX: + { + struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr; + struct ws_sockaddr_ipx* wsipx=(struct ws_sockaddr_ipx*)wsaddr; + + res=-1; + switch (*wsaddrlen) /* how much can we copy? */ + { + default: + res=0; /* enough */ + wsipx->sa_socket=uipx->sipx_port; + /* fall through */ + case 13: + case 12: + memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum)); + /* fall through */ + case 11: + case 10: + case 9: + case 8: + case 7: + case 6: + memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum)); + /* fall through */ + case 5: + case 4: + case 3: + case 2: + wsipx->sa_family=AF_IPX; + /* fall through */ + case 1: + case 0: + /* way too small */ + } + } + break; #endif + + default: + /* No conversion needed */ + memcpy(wsaddr,uaddr,*wsaddrlen); + res=(*wsaddrlensipx_family == AF_IPX) { - addr = (struct sockaddr *) - malloc(addrlen32 ? *addrlen32 : sizeof(*addr2)); - memcpy(addr, addr2, - addrlen32 ? *addrlen32 : sizeof(*addr2)); - addr2->sipx_family = WS_AF_IPX; - addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network; - addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port; - memcpy(addr2->sipx_node, - ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN); - free(addr); - } -#endif - } else SetLastError(wsaErrno()); - close(fd); + WSOCK32_getpeername(fd, addr, addrlen32); if (omask & FD_WINE_SERVEVENT) - WSOCK32_async_accept(s, as); + ws2_async_accept(s, as); return as; } } + else + { + SetLastError(WSAENOTSOCK); + } return INVALID_SOCKET; } /*********************************************************************** * accept (WINSOCK.1) */ -SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr, +SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, ws_sockaddr* addr, INT16* addrlen16 ) { INT addrlen32 = addrlen16 ? *addrlen16 : 0; @@ -832,80 +941,73 @@ /*********************************************************************** * bind (WS2_32.2) */ -INT WINAPI WSOCK32_bind(SOCKET s, struct sockaddr *name, INT namelen) +int WINAPI WSOCK32_bind(SOCKET s, const ws_sockaddr* name, int namelen) { -#ifdef HAVE_IPX - struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name; -#endif int fd = _get_sock_fd(s); + int res; - TRACE("socket %04x, ptr %8x, length %d\n", s, (int) name, namelen); + TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen); #if DEBUG_SOCKADDR dump_sockaddr(name); #endif + res=SOCKET_ERROR; if (fd != -1) { - /* FIXME: what family does this really map to on the Unix side? */ - if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP) - ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC; -#ifdef HAVE_IPX - else if (name && - ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX) - { - name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx)); - memset(name, '\0', sizeof(struct sockaddr_ipx)); - ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX; - ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port; - ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network; - memcpy(((struct sockaddr_ipx *)name)->sipx_node, - name2->sipx_node, IPX_NODE_LEN); - namelen = sizeof(struct sockaddr_ipx); - } -#endif - if ( namelen >= sizeof(*name) ) - { - if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET -#ifdef HAVE_IPX - || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX -#endif - )) + if (!name || !SUPPORTED_PF(name->sa_family)) { - if ( bind(fd, name, namelen) < 0 ) - { - int loc_errno = errno; - WARN("\tfailure - errno = %i\n", errno); - errno = loc_errno; - switch(errno) - { - case EBADF: SetLastError(WSAENOTSOCK); break; - case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break; - default: SetLastError(wsaErrno());break; - } - } - else { -#ifdef HAVE_IPX - if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) - free(name); -#endif - close(fd); - return 0; /* success */ - } - } else SetLastError(WSAEAFNOSUPPORT); - } else SetLastError(WSAEFAULT); -#ifdef HAVE_IPX - if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) - free(name); -#endif - close(fd); + SetLastError(WSAEAFNOSUPPORT); + } + else + { + const struct sockaddr* uaddr; + int uaddrlen; + + uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen); + if (uaddr == NULL) + { + SetLastError(WSAEFAULT); + } + else + { + if (bind(fd, uaddr, uaddrlen) < 0) + { + int loc_errno = errno; + WARN("\tfailure - errno = %i\n", errno); + errno = loc_errno; + switch (errno) + { + case EBADF: + SetLastError(WSAENOTSOCK); + break; + case EADDRNOTAVAIL: + SetLastError(WSAEINVAL); + break; + default: + SetLastError(wsaErrno()); + break; + } + } + else + { + res=0; /* success */ + } + ws_sockaddr_free(uaddr,name); + } + } + close(fd); } - return SOCKET_ERROR; + else + { + SetLastError(WSAENOTSOCK); + } + return res; } /*********************************************************************** * bind (WINSOCK.2) */ -INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen) +INT16 WINAPI WINSOCK_bind16(SOCKET16 s, ws_sockaddr *name, INT16 namelen) { return (INT16)WSOCK32_bind( s, name, namelen ); } @@ -931,89 +1033,85 @@ /*********************************************************************** * connect (WS2_32.4) */ -INT WINAPI WSOCK32_connect(SOCKET s, struct sockaddr *name, INT namelen) +int WINAPI WSOCK32_connect(SOCKET s, const ws_sockaddr* name, int namelen) { -#ifdef HAVE_IPX - struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name; -#endif - int fd = _get_sock_fd(s); + int fd = _get_sock_fd(s); - TRACE("socket %04x, ptr %8x, length %d\n", s, (int) name, namelen); + TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen); #if DEBUG_SOCKADDR - dump_sockaddr(name); + dump_sockaddr(name); #endif - if (fd != -1) - { - if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP) - ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC; -#ifdef HAVE_IPX - else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX) - { - name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx)); - memset(name, '\0', sizeof(struct sockaddr_ipx)); - ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX; - ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port; - ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network; - memcpy(((struct sockaddr_ipx *)name)->sipx_node, - name2->sipx_node, IPX_NODE_LEN); - namelen = sizeof(struct sockaddr_ipx); - } -#endif - if (connect(fd, name, namelen) == 0) { - close(fd); - goto connect_success; - } - if (errno == EINPROGRESS) + if (fd != -1) { - /* tell wineserver that a connection is in progress */ - _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE, - FD_CONNECT|FD_READ|FD_WRITE, - FD_WINE_CONNECTED|FD_WINE_LISTENING); - if (_is_blocking(s)) - { - int result; - /* block here */ - do_block(fd, 7); - _sync_sock_state(s); /* let wineserver notice connection */ - /* retrieve any error codes from it */ - result = _get_sock_error(s, FD_CONNECT_BIT); - if (result) - SetLastError(result); - else { - close(fd); - goto connect_success; - } - } - else SetLastError(WSAEWOULDBLOCK); - close(fd); + const struct sockaddr* uaddr; + int uaddrlen; + + uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen); + if (uaddr == NULL) + { + SetLastError(WSAEFAULT); + } + else + { + int rc; + + rc=connect(fd, uaddr, uaddrlen); + ws_sockaddr_free(uaddr,name); + if (rc == 0) + goto connect_success; + } + + if (errno == EINPROGRESS) + { + /* tell wineserver that a connection is in progress */ + _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE, + FD_CONNECT|FD_READ|FD_WRITE, + FD_WINE_CONNECTED|FD_WINE_LISTENING); + if (_is_blocking(s)) + { + int result; + /* block here */ + do_block(fd, 7); + _sync_sock_state(s); /* let wineserver notice connection */ + /* retrieve any error codes from it */ + result = _get_sock_error(s, FD_CONNECT_BIT); + if (result) + SetLastError(result); + else + { + goto connect_success; + } + } + else + { + SetLastError(WSAEWOULDBLOCK); + } + } + else + { + SetLastError(wsaErrno()); + } + close(fd); } else { - SetLastError(wsaErrno()); - close(fd); + SetLastError(WSAENOTSOCK); } - } -#ifdef HAVE_IPX - if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) - free(name); -#endif - return SOCKET_ERROR; + return SOCKET_ERROR; + connect_success: -#ifdef HAVE_IPX - if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) - free(name); -#endif + close(fd); _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE, - FD_WINE_CONNECTED|FD_READ|FD_WRITE, - FD_CONNECT|FD_WINE_LISTENING); - return 0; + FD_WINE_CONNECTED|FD_READ|FD_WRITE, + FD_CONNECT|FD_WINE_LISTENING); + return 0; } /*********************************************************************** * connect (WINSOCK.4) */ -INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen) +INT16 WINAPI WINSOCK_connect16(SOCKET16 s, ws_sockaddr *name, INT16 namelen) { return (INT16)WSOCK32_connect( s, name, namelen ); } @@ -1021,44 +1119,47 @@ /*********************************************************************** * getpeername (WS2_32.5) */ -INT WINAPI WSOCK32_getpeername(SOCKET s, struct sockaddr *name, - INT *namelen) +int WINAPI WSOCK32_getpeername(SOCKET s, ws_sockaddr *name, int *namelen) { -#ifdef HAVE_IPX - struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name; -#endif int fd = _get_sock_fd(s); + int res; + + TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen); - TRACE("socket: %04x, ptr %8x, ptr %8x\n", s, (int) name, *namelen); + res=SOCKET_ERROR; if (fd != -1) { - if (getpeername(fd, name, namelen) == 0) { -#ifdef HAVE_IPX - if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) { - name = (struct sockaddr *) - malloc(namelen ? *namelen : sizeof(*name2)); - memcpy(name, name2, namelen ? *namelen : sizeof(*name2)); - name2->sipx_family = WS_AF_IPX; - name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network; - name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port; - memcpy(name2->sipx_node, - ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN); - free(name); - } -#endif - close(fd); - return 0; - } - SetLastError(wsaErrno()); - close(fd); + struct sockaddr* uaddr; + int uaddrlen; + + uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen); + if (getpeername(fd, uaddr, &uaddrlen) != 0) + { + SetLastError(wsaErrno()); + } + else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0) + { + /* The buffer was too small */ + SetLastError(WSAEFAULT); + } + else + { + res=0; + } + ws_sockaddr_free(uaddr,name); + close(fd); } - return SOCKET_ERROR; + else + { + SetLastError(WSAENOTSOCK); + } + return res; } /*********************************************************************** * getpeername (WINSOCK.5) */ -INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name, +INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, ws_sockaddr *name, INT16 *namelen16) { INT namelen32 = *namelen16; @@ -1075,44 +1176,46 @@ /*********************************************************************** * getsockname (WS2_32.6) */ -INT WINAPI WSOCK32_getsockname(SOCKET s, struct sockaddr *name, - INT *namelen) +int WINAPI WSOCK32_getsockname(SOCKET s, ws_sockaddr *name, int *namelen) { -#ifdef HAVE_IPX - struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name; -#endif int fd = _get_sock_fd(s); + int res; + + TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen); - TRACE("socket: %04x, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen); + res=SOCKET_ERROR; if (fd != -1) { - if (getsockname(fd, name, namelen) == 0) { -#ifdef HAVE_IPX - if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) { - name = (struct sockaddr *) - malloc(namelen ? *namelen : sizeof(*name2)); - memcpy(name, name2, namelen ? *namelen : sizeof(*name2)); - name2->sipx_family = WS_AF_IPX; - name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network; - name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port; - memcpy(name2->sipx_node, - ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN); - free(name); - } -#endif - close(fd); - return 0; - } - SetLastError(wsaErrno()); - close(fd); + struct sockaddr* uaddr; + int uaddrlen; + + uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen); + if (getsockname(fd, uaddr, &uaddrlen) != 0) + { + SetLastError(wsaErrno()); + } + else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0) + { + /* The buffer was too small */ + SetLastError(WSAEFAULT); + } + else + { + res=0; + } + close(fd); } - return SOCKET_ERROR; + else + { + SetLastError(WSAENOTSOCK); + } + return res; } /*********************************************************************** * getsockname (WINSOCK.6) */ -INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name, +INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, ws_sockaddr *name, INT16 *namelen16) { INT retVal; @@ -1684,77 +1787,70 @@ /*********************************************************************** * recvfrom (WS2_32.17) */ -INT WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, INT flags, - struct sockaddr *from, INT *fromlen32) +int WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, int flags, + ws_sockaddr *from, int *fromlen) { -#ifdef HAVE_IPX - struct ws_sockaddr_ipx* from2 = (struct ws_sockaddr_ipx *)from; -#endif int fd = _get_sock_fd(s); + int res; TRACE("socket %04x, ptr %08x, len %d, flags %d\n", s, (unsigned)buf, len, flags); #if DEBUG_SOCKADDR - if( from ) dump_sockaddr(from); - else DPRINTF("from = NULL\n"); + if (from) + dump_sockaddr(from); + else + DPRINTF("from = NULL\n"); #endif + res=SOCKET_ERROR; if (fd != -1) { - int length; + struct sockaddr* uaddr; + int uaddrlen; + int length; - if (_is_blocking(s)) - { - /* block here */ - /* FIXME: OOB and exceptfds */ - do_block(fd, 1); - } - if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0) - { - TRACE(" -> %i bytes\n", length); + if (_is_blocking(s)) + { + /* block here */ + /* FIXME: OOB and exceptfds */ + do_block(fd, 1); + } -#ifdef HAVE_IPX - if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) { - from = (struct sockaddr *) - malloc(fromlen32 ? *fromlen32 : sizeof(*from2)); - memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2)); - from2->sipx_family = WS_AF_IPX; - from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network; - from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port; - memcpy(from2->sipx_node, - ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN); - free(from); - } -#endif - close(fd); - _enable_event(s, FD_READ, 0, 0); - return length; - } - SetLastError(wsaErrno()); - close(fd); + uaddr=ws_sockaddr_alloc(from,fromlen,&uaddrlen); + length=recvfrom(fd, buf, len, flags, uaddr, &uaddrlen); + if (length < 0) + { + SetLastError(wsaErrno()); + WARN(" -> ERROR\n"); + } + else if (ws_sockaddr_u2ws(uaddr,uaddrlen,from,fromlen) != 0) + { + /* The from buffer was too small, but we read the data + * anyway. Is that really bad? + */ + SetLastError(WSAEFAULT); + WARN(" -> WSAEFAULT\n"); + } + else + { + TRACE(" -> %i bytes\n", length); + _enable_event(s, FD_READ, 0, 0); + res=length; + } + close(fd); } - else SetLastError(WSAENOTSOCK); - WARN(" -> ERROR\n"); -#ifdef HAVE_IPX - if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) { - from = (struct sockaddr *) - malloc(fromlen32 ? *fromlen32 : sizeof(*from2)); - memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2)); - from2->sipx_family = WS_AF_IPX; - from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network; - from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port; - memcpy(from2->sipx_node, - ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN); - free(from); + else + { + SetLastError(WSAENOTSOCK); + WARN(" -> WSAENOTSOCK\n"); } -#endif - return SOCKET_ERROR; + return res; } /*********************************************************************** * recvfrom (WINSOCK.17) */ INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags, - struct sockaddr *from, INT16 *fromlen16) + ws_sockaddr *from, INT16 *fromlen16) { INT fromlen32; INT *p = &fromlen32; @@ -1943,72 +2043,56 @@ /*********************************************************************** * sendto (WS2_32.20) */ -INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags, - struct sockaddr *to, INT tolen) +int WINAPI WSOCK32_sendto(SOCKET s, const char *buf, int len, int flags, + const ws_sockaddr *to, int tolen) { -#ifdef HAVE_IPX - struct ws_sockaddr_ipx* to2 = (struct ws_sockaddr_ipx *)to; -#endif int fd = _get_sock_fd(s); + int res; TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags); + + res=SOCKET_ERROR; if (fd != -1) { - INT length; + const struct sockaddr* uaddr; + int uaddrlen; - if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP) - ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC; -#ifdef HAVE_IPX - else if (to && - ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX) - { - to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx)); - memset(to, '\0', sizeof(struct sockaddr_ipx)); - ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX; - ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port; - ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network; - memcpy(((struct sockaddr_ipx *)to)->sipx_node, - to2->sipx_node, IPX_NODE_LEN); - tolen = sizeof(struct sockaddr_ipx); - } -#endif - if (_is_blocking(s)) - { - /* block here */ - /* FIXME: exceptfds */ - do_block(fd, 2); - } - if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 ) - { - SetLastError(wsaErrno()); - if( GetLastError() == WSAEWOULDBLOCK ) - _enable_event(s, FD_WRITE, 0, 0); - } - else { -#ifdef HAVE_IPX - if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) { - free(to); - } -#endif - close(fd); - return length; - } - close(fd); + uaddr=ws_sockaddr_ws2u(to,tolen,&uaddrlen); + if (uaddr == NULL) + { + SetLastError(WSAEFAULT); + } + else + { + if (_is_blocking(s)) + { + /* block here */ + /* FIXME: exceptfds */ + do_block(fd, 2); + } + res=sendto(fd, buf, len, flags, uaddr, uaddrlen); + if (res < 0 ) + { + SetLastError(wsaErrno()); + if( GetLastError() == WSAEWOULDBLOCK ) + _enable_event(s, FD_WRITE, 0, 0); + } + ws_sockaddr_free(uaddr,to); + } + close(fd); } - else SetLastError(WSAENOTSOCK); -#ifdef HAVE_IPX - if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) { - free(to); + else + { + SetLastError(WSAENOTSOCK); } -#endif - return SOCKET_ERROR; + return res; } /*********************************************************************** * sendto (WINSOCK.20) */ INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags, - struct sockaddr *to, INT16 tolen) + ws_sockaddr *to, INT16 tolen) { return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen ); }