(file) Return to socket.c CVS log (file) (dir) Up to [RizwankCVS] / wine4 / wine / dlls / winsock

   1 cs130_tom 1.1 /*
   2                * based on Windows Sockets 1.1 specs
   3                * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
   4                *
   5                * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
   6                *
   7                * This library is free software; you can redistribute it and/or
   8                * modify it under the terms of the GNU Lesser General Public
   9                * License as published by the Free Software Foundation; either
  10                * version 2.1 of the License, or (at your option) any later version.
  11                *
  12                * This library is distributed in the hope that it will be useful,
  13                * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14                * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15                * Lesser General Public License for more details.
  16                *
  17                * You should have received a copy of the GNU Lesser General Public
  18                * License along with this library; if not, write to the Free Software
  19                * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20                *
  21                * NOTE: If you make any changes to fix a particular app, make sure
  22 cs130_tom 1.1  * they don't break something else like Netscape or telnet and ftp
  23                * clients and servers (www.winsite.com got a lot of those).
  24                */
  25               
  26               #include "config.h"
  27               #include "wine/port.h"
  28               
  29               #include <stdarg.h>
  30               #include <stdio.h>
  31               #include <string.h>
  32               #include <sys/types.h>
  33               #ifdef HAVE_SYS_IPC_H
  34               # include <sys/ipc.h>
  35               #endif
  36               #ifdef HAVE_SYS_IOCTL_H
  37               # include <sys/ioctl.h>
  38               #endif
  39               #ifdef HAVE_SYS_FILIO_H
  40               # include <sys/filio.h>
  41               #endif
  42               #ifdef HAVE_SYS_SOCKIO_H
  43 cs130_tom 1.1 # include <sys/sockio.h>
  44               #endif
  45               
  46               #if defined(__EMX__)
  47               # include <sys/so_ioctl.h>
  48               #endif
  49               
  50               #ifdef HAVE_SYS_PARAM_H
  51               # include <sys/param.h>
  52               #endif
  53               
  54               #ifdef HAVE_SYS_MSG_H
  55               # include <sys/msg.h>
  56               #endif
  57               #ifdef HAVE_SYS_WAIT_H
  58               # include <sys/wait.h>
  59               #endif
  60               #ifdef HAVE_SYS_UIO_H
  61               # include <sys/uio.h>
  62               #endif
  63               #ifdef HAVE_SYS_SOCKET_H
  64 cs130_tom 1.1 #include <sys/socket.h>
  65               #endif
  66               #ifdef HAVE_NETINET_IN_H
  67               # include <netinet/in.h>
  68               #endif
  69               #ifdef HAVE_NETINET_TCP_H
  70               # include <netinet/tcp.h>
  71               #endif
  72               #ifdef HAVE_ARPA_INET_H
  73               # include <arpa/inet.h>
  74               #endif
  75               #include <ctype.h>
  76               #include <fcntl.h>
  77               #include <errno.h>
  78               #ifdef HAVE_SYS_ERRNO_H
  79               #include <sys/errno.h>
  80               #endif
  81               #ifdef HAVE_NETDB_H
  82               #include <netdb.h>
  83               #endif
  84               #ifdef HAVE_UNISTD_H
  85 cs130_tom 1.1 # include <unistd.h>
  86               #endif
  87               #include <stdlib.h>
  88               #ifdef HAVE_ARPA_NAMESER_H
  89               # include <arpa/nameser.h>
  90               #endif
  91               #ifdef HAVE_RESOLV_H
  92               # include <resolv.h>
  93               #endif
  94               #ifdef HAVE_NET_IF_H
  95               # include <net/if.h>
  96               #endif
  97               #ifdef HAVE_IPX_GNU
  98               # include <netipx/ipx.h>
  99               # define HAVE_IPX
 100               #endif
 101               #ifdef HAVE_IPX_LINUX
 102               # include <asm/types.h>
 103               # include <linux/ipx.h>
 104               # define HAVE_IPX
 105               #endif
 106 cs130_tom 1.1 
 107               #ifdef HAVE_SYS_POLL_H
 108               # include <sys/poll.h>
 109               #endif
 110               #ifdef HAVE_SYS_TIME_H
 111               # include <sys/time.h>
 112               #endif
 113               
 114               #define NONAMELESSUNION
 115               #define NONAMELESSSTRUCT
 116               #include "windef.h"
 117               #include "winbase.h"
 118               #include "wingdi.h"
 119               #include "winuser.h"
 120               #include "winerror.h"
 121               #include "winnls.h"
 122               #include "winsock2.h"
 123               #include "mswsock.h"
 124               #include "ws2tcpip.h"
 125               #include "wsipx.h"
 126               #include "winnt.h"
 127 cs130_tom 1.1 #include "iphlpapi.h"
 128               #include "thread.h"
 129               #include "wine/server.h"
 130               #include "wine/debug.h"
 131               #include "ntstatus.h"
 132               #include "wine/unicode.h"
 133               
 134               #ifdef HAVE_IPX
 135               # include "wsnwlink.h"
 136               #endif
 137               
 138               
 139               #ifdef __FreeBSD__
 140               # define sipx_network    sipx_addr.x_net
 141               # define sipx_node       sipx_addr.x_host.c_host
 142               #endif  /* __FreeBSD__ */
 143               
 144               WINE_DEFAULT_DEBUG_CHANNEL(winsock);
 145               
 146               /* critical section to protect some non-rentrant net function */
 147               extern CRITICAL_SECTION csWSgetXXXbyYYY;
 148 cs130_tom 1.1 
 149               inline static const char *debugstr_sockaddr( const struct WS_sockaddr *a )
 150               {
 151                   if (!a) return "(nil)";
 152                   return wine_dbg_sprintf("{ family %d, address %s, port %d }",
 153                                           ((struct sockaddr_in *)a)->sin_family,
 154                                           inet_ntoa(((struct sockaddr_in *)a)->sin_addr),
 155                                           ntohs(((struct sockaddr_in *)a)->sin_port));
 156               }
 157               
 158               /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
 159               #define SOCKET2HANDLE(s) ((HANDLE)(s))
 160               #define HANDLE2SOCKET(h) ((SOCKET)(h))
 161               
 162               /****************************************************************
 163                * Async IO declarations
 164                ****************************************************************/
 165               
 166               typedef struct ws2_async
 167               {
 168                   HANDLE                              hSocket;
 169 cs130_tom 1.1     enum ws2_mode {ws2m_read, ws2m_write, ws2m_sd_read, ws2m_sd_write} mode;
 170                   LPWSAOVERLAPPED                     user_overlapped;
 171                   LPWSAOVERLAPPED_COMPLETION_ROUTINE  completion_func;
 172                   struct iovec                        *iovec;
 173                   int                                 n_iovecs;
 174                   struct WS_sockaddr                  *addr;
 175                   union
 176                   {
 177                       int val;     /* for send operations */
 178                       int *ptr;    /* for recv operations */
 179                   }                                   addrlen;
 180                   DWORD                               flags;
 181                   int                                 fd;
 182                   HANDLE                              event;
 183               } ws2_async;
 184               
 185               /****************************************************************/
 186               
 187               /* ----------------------------------- internal data */
 188               
 189               /* ws_... struct conversion flags */
 190 cs130_tom 1.1 
 191               typedef struct          /* WSAAsyncSelect() control struct */
 192               {
 193                 HANDLE      service, event, sock;
 194                 HWND        hWnd;
 195                 UINT        uMsg;
 196                 LONG        lEvent;
 197               } ws_select_info;
 198               
 199               #define WS_MAX_SOCKETS_PER_PROCESS      128     /* reasonable guess */
 200               #define WS_MAX_UDP_DATAGRAM             1024
 201               static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
 202               
 203               /* hostent's, servent's and protent's are stored in one buffer per thread,
 204                * as documented on MSDN for the functions that return any of the buffers */
 205               struct per_thread_data
 206               {
 207                   int opentype;
 208                   struct WS_hostent *he_buffer;
 209                   struct WS_protoent *pe_buffer;
 210 cs130_tom 1.2 
 211                   char *se_buffer;
 212                   struct WS_servent se;
 213               
 214 cs130_tom 1.1     int he_len;
 215                   int se_len;
 216                   int pe_len;
 217               };
 218               
 219               static DWORD tls_index = TLS_OUT_OF_INDEXES; /* TLS index for per-thread data */
 220               static INT num_startup;          /* reference counter */
 221               static FARPROC blocking_hook = WSA_DefaultBlockingHook;
 222               
 223               /* function prototypes */
 224               static struct WS_hostent *WS_dup_he(const struct hostent* p_he);
 225               static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe);
 226               static struct WS_servent *WS_dup_se(const struct servent* p_se);
 227               
 228               int WSAIOCTL_GetInterfaceCount(void);
 229               int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
 230               
 231               UINT wsaErrno(void);
 232               UINT wsaHerrno(int errnr);
 233               
 234               #define MAP_OPTION(opt) { WS_##opt, opt }
 235 cs130_tom 1.1 
 236               static const int ws_sock_map[][2] =
 237               {
 238                   MAP_OPTION( SO_DEBUG ),
 239                   MAP_OPTION( SO_REUSEADDR ),
 240                   MAP_OPTION( SO_KEEPALIVE ),
 241                   MAP_OPTION( SO_DONTROUTE ),
 242                   MAP_OPTION( SO_BROADCAST ),
 243                   MAP_OPTION( SO_LINGER ),
 244                   MAP_OPTION( SO_OOBINLINE ),
 245                   MAP_OPTION( SO_SNDBUF ),
 246                   MAP_OPTION( SO_RCVBUF ),
 247                   MAP_OPTION( SO_ERROR ),
 248                   MAP_OPTION( SO_TYPE ),
 249               #ifdef SO_RCVTIMEO
 250                   MAP_OPTION( SO_RCVTIMEO ),
 251               #endif
 252               #ifdef SO_SNDTIMEO
 253                   MAP_OPTION( SO_SNDTIMEO ),
 254               #endif
 255                   { 0, 0 }
 256 cs130_tom 1.1 };
 257               
 258               static const int ws_tcp_map[][2] =
 259               {
 260               #ifdef TCP_NODELAY
 261                   MAP_OPTION( TCP_NODELAY ),
 262               #endif
 263                   { 0, 0 }
 264               };
 265               
 266               static const int ws_ip_map[][2] =
 267               {
 268                   MAP_OPTION( IP_MULTICAST_IF ),
 269                   MAP_OPTION( IP_MULTICAST_TTL ),
 270                   MAP_OPTION( IP_MULTICAST_LOOP ),
 271                   MAP_OPTION( IP_ADD_MEMBERSHIP ),
 272                   MAP_OPTION( IP_DROP_MEMBERSHIP ),
 273                   MAP_OPTION( IP_OPTIONS ),
 274               #ifdef IP_HDRINCL
 275                   MAP_OPTION( IP_HDRINCL ),
 276               #endif
 277 cs130_tom 1.1     MAP_OPTION( IP_TOS ),
 278                   MAP_OPTION( IP_TTL ),
 279                   { 0, 0 }
 280               };
 281               
 282               inline static DWORD NtStatusToWSAError( const DWORD status )
 283               {
 284                   /* We only need to cover the status codes set by server async request handling */
 285                   DWORD wserr;
 286                   switch ( status )
 287                   {
 288                   case STATUS_SUCCESS:              wserr = 0;                     break;
 289                   case STATUS_PENDING:              wserr = WSA_IO_PENDING;        break;
 290                   case STATUS_INVALID_HANDLE:       wserr = WSAENOTSOCK;           break;  /* WSAEBADF ? */
 291                   case STATUS_INVALID_PARAMETER:    wserr = WSAEINVAL;             break;
 292                   case STATUS_PIPE_DISCONNECTED:    wserr = WSAESHUTDOWN;          break;
 293                   case STATUS_CANCELLED:            wserr = WSA_OPERATION_ABORTED; break;
 294                   case STATUS_TIMEOUT:              wserr = WSAETIMEDOUT;          break;
 295                   case STATUS_NO_MEMORY:            wserr = WSAEFAULT;             break;
 296                   default:
 297                       if ( status >= WSABASEERR && status <= WSABASEERR+1004 )
 298 cs130_tom 1.1             /* It is not a NT status code but a winsock error */
 299                           wserr = status;
 300                       else
 301                       {
 302                           wserr = RtlNtStatusToDosError( status );
 303                           FIXME( "Status code %08lx converted to DOS error code %lx\n", status, wserr );
 304                       }
 305                   }
 306                   return wserr;
 307               }
 308               
 309               /* set last error code from NT status without mapping WSA errors */
 310               inline static unsigned int set_error( unsigned int err )
 311               {
 312                   if (err)
 313                   {
 314                       err = NtStatusToWSAError( err );
 315                       SetLastError( err );
 316                   }
 317                   return err;
 318               }
 319 cs130_tom 1.1 
 320               inline static int get_sock_fd( SOCKET s, DWORD access, int *flags )
 321               {
 322                   int fd;
 323                   if (set_error( wine_server_handle_to_fd( SOCKET2HANDLE(s), access, &fd, flags ) ))
 324                       return -1;
 325                   return fd;
 326               }
 327               
 328               inline static void release_sock_fd( SOCKET s, int fd )
 329               {
 330                   wine_server_release_fd( SOCKET2HANDLE(s), fd );
 331               }
 332               
 333               static void _enable_event( HANDLE s, unsigned int event,
 334                                          unsigned int sstate, unsigned int cstate )
 335               {
 336                   SERVER_START_REQ( enable_socket_event )
 337                   {
 338                       req->handle = s;
 339                       req->mask   = event;
 340 cs130_tom 1.1         req->sstate = sstate;
 341                       req->cstate = cstate;
 342                       wine_server_call( req );
 343                   }
 344                   SERVER_END_REQ;
 345               }
 346               
 347               static int _is_blocking(SOCKET s)
 348               {
 349                   int ret;
 350                   SERVER_START_REQ( get_socket_event )
 351                   {
 352                       req->handle  = SOCKET2HANDLE(s);
 353                       req->service = FALSE;
 354                       req->c_event = 0;
 355                       wine_server_call( req );
 356                       ret = (reply->state & FD_WINE_NONBLOCKING) == 0;
 357                   }
 358                   SERVER_END_REQ;
 359                   return ret;
 360               }
 361 cs130_tom 1.1 
 362               static unsigned int _get_sock_mask(SOCKET s)
 363               {
 364                   unsigned int ret;
 365                   SERVER_START_REQ( get_socket_event )
 366                   {
 367                       req->handle  = SOCKET2HANDLE(s);
 368                       req->service = FALSE;
 369                       req->c_event = 0;
 370                       wine_server_call( req );
 371                       ret = reply->mask;
 372                   }
 373                   SERVER_END_REQ;
 374                   return ret;
 375               }
 376               
 377               static void _sync_sock_state(SOCKET s)
 378               {
 379                   /* do a dummy wineserver request in order to let
 380                      the wineserver run through its select loop once */
 381                   (void)_is_blocking(s);
 382 cs130_tom 1.1 }
 383               
 384               static int _get_sock_error(SOCKET s, unsigned int bit)
 385               {
 386                   int events[FD_MAX_EVENTS];
 387               
 388                   SERVER_START_REQ( get_socket_event )
 389                   {
 390                       req->handle  = SOCKET2HANDLE(s);
 391                       req->service = FALSE;
 392                       req->c_event = 0;
 393                       wine_server_set_reply( req, events, sizeof(events) );
 394                       wine_server_call( req );
 395                   }
 396                   SERVER_END_REQ;
 397                   return events[bit];
 398               }
 399               
 400               static struct per_thread_data *get_per_thread_data(void)
 401               {
 402                   struct per_thread_data * ptb = TlsGetValue( tls_index );
 403 cs130_tom 1.1     /* lazy initialization */
 404                   if (!ptb)
 405                   {
 406                       ptb = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ptb) );
 407                       TlsSetValue( tls_index, ptb );
 408 cs130_tom 1.2 
 409                       ptb->se_len = 0;
 410 cs130_tom 1.1     }
 411                   return ptb;
 412               }
 413               
 414               static void free_per_thread_data(void)
 415               {
 416                   struct per_thread_data * ptb = TlsGetValue( tls_index );
 417               
 418                   if (!ptb) return;
 419               
 420                   /* delete scratch buffers */
 421                   HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
 422                   HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
 423                   HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
 424                   ptb->he_buffer = NULL;
 425                   ptb->se_buffer = NULL;
 426                   ptb->pe_buffer = NULL;
 427               
 428                   HeapFree( GetProcessHeap(), 0, ptb );
 429               }
 430               
 431 cs130_tom 1.1 /***********************************************************************
 432                *		DllMain (WS2_32.init)
 433                */
 434               BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
 435               {
 436                   TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);
 437                   switch (fdwReason) {
 438                   case DLL_PROCESS_ATTACH:
 439                       tls_index = TlsAlloc();
 440                       break;
 441                   case DLL_PROCESS_DETACH:
 442                       free_per_thread_data();
 443                       TlsFree( tls_index );
 444                       num_startup = 0;
 445                       break;
 446                   case DLL_THREAD_DETACH:
 447                       free_per_thread_data();
 448                       break;
 449                   }
 450                   return TRUE;
 451               }
 452 cs130_tom 1.1 
 453               /***********************************************************************
 454                *          convert_sockopt()
 455                *
 456                * Converts socket flags from Windows format.
 457                * Return 1 if converted, 0 if not (error).
 458                */
 459               static int convert_sockopt(INT *level, INT *optname)
 460               {
 461                 int i;
 462                 switch (*level)
 463                 {
 464                    case WS_SOL_SOCKET:
 465                       *level = SOL_SOCKET;
 466                       for(i=0; ws_sock_map[i][0]; i++)
 467                       {
 468                           if( ws_sock_map[i][0] == *optname )
 469                           {
 470                               *optname = ws_sock_map[i][1];
 471                               return 1;
 472                           }
 473 cs130_tom 1.1         }
 474                       FIXME("Unknown SOL_SOCKET optname 0x%x\n", *optname);
 475                       break;
 476                    case WS_IPPROTO_TCP:
 477                       *level = IPPROTO_TCP;
 478                       for(i=0; ws_tcp_map[i][0]; i++)
 479                       {
 480                           if ( ws_tcp_map[i][0] == *optname )
 481                           {
 482                               *optname = ws_tcp_map[i][1];
 483                               return 1;
 484                           }
 485                       }
 486                       FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname);
 487               	break;
 488                    case WS_IPPROTO_IP:
 489                       *level = IPPROTO_IP;
 490                       for(i=0; ws_ip_map[i][0]; i++)
 491                       {
 492                           if (ws_ip_map[i][0] == *optname )
 493                           {
 494 cs130_tom 1.1                 *optname = ws_ip_map[i][1];
 495                               return 1;
 496                           }
 497                       }
 498               	FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname);
 499               	break;
 500                    default: FIXME("Unimplemented or unknown socket level\n");
 501                 }
 502                 return 0;
 503               }
 504               
 505               static inline BOOL is_timeout_option( int optname )
 506               {
 507               #ifdef SO_RCVTIMEO
 508                   if (optname == SO_RCVTIMEO) return TRUE;
 509               #endif
 510               #ifdef SO_SNDTIMEO
 511                   if (optname == SO_SNDTIMEO) return TRUE;
 512               #endif
 513                   return FALSE;
 514               }
 515 cs130_tom 1.1 
 516               /* ----------------------------------- Per-thread info (or per-process?) */
 517               
 518               static char *strdup_lower(const char *str)
 519               {
 520                   int i;
 521                   char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
 522               
 523                   if (ret)
 524                   {
 525                       for (i = 0; str[i]; i++) ret[i] = tolower(str[i]);
 526                       ret[i] = 0;
 527                   }
 528                   else SetLastError(WSAENOBUFS);
 529                   return ret;
 530               }
 531               
 532               static fd_set* fd_set_import( fd_set* fds, const WS_fd_set* wsfds, int access, int* highfd, int lfd[] )
 533               {
 534                   /* translate Winsock fd set into local fd set */
 535                   if( wsfds )
 536 cs130_tom 1.1     {
 537                       unsigned int i;
 538               
 539                       FD_ZERO(fds);
 540                       for( i = 0; i < wsfds->fd_count; i++ )
 541                       {
 542                           int s = wsfds->fd_array[i];
 543                           int fd = get_sock_fd( s, access, NULL );
 544                           if (fd != -1)
 545                           {
 546                               lfd[ i ] = fd;
 547                               if( fd > *highfd ) *highfd = fd;
 548                               FD_SET(fd, fds);
 549                           }
 550                           else lfd[ i ] = -1;
 551                       }
 552                       return fds;
 553                   }
 554                   return NULL;
 555               }
 556               
 557 cs130_tom 1.1 inline static int sock_error_p(int s)
 558               {
 559                   unsigned int optval, optlen;
 560               
 561                   optlen = sizeof(optval);
 562                   getsockopt(s, SOL_SOCKET, SO_ERROR, (void *) &optval, &optlen);
 563                   if (optval) WARN("\t[%i] error: %d\n", s, optval);
 564                   return optval != 0;
 565               }
 566               
 567               static int fd_set_export( const fd_set* fds, fd_set* exceptfds, WS_fd_set* wsfds, int lfd[] )
 568               {
 569                   int num_err = 0;
 570               
 571                   /* translate local fd set into Winsock fd set, adding
 572                    * errors to exceptfds (only if app requested it) */
 573               
 574                   if( wsfds )
 575                   {
 576               	int i, j, count = wsfds->fd_count;
 577               
 578 cs130_tom 1.1 	for( i = 0, j = 0; i < count; i++ )
 579               	{
 580                           int fd = lfd[i];
 581                           SOCKET s = wsfds->fd_array[i];
 582                           if (fd == -1) continue;
 583                           if( FD_ISSET(fd, fds) )
 584                           {
 585                               if ( exceptfds && sock_error_p(fd) )
 586                               {
 587                                   FD_SET(fd, exceptfds);
 588                                   num_err++;
 589                               }
 590                               else wsfds->fd_array[j++] = s;
 591                           }
 592                           release_sock_fd( s, fd );
 593               	}
 594               	wsfds->fd_count = j;
 595                   }
 596                   return num_err;
 597               }
 598               
 599 cs130_tom 1.1 static void fd_set_unimport( WS_fd_set* wsfds, int lfd[] )
 600               {
 601                   if ( wsfds )
 602                   {
 603               	unsigned int i;
 604               
 605               	for ( i = 0; i < wsfds->fd_count; i++ )
 606               	    if ( lfd[i] >= 0 ) release_sock_fd( wsfds->fd_array[i], lfd[i] );
 607                       wsfds->fd_count = 0;
 608                   }
 609               }
 610               
 611               /* Utility: get the SO_RCVTIMEO or SO_SNDTIMEO socket option
 612                * from an fd and return the value converted to milli seconds
 613                * or -1 if there is an infinite time out */
 614               static inline int get_rcvsnd_timeo( int fd, int optname)
 615               {
 616                 struct timeval tv;
 617                 int len = sizeof(tv);
 618                 int ret = getsockopt(fd, SOL_SOCKET, optname, &tv, &len);
 619                 if( ret >= 0)
 620 cs130_tom 1.1       ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
 621                 if( ret <= 0 ) /* tv == {0,0} means infinite time out */
 622                     return -1;
 623                 return ret;
 624               }
 625               
 626               /* macro wrappers for portability */
 627               #ifdef SO_RCVTIMEO
 628               #define GET_RCVTIMEO(fd) get_rcvsnd_timeo( (fd), SO_RCVTIMEO)
 629               #else
 630               #define GET_RCVTIMEO(fd) (-1)
 631               #endif
 632               
 633               #ifdef SO_SNDTIMEO
 634               #define GET_SNDTIMEO(fd) get_rcvsnd_timeo( (fd), SO_SNDTIMEO)
 635               #else
 636               #define GET_SNDTIMEO(fd) (-1)
 637               #endif
 638               
 639               /* utility: given an fd, will block until one of the events occurs */
 640               static inline int do_block( int fd, int events, int timeout )
 641 cs130_tom 1.1 {
 642                 struct pollfd pfd;
 643                 int ret;
 644               
 645                 pfd.fd = fd;
 646                 pfd.events = events;
 647               
 648                 while ((ret = poll(&pfd, 1, timeout)) < 0)
 649                 {
 650                     if (errno != EINTR)
 651                         return -1;
 652                 }
 653                 if( ret == 0 )
 654                     return 0;
 655                 return pfd.revents;
 656               }
 657               
 658               
 659               /* ----------------------------------- API -----
 660                *
 661                * Init / cleanup / error checking.
 662 cs130_tom 1.1  */
 663               
 664               /***********************************************************************
 665                *      WSAStartup		(WS2_32.115)
 666                */
 667               int WINAPI WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
 668               {
 669                   TRACE("verReq=%x\n", wVersionRequested);
 670               
 671                   if (LOBYTE(wVersionRequested) < 1)
 672                       return WSAVERNOTSUPPORTED;
 673               
 674                   if (!lpWSAData) return WSAEINVAL;
 675               
 676                   num_startup++;
 677               
 678                   /* that's the whole of the negotiation for now */
 679                   lpWSAData->wVersion = wVersionRequested;
 680                   /* return winsock information */
 681                   lpWSAData->wHighVersion = 0x0202;
 682                   strcpy(lpWSAData->szDescription, "WinSock 2.0" );
 683 cs130_tom 1.1     strcpy(lpWSAData->szSystemStatus, "Running" );
 684                   lpWSAData->iMaxSockets = WS_MAX_SOCKETS_PER_PROCESS;
 685                   lpWSAData->iMaxUdpDg = WS_MAX_UDP_DATAGRAM;
 686                   /* don't do anything with lpWSAData->lpVendorInfo */
 687                   /* (some apps don't allocate the space for this field) */
 688               
 689                   TRACE("succeeded\n");
 690                   return 0;
 691               }
 692               
 693               
 694               /***********************************************************************
 695                *      WSACleanup			(WS2_32.116)
 696                */
 697               INT WINAPI WSACleanup(void)
 698               {
 699                   if (num_startup)
 700                       return 0;
 701                   SetLastError(WSANOTINITIALISED);
 702                   return SOCKET_ERROR;
 703               }
 704 cs130_tom 1.1 
 705               
 706               /***********************************************************************
 707                *      WSAGetLastError		(WINSOCK.111)
 708                *      WSAGetLastError		(WS2_32.111)
 709                */
 710               INT WINAPI WSAGetLastError(void)
 711               {
 712               	return GetLastError();
 713               }
 714               
 715               /***********************************************************************
 716                *      WSASetLastError		(WS2_32.112)
 717                */
 718               void WINAPI WSASetLastError(INT iError) {
 719                   SetLastError(iError);
 720               }
 721               
 722               static struct WS_hostent *check_buffer_he(int size)
 723               {
 724                   struct per_thread_data * ptb = get_per_thread_data();
 725 cs130_tom 1.1     if (ptb->he_buffer)
 726                   {
 727                       if (ptb->he_len >= size ) return ptb->he_buffer;
 728                       HeapFree( GetProcessHeap(), 0, ptb->he_buffer );
 729                   }
 730                   ptb->he_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->he_len = size) );
 731                   if (!ptb->he_buffer) SetLastError(WSAENOBUFS);
 732                   return ptb->he_buffer;
 733               }
 734               
 735 cs130_tom 1.2 static char *check_buffer_se(int size)
 736 cs130_tom 1.1 {
 737                   struct per_thread_data * ptb = get_per_thread_data();
 738 cs130_tom 1.2     if (ptb->se_len > 0)
 739 cs130_tom 1.1     {
 740                       if (ptb->se_len >= size ) return ptb->se_buffer;
 741                       HeapFree( GetProcessHeap(), 0, ptb->se_buffer );
 742                   }
 743                   ptb->se_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->se_len = size) );
 744                   if (!ptb->se_buffer) SetLastError(WSAENOBUFS);
 745                   return ptb->se_buffer;
 746               }
 747               
 748               static struct WS_protoent *check_buffer_pe(int size)
 749               {
 750                   struct per_thread_data * ptb = get_per_thread_data();
 751                   if (ptb->pe_buffer)
 752                   {
 753                       if (ptb->pe_len >= size ) return ptb->pe_buffer;
 754                       HeapFree( GetProcessHeap(), 0, ptb->pe_buffer );
 755                   }
 756                   ptb->pe_buffer = HeapAlloc( GetProcessHeap(), 0, (ptb->pe_len = size) );
 757                   if (!ptb->pe_buffer) SetLastError(WSAENOBUFS);
 758                   return ptb->pe_buffer;
 759               }
 760 cs130_tom 1.1 
 761               /* ----------------------------------- i/o APIs */
 762               
 763               #ifdef HAVE_IPX
 764               #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET || (pf)== WS_AF_IPX)
 765               #else
 766               #define SUPPORTED_PF(pf) ((pf)==WS_AF_INET)
 767               #endif
 768               
 769               
 770               /**********************************************************************/
 771               
 772               /* Returns the converted address if successful, NULL if it was too small to
 773                * start with. Note that the returned pointer may be the original pointer
 774                * if no conversion is necessary.
 775                */
 776               static const struct sockaddr* ws_sockaddr_ws2u(const struct WS_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen)
 777               {
 778                   switch (wsaddr->sa_family)
 779                   {
 780               #ifdef HAVE_IPX
 781 cs130_tom 1.1     case WS_AF_IPX:
 782                       {
 783                           struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
 784                           struct sockaddr_ipx* uipx;
 785               
 786                           if (wsaddrlen<sizeof(struct WS_sockaddr_ipx))
 787                               return NULL;
 788               
 789                           *uaddrlen=sizeof(struct sockaddr_ipx);
 790                           uipx=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *uaddrlen);
 791                           uipx->sipx_family=AF_IPX;
 792                           uipx->sipx_port=wsipx->sa_socket;
 793                           /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node
 794                            * in one go
 795                            */
 796                           memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node));
 797               #ifdef IPX_FRAME_NONE
 798                           uipx->sipx_type=IPX_FRAME_NONE;
 799               #endif
 800                           return (const struct sockaddr*)uipx;
 801                       }
 802 cs130_tom 1.1 #endif
 803               
 804                   default:
 805                       if (wsaddrlen<sizeof(struct WS_sockaddr))
 806                           return NULL;
 807               
 808                       /* No conversion needed, just return the original address */
 809                       *uaddrlen=wsaddrlen;
 810                       return (const struct sockaddr*)wsaddr;
 811                   }
 812               }
 813               
 814               /* Allocates a Unix sockaddr structure to receive the data */
 815               inline struct sockaddr* ws_sockaddr_alloc(const struct WS_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen)
 816               {
 817                   if (wsaddr==NULL)
 818                   {
 819                     ERR( "WINE shouldn't pass a NULL wsaddr! Attempting to continue\n" );
 820               
 821                     /* This is not strictly the right thing to do. Hope it works however */
 822                     *uaddrlen=0;
 823 cs130_tom 1.1 
 824                     return NULL;
 825                   }
 826               
 827                   if (*wsaddrlen==0)
 828                       *uaddrlen=0;
 829                   else
 830                       *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen);
 831               
 832                   return HeapAlloc(GetProcessHeap(), 0, *uaddrlen);
 833               }
 834               
 835               /* Returns 0 if successful, -1 if the buffer is too small */
 836               static int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, struct WS_sockaddr* wsaddr, int* wsaddrlen)
 837               {
 838                   int res;
 839               
 840                   switch(uaddr->sa_family)
 841                   {
 842               #ifdef HAVE_IPX
 843                   case AF_IPX:
 844 cs130_tom 1.1         {
 845                           struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr;
 846                           struct WS_sockaddr_ipx* wsipx=(struct WS_sockaddr_ipx*)wsaddr;
 847               
 848                           res=-1;
 849                           switch (*wsaddrlen) /* how much can we copy? */
 850                           {
 851                           default:
 852                               res=0; /* enough */
 853                               *wsaddrlen=uaddrlen;
 854                               wsipx->sa_socket=uipx->sipx_port;
 855                               /* fall through */
 856                           case 13:
 857                           case 12:
 858                               memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum));
 859                               /* fall through */
 860                           case 11:
 861                           case 10:
 862                           case 9:
 863                           case 8:
 864                           case 7:
 865 cs130_tom 1.1             case 6:
 866                               memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum));
 867                               /* fall through */
 868                           case 5:
 869                           case 4:
 870                           case 3:
 871                           case 2:
 872                               wsipx->sa_family=WS_AF_IPX;
 873                               /* fall through */
 874                           case 1:
 875                           case 0:
 876                               /* way too small */
 877                               break;
 878                           }
 879                       }
 880                       break;
 881               #endif
 882               
 883                   default:
 884                       /* No conversion needed */
 885                       memcpy(wsaddr,uaddr,*wsaddrlen);
 886 cs130_tom 1.1         if (*wsaddrlen<uaddrlen) {
 887                           res=-1;
 888                       } else {
 889                           *wsaddrlen=uaddrlen;
 890                           res=0;
 891                       }
 892                   }
 893                   return res;
 894               }
 895               
 896               /* to be called to free the memory allocated by ws_sockaddr_ws2u or
 897                * ws_sockaddr_alloc
 898                */
 899               inline void ws_sockaddr_free(const struct sockaddr* uaddr, const struct WS_sockaddr* wsaddr)
 900               {
 901                   if (uaddr!=(const struct sockaddr*)wsaddr)
 902                       HeapFree(GetProcessHeap(), 0, (void *)uaddr);
 903               }
 904               
 905               /**************************************************************************
 906                * Functions for handling overlapped I/O
 907 cs130_tom 1.1  **************************************************************************/
 908               
 909               static void CALLBACK ws2_async_terminate(ws2_async* as, IO_STATUS_BLOCK* iosb)
 910               {
 911                   TRACE( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, iosb );
 912               
 913                   wine_server_release_fd( as->hSocket, as->fd );
 914                   if ( as->event != INVALID_HANDLE_VALUE )
 915                       NtSetEvent( as->event, NULL );
 916               
 917                   if (as->completion_func)
 918                       as->completion_func( NtStatusToWSAError (iosb->u.Status),
 919                                            iosb->Information, as->user_overlapped, as->flags );
 920                   if ( !as->user_overlapped )
 921                   {
 922               #if 0
 923                       /* FIXME: I don't think this is really used */
 924                       if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
 925                           WSACloseEvent( as->overlapped->hEvent  );
 926               #endif
 927                       HeapFree( GetProcessHeap(), 0, iosb );
 928 cs130_tom 1.1     }
 929               
 930                   HeapFree( GetProcessHeap(), 0, as->iovec );
 931                   HeapFree( GetProcessHeap(), 0, as );
 932               }
 933               
 934               /***********************************************************************
 935                *              WS2_make_async          (INTERNAL)
 936                */
 937               
 938               static void WINAPI WS2_async_recv(void*, IO_STATUS_BLOCK*, ULONG);
 939               static void WINAPI WS2_async_send(void*, IO_STATUS_BLOCK*, ULONG);
 940               static void WINAPI WS2_async_shutdown( void*, IO_STATUS_BLOCK*, ULONG);
 941               
 942               inline static struct ws2_async*
 943               WS2_make_async(SOCKET s, int fd, enum ws2_mode mode, struct iovec *iovec, DWORD dwBufferCount,
 944                              LPDWORD lpFlags, struct WS_sockaddr *addr,
 945                              LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
 946                              LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
 947                              IO_STATUS_BLOCK **piosb)
 948               {
 949 cs130_tom 1.1     struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof( ws2_async ) );
 950               
 951                   TRACE( "wsa %p\n", wsa );
 952               
 953                   if (!wsa)
 954                       return NULL;
 955               
 956                   wsa->hSocket = (HANDLE) s;
 957                   wsa->mode = mode;
 958                   switch (mode)
 959                   {
 960                   case ws2m_read:
 961                   case ws2m_sd_read:
 962                       wsa->flags = *lpFlags;
 963                       wsa->addrlen.ptr = addrlen;
 964                       break;
 965                   case ws2m_write:
 966                   case ws2m_sd_write:
 967                       wsa->flags = 0;
 968                       wsa->addrlen.val = *addrlen;
 969                       break;
 970 cs130_tom 1.1     default:
 971                       ERR("Invalid async mode: %d\n", mode);
 972                   }
 973                   wsa->user_overlapped = lpOverlapped;
 974                   wsa->completion_func = lpCompletionRoutine;
 975                   wsa->iovec = iovec;
 976                   wsa->n_iovecs = dwBufferCount;
 977                   wsa->addr = addr;
 978                   wsa->fd = fd;
 979                   wsa->event = INVALID_HANDLE_VALUE;
 980               
 981                   if ( lpOverlapped )
 982                   {
 983                       *piosb = (IO_STATUS_BLOCK*)lpOverlapped;
 984                       if (!lpCompletionRoutine)
 985                       {
 986                           wsa->event = lpOverlapped->hEvent;
 987                           NtResetEvent(wsa->event, NULL);
 988                       }
 989                   }
 990                   else if (!(*piosb = HeapAlloc( GetProcessHeap(), 0, sizeof(IO_STATUS_BLOCK))))
 991 cs130_tom 1.1         goto error;
 992               
 993                   (*piosb)->Information = 0;
 994                   (*piosb)->u.Status = STATUS_PENDING;
 995                   TRACE( "wsa %p, h %p, ev %p, fd %d, iosb %p, uov %p, cfunc %p\n",
 996                          wsa, wsa->hSocket, wsa->event, wsa->fd,
 997                          *piosb, wsa->user_overlapped, wsa->completion_func );
 998               
 999                   return wsa;
1000               
1001               error:
1002                   TRACE("Error\n");
1003                   HeapFree( GetProcessHeap(), 0, wsa );
1004                   return NULL;
1005               }
1006               
1007               static ULONG ws2_queue_async(struct ws2_async* wsa, IO_STATUS_BLOCK* iosb)
1008               {
1009                   PIO_APC_ROUTINE     apc;
1010                   int                 type;
1011                   NTSTATUS            status;
1012 cs130_tom 1.1 
1013                   switch (wsa->mode)
1014                   {
1015                   case ws2m_read:     apc = WS2_async_recv;     type = ASYNC_TYPE_READ;  break;
1016                   case ws2m_write:    apc = WS2_async_send;     type = ASYNC_TYPE_WRITE; break;
1017                   case ws2m_sd_read:  apc = WS2_async_shutdown; type = ASYNC_TYPE_READ;  break;
1018                   case ws2m_sd_write: apc = WS2_async_shutdown; type = ASYNC_TYPE_WRITE; break;
1019                   default: FIXME("Unknown internal mode (%d)\n", wsa->mode); return STATUS_INVALID_PARAMETER;
1020                   }
1021               
1022                   SERVER_START_REQ( register_async )
1023                   {
1024                       req->handle = wsa->hSocket;
1025                       req->io_apc = apc;
1026                       req->io_sb = iosb;
1027                       req->io_user = wsa;
1028                       req->type = type;
1029                       req->count = iosb->Information;
1030                       status = wine_server_call( req );
1031                   }
1032                   SERVER_END_REQ;
1033 cs130_tom 1.1 
1034                   if ( status ) iosb->u.Status = status;
1035                   if ( iosb->u.Status != STATUS_PENDING )
1036                   {
1037                       (apc)( wsa, iosb, iosb->u.Status );
1038                       return iosb->u.Status;
1039                   }
1040                   NtCurrentTeb()->num_async_io++;
1041                   return STATUS_SUCCESS;
1042               }
1043               
1044               /***********************************************************************
1045                *              WS2_recv                (INTERNAL)
1046                *
1047                * Workhorse for both synchronous and asynchronous recv() operations.
1048                */
1049               static int WS2_recv( int fd, struct iovec* iov, int count,
1050                                    struct WS_sockaddr *lpFrom, LPINT lpFromlen,
1051                                     LPDWORD lpFlags )
1052               {
1053                   struct msghdr hdr;
1054 cs130_tom 1.1     int n;
1055                   TRACE( "fd %d, iovec %p, count %d addr %s, len %p, flags %lx\n",
1056                          fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags);
1057               
1058                   hdr.msg_name = NULL;
1059               
1060                   if ( lpFrom )
1061                   {
1062                       hdr.msg_namelen = *lpFromlen;
1063                       hdr.msg_name = ws_sockaddr_alloc( lpFrom, lpFromlen, &hdr.msg_namelen );
1064                       if ( !hdr.msg_name )
1065                       {
1066                           WSASetLastError( WSAEFAULT );
1067                           n = -1;
1068                           goto out;
1069                       }
1070                   }
1071                   else
1072                       hdr.msg_namelen = 0;
1073               
1074                   hdr.msg_iov = iov;
1075 cs130_tom 1.1     hdr.msg_iovlen = count;
1076               #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1077                   hdr.msg_accrights = NULL;
1078                   hdr.msg_accrightslen = 0;
1079               #else
1080                   hdr.msg_control = NULL;
1081                   hdr.msg_controllen = 0;
1082                   hdr.msg_flags = 0;
1083               #endif
1084               
1085                   if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 )
1086                   {
1087                       TRACE( "recvmsg error %d\n", errno);
1088                       goto out;
1089                   }
1090               
1091                   if ( lpFrom &&
1092                        ws_sockaddr_u2ws( hdr.msg_name, hdr.msg_namelen,
1093                                          lpFrom, lpFromlen ) != 0 )
1094                   {
1095                       /* The from buffer was too small, but we read the data
1096 cs130_tom 1.1          * anyway. Is that really bad?
1097                        */
1098                       WSASetLastError( WSAEFAULT );
1099                       WARN( "Address buffer too small\n" );
1100                   }
1101               
1102               out:
1103               
1104                   ws_sockaddr_free( hdr.msg_name, lpFrom );
1105                   TRACE("-> %d\n", n);
1106                   return n;
1107               }
1108               
1109               /***********************************************************************
1110                *              WS2_async_recv          (INTERNAL)
1111                *
1112                * Handler for overlapped recv() operations.
1113                */
1114               static void WINAPI WS2_async_recv( void* ovp, IO_STATUS_BLOCK* iosb, ULONG status)
1115               {
1116                   ws2_async* wsa = (ws2_async*) ovp;
1117 cs130_tom 1.1     int result, err;
1118               
1119                   TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1120               
1121                   switch (status)
1122                   {
1123                   case STATUS_ALERTED:
1124                       result = WS2_recv( wsa->fd, wsa->iovec, wsa->n_iovecs,
1125                                          wsa->addr, wsa->addrlen.ptr, &wsa->flags );
1126                       if (result >= 0)
1127                       {
1128                           iosb->u.Status = STATUS_SUCCESS;
1129                           iosb->Information = result;
1130                           TRACE( "received %d bytes\n", result );
1131                           _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1132                       }
1133                       else
1134                       {
1135                           err = wsaErrno();
1136                           if ( err == WSAEINTR || err == WSAEWOULDBLOCK )  /* errno: EINTR / EAGAIN */
1137                           {
1138 cs130_tom 1.1                 iosb->u.Status = STATUS_PENDING;
1139                               _enable_event( wsa->hSocket, FD_READ, 0, 0 );
1140                               TRACE( "still pending\n" );
1141                           }
1142                           else
1143                           {
1144                               iosb->u.Status = err; /* FIXME: is this correct ???? */
1145                               TRACE( "Error: %x\n", err );
1146                           }
1147                       }
1148                       if (iosb->u.Status == STATUS_PENDING)
1149                           ws2_queue_async(wsa, iosb);
1150                       else
1151                           ws2_async_terminate(wsa, iosb);
1152                       break;
1153                   default:
1154                       FIXME( "status: %ld\n", status );
1155                       iosb->u.Status = status;
1156                       ws2_async_terminate(wsa, iosb);
1157                       return;
1158                   }
1159 cs130_tom 1.1 }
1160               
1161               /***********************************************************************
1162                *              WS2_send                (INTERNAL)
1163                *
1164                * Workhorse for both synchronous and asynchronous send() operations.
1165                */
1166               static int WS2_send( int fd, struct iovec* iov, int count,
1167                                    const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
1168               {
1169                   struct msghdr hdr;
1170                   int n = -1;
1171                   TRACE( "fd %d, iovec %p, count %d addr %s, len %d, flags %lx\n",
1172                          fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags);
1173               
1174                   hdr.msg_name = NULL;
1175               
1176                   if ( to )
1177                   {
1178                       hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u( to, tolen, &hdr.msg_namelen );
1179                       if ( !hdr.msg_name )
1180 cs130_tom 1.1         {
1181                           WSASetLastError( WSAEFAULT );
1182                           goto out;
1183                       }
1184               
1185               #ifdef HAVE_IPX
1186                       if(to->sa_family == WS_AF_IPX)
1187                       {
1188               #ifdef SOL_IPX
1189                           struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
1190                           int val=0;
1191                           int len=sizeof(int);
1192               
1193                           /* The packet type is stored at the ipx socket level; At least the linux kernel seems
1194                            *  to do something with it in case hdr.msg_name is NULL. Nonetheless can we use it to store
1195                            *  the packet type and then we can retrieve it using getsockopt. After that we can set the
1196                            *  ipx type in the sockaddr_opx structure with the stored value.
1197                            */
1198                           if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1)
1199                           {
1200                               TRACE("ptype: %d (fd:%d)\n", val, fd);
1201 cs130_tom 1.1                 uipx->sipx_type = val;
1202                           }
1203               #endif
1204                       }
1205               #endif
1206               
1207                   }
1208                   else
1209                       hdr.msg_namelen = 0;
1210               
1211                   hdr.msg_iov = iov;
1212                   hdr.msg_iovlen = count;
1213               #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
1214                   hdr.msg_accrights = NULL;
1215                   hdr.msg_accrightslen = 0;
1216               #else
1217                   hdr.msg_control = NULL;
1218                   hdr.msg_controllen = 0;
1219                   hdr.msg_flags = 0;
1220               #endif
1221               
1222 cs130_tom 1.1     n = sendmsg(fd, &hdr, dwFlags);
1223               
1224               out:
1225                   ws_sockaddr_free( hdr.msg_name, to );
1226                   return n;
1227               }
1228               
1229               /***********************************************************************
1230                *              WS2_async_send          (INTERNAL)
1231                *
1232                * Handler for overlapped send() operations.
1233                */
1234               static void WINAPI WS2_async_send(void* as, IO_STATUS_BLOCK* iosb, ULONG status)
1235               {
1236                   ws2_async* wsa = (ws2_async*) as;
1237                   int result;
1238               
1239                   TRACE( "(%p %p %lx)\n", wsa, iosb, status );
1240               
1241                   switch (status)
1242                   {
1243 cs130_tom 1.1     case STATUS_ALERTED:
1244                       if (iosb->u.Status != STATUS_PENDING) FIXME("wrong %08lx\n", iosb->u.Status);
1245                       /* check to see if the data is ready (non-blocking) */
1246                       result = WS2_send( wsa->fd, wsa->iovec, wsa->n_iovecs,
1247                                          wsa->addr, wsa->addrlen.val, wsa->flags );
1248               
1249                       if (result >= 0)
1250                       {
1251                           iosb->u.Status = STATUS_SUCCESS;
1252                           iosb->Information = result;
1253                           TRACE( "sent %d bytes\n", result );
1254                           _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1255                       }
1256                       else
1257                       {
1258                           int err = wsaErrno();
1259                           if ( err == WSAEINTR )
1260                           {
1261                               iosb->u.Status = STATUS_PENDING;
1262                               _enable_event( wsa->hSocket, FD_WRITE, 0, 0 );
1263                               TRACE( "still pending\n" );
1264 cs130_tom 1.1             }
1265                           else
1266                           {
1267                               /* We set the status to a winsock error code and check for that
1268                                  later in NtStatusToWSAError () */
1269                               iosb->u.Status = err;
1270                               TRACE( "Error: %x\n", err );
1271                           }
1272                       }
1273                       if (iosb->u.Status == STATUS_PENDING)
1274                           ws2_queue_async(wsa, iosb);
1275                       else
1276                           ws2_async_terminate(wsa, iosb);
1277                       break;
1278                   default:
1279                       FIXME( "status: %ld\n", status );
1280                       iosb->u.Status = status;
1281                       ws2_async_terminate(wsa, iosb);
1282                       return;
1283                   }
1284               
1285 cs130_tom 1.1 }
1286               
1287               /***********************************************************************
1288                *              WS2_async_shutdown      (INTERNAL)
1289                *
1290                * Handler for shutdown() operations on overlapped sockets.
1291                */
1292               static void WINAPI WS2_async_shutdown( void* as, PIO_STATUS_BLOCK iosb, ULONG status )
1293               {
1294                   ws2_async* wsa = (ws2_async*) as;
1295                   int err = 1;
1296               
1297                   TRACE( "async %p %d\n", wsa, wsa->mode );
1298                   switch (status)
1299                   {
1300                   case STATUS_ALERTED:
1301                       switch ( wsa->mode )
1302                       {
1303                       case ws2m_sd_read:   err = shutdown( wsa->fd, 0 );  break;
1304                       case ws2m_sd_write:  err = shutdown( wsa->fd, 1 );  break;
1305                       default: ERR("invalid mode: %d\n", wsa->mode );
1306 cs130_tom 1.1         }
1307                       iosb->u.Status = err ? wsaErrno() : STATUS_SUCCESS;
1308                       if (iosb->u.Status == STATUS_PENDING)
1309                           ws2_queue_async(wsa, iosb);
1310                       else
1311                           ws2_async_terminate(wsa, iosb);
1312                       break;
1313                   default:
1314                       iosb->u.Status = status;
1315                       ws2_async_terminate(wsa, iosb);
1316                       break;
1317                   }
1318               
1319               }
1320               
1321               /***********************************************************************
1322                *  WS2_register_async_shutdown         (INTERNAL)
1323                *
1324                * Helper function for WS_shutdown() on overlapped sockets.
1325                */
1326               static int WS2_register_async_shutdown( SOCKET s, int fd, enum ws2_mode mode )
1327 cs130_tom 1.1 {
1328                   struct ws2_async *wsa;
1329                   int ret, err = WSAEFAULT;
1330                   DWORD dwflags = 0;
1331                   int len = 0;
1332                   LPWSAOVERLAPPED ovl = HeapAlloc(GetProcessHeap(), 0, sizeof( WSAOVERLAPPED ));
1333                   IO_STATUS_BLOCK *iosb;
1334               
1335                   TRACE("s %d fd %d mode %d\n", s, fd, mode);
1336                   if (!ovl)
1337                       goto out;
1338               
1339                   ovl->hEvent = WSACreateEvent();
1340                   if ( ovl->hEvent == WSA_INVALID_EVENT )
1341                       goto out_free;
1342               
1343                   wsa = WS2_make_async( s, fd, mode, NULL, 0,
1344                                         &dwflags, NULL, &len, ovl, NULL, &iosb );
1345                   if ( !wsa )
1346                       goto out_close;
1347               
1348 cs130_tom 1.1     /* Hack: this will cause ws2_async_cleanup() to free the overlapped structure */
1349                   wsa->user_overlapped = NULL;
1350                   if ( (ret = ws2_queue_async( wsa, iosb )) )
1351                   {
1352                       err = NtStatusToWSAError( ret );
1353                       goto out;
1354                   }
1355                   /* Try immediate completion */
1356                   while ( WaitForSingleObjectEx( ovl->hEvent, 0, TRUE ) == STATUS_USER_APC );
1357                   return 0;
1358               
1359               out_close:
1360                   WSACloseEvent( ovl->hEvent );
1361               out_free:
1362                   HeapFree( GetProcessHeap(), 0, iosb );
1363                   HeapFree( GetProcessHeap(), 0, ovl );
1364               out:
1365                   return err;
1366               }
1367               
1368               /***********************************************************************
1369 cs130_tom 1.1  *		accept		(WS2_32.1)
1370                */
1371               SOCKET WINAPI WS_accept(SOCKET s, struct WS_sockaddr *addr,
1372                                                int *addrlen32)
1373               {
1374                   SOCKET as;
1375               
1376                   TRACE("socket %04x\n", s );
1377                   if (_is_blocking(s))
1378                   {
1379                       int fd = get_sock_fd( s, GENERIC_READ, NULL );
1380                       if (fd == -1) return INVALID_SOCKET;
1381                       /* block here */
1382                       do_block(fd, POLLIN, -1);
1383                       _sync_sock_state(s); /* let wineserver notice connection */
1384                       release_sock_fd( s, fd );
1385                       /* retrieve any error codes from it */
1386                       SetLastError(_get_sock_error(s, FD_ACCEPT_BIT));
1387                       /* FIXME: care about the error? */
1388                   }
1389                   SERVER_START_REQ( accept_socket )
1390 cs130_tom 1.1     {
1391                       req->lhandle = SOCKET2HANDLE(s);
1392                       req->access  = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
1393                       req->inherit = TRUE;
1394                       set_error( wine_server_call( req ) );
1395                       as = HANDLE2SOCKET( reply->handle );
1396                   }
1397                   SERVER_END_REQ;
1398                   if (as)
1399                   {
1400                       if (addr) WS_getpeername(as, addr, addrlen32);
1401                       return as;
1402                   }
1403                   return INVALID_SOCKET;
1404               }
1405               
1406               /***********************************************************************
1407                *		bind			(WS2_32.2)
1408                */
1409               int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
1410               {
1411 cs130_tom 1.1     int fd = get_sock_fd( s, 0, NULL );
1412                   int res = SOCKET_ERROR;
1413               
1414                   TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1415               
1416                   if (fd != -1)
1417                   {
1418                       if (!name || !SUPPORTED_PF(name->sa_family))
1419                       {
1420                           SetLastError(WSAEAFNOSUPPORT);
1421                       }
1422                       else
1423                       {
1424                           const struct sockaddr* uaddr;
1425                           int uaddrlen;
1426               
1427                           uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1428                           if (uaddr == NULL)
1429                           {
1430                               SetLastError(WSAEFAULT);
1431                           }
1432 cs130_tom 1.1             else
1433                           {
1434                               if (bind(fd, uaddr, uaddrlen) < 0)
1435                               {
1436                                   int loc_errno = errno;
1437                                   WARN("\tfailure - errno = %i\n", errno);
1438                                   errno = loc_errno;
1439                                   switch (errno)
1440                                   {
1441                                   case EBADF:
1442                                       SetLastError(WSAENOTSOCK);
1443                                       break;
1444                                   case EADDRNOTAVAIL:
1445                                       SetLastError(WSAEINVAL);
1446                                       break;
1447                                   default:
1448                                       SetLastError(wsaErrno());
1449                                       break;
1450                                   }
1451                               }
1452                               else
1453 cs130_tom 1.1                 {
1454                                   res=0; /* success */
1455                               }
1456                               ws_sockaddr_free(uaddr,name);
1457                           }
1458                       }
1459                       release_sock_fd( s, fd );
1460                   }
1461                   return res;
1462               }
1463               
1464               /***********************************************************************
1465                *		closesocket		(WS2_32.3)
1466                */
1467               int WINAPI WS_closesocket(SOCKET s)
1468               {
1469                   TRACE("socket %04x\n", s);
1470                   if (CloseHandle(SOCKET2HANDLE(s))) return 0;
1471                   return SOCKET_ERROR;
1472               }
1473               
1474 cs130_tom 1.1 /***********************************************************************
1475                *		connect		(WS2_32.4)
1476                */
1477               int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
1478               {
1479                   int fd = get_sock_fd( s, GENERIC_READ, NULL );
1480               
1481                   TRACE("socket %04x, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
1482               
1483                   if (fd != -1)
1484                   {
1485                       const struct sockaddr* uaddr;
1486                       int uaddrlen;
1487               
1488                       uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen);
1489                       if (uaddr == NULL)
1490                       {
1491                           SetLastError(WSAEFAULT);
1492                       }
1493                       else
1494                       {
1495 cs130_tom 1.1             int rc;
1496               
1497                           rc=connect(fd, uaddr, uaddrlen);
1498                           ws_sockaddr_free(uaddr,name);
1499                           if (rc == 0)
1500                               goto connect_success;
1501                       }
1502               
1503                       if (errno == EINPROGRESS)
1504                       {
1505                           /* tell wineserver that a connection is in progress */
1506                           _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1507                                         FD_CONNECT|FD_READ|FD_WRITE,
1508                                         FD_WINE_CONNECTED|FD_WINE_LISTENING);
1509                           if (_is_blocking(s))
1510                           {
1511                               int result;
1512                               /* block here */
1513                               do_block(fd, POLLIN | POLLOUT, -1);
1514                               _sync_sock_state(s); /* let wineserver notice connection */
1515                               /* retrieve any error codes from it */
1516 cs130_tom 1.1                 result = _get_sock_error(s, FD_CONNECT_BIT);
1517                               if (result)
1518                                   SetLastError(result);
1519                               else
1520                               {
1521                                   goto connect_success;
1522                               }
1523                           }
1524                           else
1525                           {
1526                               SetLastError(WSAEWOULDBLOCK);
1527                           }
1528                       }
1529                       else
1530                       {
1531                           SetLastError(wsaErrno());
1532                       }
1533                       release_sock_fd( s, fd );
1534                   }
1535                   return SOCKET_ERROR;
1536               
1537 cs130_tom 1.1 connect_success:
1538                   release_sock_fd( s, fd );
1539                   _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
1540                                 FD_WINE_CONNECTED|FD_READ|FD_WRITE,
1541                                 FD_CONNECT|FD_WINE_LISTENING);
1542                   return 0;
1543               }
1544               
1545               /***********************************************************************
1546                *              WSAConnect             (WS2_32.30)
1547                */
1548               int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
1549                                      LPWSABUF lpCallerData, LPWSABUF lpCalleeData,
1550                                      LPQOS lpSQOS, LPQOS lpGQOS )
1551               {
1552                   if ( lpCallerData || lpCalleeData || lpSQOS || lpGQOS )
1553                       FIXME("unsupported parameters!\n");
1554                   return WS_connect( s, name, namelen );
1555               }
1556               
1557               
1558 cs130_tom 1.1 /***********************************************************************
1559                *		getpeername		(WS2_32.5)
1560                */
1561               int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
1562               {
1563                   int fd;
1564                   int res;
1565               
1566                   TRACE("socket: %04x, ptr %p, len %08x\n", s, name, *namelen);
1567               
1568                   /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1569                   if( (name == NULL) || (namelen == NULL) )
1570                   {
1571                       SetLastError( WSAEFAULT );
1572                       return SOCKET_ERROR;
1573                   }
1574               
1575                   fd = get_sock_fd( s, 0, NULL );
1576                   res = SOCKET_ERROR;
1577               
1578                   if (fd != -1)
1579 cs130_tom 1.1     {
1580                       struct sockaddr* uaddr;
1581                       int uaddrlen;
1582               
1583                       uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1584                       if (getpeername(fd, uaddr, &uaddrlen) != 0)
1585                       {
1586                           SetLastError(wsaErrno());
1587                       }
1588                       else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1589                       {
1590                           /* The buffer was too small */
1591                           SetLastError(WSAEFAULT);
1592                       }
1593                       else
1594                       {
1595                           res=0;
1596                       }
1597                       ws_sockaddr_free(uaddr,name);
1598                       release_sock_fd( s, fd );
1599                   }
1600 cs130_tom 1.1     return res;
1601               }
1602               
1603               /***********************************************************************
1604                *		getsockname		(WS2_32.6)
1605                */
1606               int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
1607               {
1608                   int fd;
1609                   int res;
1610               
1611                   TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen);
1612               
1613                   /* Check if what we've received is valid. Should we use IsBadReadPtr? */
1614                   if( (name == NULL) || (namelen == NULL) )
1615                   {
1616                       SetLastError( WSAEFAULT );
1617                       return SOCKET_ERROR;
1618                   }
1619               
1620                   fd = get_sock_fd( s, 0, NULL );
1621 cs130_tom 1.1     res = SOCKET_ERROR;
1622               
1623                   if (fd != -1)
1624                   {
1625                       struct sockaddr* uaddr;
1626                       int uaddrlen;
1627               
1628                       uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen);
1629                       if (getsockname(fd, uaddr, &uaddrlen) != 0)
1630                       {
1631                           SetLastError(wsaErrno());
1632                       }
1633                       else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0)
1634                       {
1635                           /* The buffer was too small */
1636                           SetLastError(WSAEFAULT);
1637                       }
1638                       else
1639                       {
1640                           res=0;
1641                       }
1642 cs130_tom 1.1         ws_sockaddr_free(uaddr,name);
1643                       release_sock_fd( s, fd );
1644                   }
1645                   return res;
1646               }
1647               
1648               /***********************************************************************
1649                *		getsockopt		(WS2_32.7)
1650                */
1651               INT WINAPI WS_getsockopt(SOCKET s, INT level,
1652                                                 INT optname, char *optval, INT *optlen)
1653               {
1654                   int fd;
1655                   INT ret = 0;
1656               
1657                   TRACE("socket: %04x, level 0x%x, name 0x%x, ptr %8x, len %d\n", s, level,
1658                         (int) optname, (int) optval, (int) *optlen);
1659                   /* SO_OPENTYPE does not require a valid socket handle. */
1660                   if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
1661                   {
1662                       if (!optlen || *optlen < sizeof(int) || !optval)
1663 cs130_tom 1.1         {
1664                           SetLastError(WSAEFAULT);
1665                           return SOCKET_ERROR;
1666                       }
1667                       *(int *)optval = get_per_thread_data()->opentype;
1668                       *optlen = sizeof(int);
1669                       TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
1670                       return 0;
1671                   }
1672               
1673               #ifdef HAVE_IPX
1674                   if(level == NSPROTO_IPX)
1675                   {
1676                   	struct WS_sockaddr_ipx addr;
1677               	IPX_ADDRESS_DATA *data;
1678               	int namelen;
1679               	switch(optname)
1680               	{
1681               	    case IPX_PTYPE:
1682               		fd = get_sock_fd( s, 0, NULL );
1683               #ifdef SOL_IPX
1684 cs130_tom 1.1 		if(getsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
1685               		{
1686               		    return SOCKET_ERROR;
1687               		}
1688               #else
1689                               {
1690                                   struct ipx val;
1691                                   socklen_t len=sizeof(struct ipx);
1692               
1693                                   if(getsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, &len) == -1 )
1694                                       return SOCKET_ERROR;
1695                                   *optval = (int)val.ipx_pt;
1696                               }
1697               #endif
1698               		TRACE("ptype: %d (fd: %d)\n", *(int*)optval, fd);
1699                   		release_sock_fd( s, fd );
1700               	
1701               		return 0;
1702               	    case IPX_ADDRESS:
1703               		/*
1704               		*  On a Win2000 system with one network card there are usually three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
1705 cs130_tom 1.1 		*  Using this call you can then retrieve info about this all. In case of Linux it is a bit different. Usually you have
1706               		*  only "one" device active and further it is not possible to query things like the linkspeed.
1707               		*/
1708               		FIXME("IPX_ADDRESS\n");
1709               		namelen = sizeof(struct WS_sockaddr);
1710               		memset(&addr, 0, sizeof(struct WS_sockaddr));
1711               		WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
1712               
1713               		data = (IPX_ADDRESS_DATA*)optval;
1714                               memcpy(data->nodenum,&addr.sa_nodenum,sizeof(data->nodenum));
1715                               memcpy(data->netnum,&addr.sa_netnum,sizeof(data->netnum));
1716               		data->adapternum = 0;
1717               		data->wan = FALSE; /* We are not on a wan for now .. */
1718               		data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
1719               		data->maxpkt = 1467; /* This value is the default one, at least on Win2k/WinXP */
1720               		data->linkspeed = 100000; /* Set the line speed in 100bit/s to 10 Mbit; note 1MB = 1000kB in this case */
1721               		return 0;	
1722               	    case IPX_MAX_ADAPTER_NUM:
1723               		FIXME("IPX_MAX_ADAPTER_NUM\n");
1724                   		*(int*)optval = 1; /* As noted under IPX_ADDRESS we have just one card. */
1725               
1726 cs130_tom 1.1 		return 0;
1727               	    default:
1728               		FIXME("IPX optname:%x\n", optname);
1729               		return SOCKET_ERROR;
1730               	}
1731                   }
1732               #endif
1733               
1734                   if( (fd = get_sock_fd( s, 0, NULL )) == -1)
1735                       return SOCKET_ERROR;
1736               
1737                   if (!convert_sockopt(&level, &optname)) {
1738                       SetLastError(WSAENOPROTOOPT);	/* Unknown option */
1739                       ret = SOCKET_ERROR;
1740                   } else {
1741                       struct timeval tv;
1742                       struct linger lingval;
1743                       INT len, *plen = optlen;
1744                       char *pval = optval;
1745                       if(level == SOL_SOCKET && is_timeout_option(optname)) {
1746                           len = sizeof(tv);
1747 cs130_tom 1.1             plen = &len;
1748                           pval = (char *) &tv;
1749                       } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1750                           len = sizeof(lingval);
1751                           plen = &len;
1752                           pval = (char *) &lingval;
1753                       }
1754                       if (getsockopt(fd, (int) level, optname, pval, plen) != 0 ) {
1755                           SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
1756                           ret = SOCKET_ERROR;
1757                       } else if(level == SOL_SOCKET && is_timeout_option(optname)) {
1758                           if( *optlen >= sizeof(INT) ) {
1759                               *optlen = sizeof(INT);
1760                               *(INT*)optval = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1761                           } else {
1762                               SetLastError(WSAEFAULT);
1763                               ret = SOCKET_ERROR;
1764                           }
1765                       } else if( level == SOL_SOCKET && optname == SO_LINGER) {
1766                           if( *optlen >=  sizeof( LINGER) ) {
1767                               (( LINGER *) optval)->l_onoff = lingval.l_onoff;
1768 cs130_tom 1.1                 (( LINGER *) optval)->l_linger = lingval.l_linger;
1769                           } else {
1770                               SetLastError(WSAEFAULT);
1771                               ret = SOCKET_ERROR;
1772                           }
1773                       }
1774                   }
1775                   release_sock_fd( s, fd );
1776                   return ret;
1777               }
1778               
1779               
1780               /***********************************************************************
1781                *		htonl			(WINSOCK.8)
1782                *		htonl			(WS2_32.8)
1783                */
1784               u_long WINAPI WS_htonl(u_long hostlong)
1785               {
1786                   return htonl(hostlong);
1787               }
1788               
1789 cs130_tom 1.1 
1790               /***********************************************************************
1791                *		htons			(WINSOCK.9)
1792                *		htons			(WS2_32.9)
1793                */
1794               u_short WINAPI WS_htons(u_short hostshort)
1795               {
1796                   return htons(hostshort);
1797               }
1798               
1799               /***********************************************************************
1800                *		WSAHtonl		(WS2_32.46)
1801                *  From MSDN decription of error codes, this function should also
1802                *  check if WinSock has been initialized and the socket is a valid
1803                *  socket. But why? This function only translates a host byte order
1804                *  u_long into a network byte order u_long...
1805                */
1806               int WINAPI WSAHtonl(SOCKET s, u_long hostlong, u_long *lpnetlong)
1807               {
1808                   if (lpnetlong)
1809                   {
1810 cs130_tom 1.1         *lpnetlong = htonl(hostlong);
1811                       return 0;
1812                   }
1813                   WSASetLastError(WSAEFAULT);
1814                   return SOCKET_ERROR;
1815               }
1816               
1817               /***********************************************************************
1818                *		WSAHtons		(WS2_32.47)
1819                *  From MSDN decription of error codes, this function should also
1820                *  check if WinSock has been initialized and the socket is a valid
1821                *  socket. But why? This function only translates a host byte order
1822                *  u_short into a network byte order u_short...
1823                */
1824               int WINAPI WSAHtons(SOCKET s, u_short hostshort, u_short *lpnetshort)
1825               {
1826               
1827                   if (lpnetshort)
1828                   {
1829                       *lpnetshort = htons(hostshort);
1830                       return 0;
1831 cs130_tom 1.1     }
1832                   WSASetLastError(WSAEFAULT);
1833                   return SOCKET_ERROR;
1834               }
1835               
1836               
1837               /***********************************************************************
1838                *		inet_addr		(WINSOCK.10)
1839                *		inet_addr		(WS2_32.11)
1840                */
1841               u_long WINAPI WS_inet_addr(const char *cp)
1842               {
1843                   return inet_addr(cp);
1844               }
1845               
1846               
1847               /***********************************************************************
1848                *		ntohl			(WINSOCK.14)
1849                *		ntohl			(WS2_32.14)
1850                */
1851               u_long WINAPI WS_ntohl(u_long netlong)
1852 cs130_tom 1.1 {
1853                   return ntohl(netlong);
1854               }
1855               
1856               
1857               /***********************************************************************
1858                *		ntohs			(WINSOCK.15)
1859                *		ntohs			(WS2_32.15)
1860                */
1861               u_short WINAPI WS_ntohs(u_short netshort)
1862               {
1863                   return ntohs(netshort);
1864               }
1865               
1866               
1867               /***********************************************************************
1868                *		inet_ntoa		(WS2_32.12)
1869                */
1870               char* WINAPI WS_inet_ntoa(struct WS_in_addr in)
1871               {
1872                 /* use "buffer for dummies" here because some applications have a
1873 cs130_tom 1.1    * propensity to decode addresses in ws_hostent structure without
1874                  * saving them first...
1875                  */
1876                   static char dbuffer[16]; /* Yes, 16: 4*3 digits + 3 '.' + 1 '\0' */
1877               
1878                   char* s = inet_ntoa(*((struct in_addr*)&in));
1879                   if( s )
1880                   {
1881                       strcpy(dbuffer, s);
1882                       return dbuffer;
1883                   }
1884                   SetLastError(wsaErrno());
1885                   return NULL;
1886               }
1887               
1888               /**********************************************************************
1889                *              WSAIoctl                (WS2_32.50)
1890                *
1891                *
1892                *   FIXME:  Only SIO_GET_INTERFACE_LIST option implemented.
1893                */
1894 cs130_tom 1.1 INT WINAPI WSAIoctl(SOCKET s,
1895                                   DWORD   dwIoControlCode,
1896                                   LPVOID  lpvInBuffer,
1897                                   DWORD   cbInBuffer,
1898                                   LPVOID  lpbOutBuffer,
1899                                   DWORD   cbOutBuffer,
1900                                   LPDWORD lpcbBytesReturned,
1901                                   LPWSAOVERLAPPED lpOverlapped,
1902                                   LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
1903               {
1904                  int fd = get_sock_fd( s, 0, NULL );
1905               
1906                  if (fd == -1) return SOCKET_ERROR;
1907               
1908                  TRACE("%d, 0x%08lx, %p, %ld, %p, %ld, %p, %p, %p\n", 
1909                      s, dwIoControlCode, lpvInBuffer, cbInBuffer, lpbOutBuffer,
1910                      cbOutBuffer, lpcbBytesReturned, lpOverlapped, lpCompletionRoutine);
1911               
1912                  switch( dwIoControlCode )
1913                  {
1914                  case SIO_GET_INTERFACE_LIST:
1915 cs130_tom 1.1        {
1916                          INTERFACE_INFO* intArray = (INTERFACE_INFO*)lpbOutBuffer;
1917                          DWORD size, numInt, apiReturn;
1918               
1919                          TRACE("-> SIO_GET_INTERFACE_LIST request\n");
1920               
1921                          if (!lpbOutBuffer)
1922                          {
1923                              release_sock_fd( s, fd );
1924                              WSASetLastError(WSAEFAULT);
1925                              return SOCKET_ERROR;
1926                          }
1927                          if (!lpcbBytesReturned)
1928                          {
1929                              release_sock_fd( s, fd );
1930                              WSASetLastError(WSAEFAULT);
1931                              return SOCKET_ERROR;
1932                          }
1933               
1934                          apiReturn = GetAdaptersInfo(NULL, &size);
1935                          if (apiReturn == ERROR_NO_DATA)
1936 cs130_tom 1.1            {
1937                              numInt = 0;
1938                          }
1939                          else if (apiReturn == ERROR_BUFFER_OVERFLOW)
1940                          {
1941                              PIP_ADAPTER_INFO table = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(),0,size);
1942               
1943                              if (table)
1944                              {
1945                                 if (GetAdaptersInfo(table, &size) == NO_ERROR)
1946                                 {
1947                                    PIP_ADAPTER_INFO ptr;
1948               
1949                                    if (size*sizeof(INTERFACE_INFO)/sizeof(IP_ADAPTER_INFO) > cbOutBuffer)
1950                                    {
1951                                       WARN("Buffer too small = %lu, cbOutBuffer = %lu\n", size, cbOutBuffer);
1952                                       HeapFree(GetProcessHeap(),0,table);
1953                                       release_sock_fd( s, fd );
1954                                       WSASetLastError(WSAEFAULT);
1955                                       return SOCKET_ERROR;
1956                                    }
1957 cs130_tom 1.1                      for (ptr = table, numInt = 0; ptr;
1958                                     ptr = ptr->Next, intArray++, numInt++)
1959                                    {
1960                                       unsigned int addr, mask, bcast;
1961                                       struct ifreq ifInfo;
1962               
1963                                       /* Socket Status Flags */
1964                                       strncpy(ifInfo.ifr_name, ptr->AdapterName, IFNAMSIZ);
1965                                       ifInfo.ifr_name[IFNAMSIZ-1] = '\0';
1966                                       if (ioctl(fd, SIOCGIFFLAGS, &ifInfo) < 0)
1967                                       {
1968                                          ERR("Error obtaining status flags for socket!\n");
1969                                          HeapFree(GetProcessHeap(),0,table);
1970                                          release_sock_fd( s, fd );
1971                                          WSASetLastError(WSAEINVAL);
1972                                          return SOCKET_ERROR;
1973                                       }
1974                                       else
1975                                       {
1976                                          /* set flags; the values of IFF_* are not the same
1977                                             under Linux and Windows, therefore must generate
1978 cs130_tom 1.1                               new flags */
1979                                          intArray->iiFlags = 0;
1980                                          if (ifInfo.ifr_flags & IFF_BROADCAST)
1981                                             intArray->iiFlags |= WS_IFF_BROADCAST;
1982               #ifdef IFF_POINTOPOINT
1983                                          if (ifInfo.ifr_flags & IFF_POINTOPOINT)
1984                                             intArray->iiFlags |= WS_IFF_POINTTOPOINT;
1985               #endif
1986                                          if (ifInfo.ifr_flags & IFF_LOOPBACK)
1987                                             intArray->iiFlags |= WS_IFF_LOOPBACK;
1988                                          if (ifInfo.ifr_flags & IFF_UP)
1989                                             intArray->iiFlags |= WS_IFF_UP;
1990                                          if (ifInfo.ifr_flags & IFF_MULTICAST)
1991                                             intArray->iiFlags |= WS_IFF_MULTICAST;
1992                                       }
1993               
1994                                       addr = inet_addr(ptr->IpAddressList.IpAddress.String);
1995                                       mask = inet_addr(ptr->IpAddressList.IpMask.String);
1996                                       bcast = addr | (addr & !mask);
1997                                       intArray->iiAddress.AddressIn.sin_family = AF_INET;
1998                                       intArray->iiAddress.AddressIn.sin_port = 0;
1999 cs130_tom 1.1                         intArray->iiAddress.AddressIn.sin_addr.WS_s_addr =
2000                                        addr;
2001                                       intArray->iiNetmask.AddressIn.sin_family = AF_INET;
2002                                       intArray->iiNetmask.AddressIn.sin_port = 0;
2003                                       intArray->iiNetmask.AddressIn.sin_addr.WS_s_addr =
2004                                        mask;
2005                                       intArray->iiBroadcastAddress.AddressIn.sin_family =
2006                                        AF_INET;
2007                                       intArray->iiBroadcastAddress.AddressIn.sin_port = 0;
2008                                       intArray->iiBroadcastAddress.AddressIn.sin_addr.
2009                                        WS_s_addr = bcast;
2010                                    }
2011                                 }
2012                                 else
2013                                 {
2014                                    ERR("Unable to get interface table!\n");
2015                                    release_sock_fd( s, fd );
2016                                    HeapFree(GetProcessHeap(),0,table);
2017                                    WSASetLastError(WSAEINVAL);
2018                                    return SOCKET_ERROR;
2019                                 }
2020 cs130_tom 1.1                   HeapFree(GetProcessHeap(),0,table);
2021                              }
2022                              else
2023                              {
2024                                 release_sock_fd( s, fd );
2025                                 WSASetLastError(WSAEINVAL);
2026                                 return SOCKET_ERROR;
2027                              }
2028                          }
2029                          else
2030                          {
2031                              ERR("Unable to get interface table!\n");
2032                              release_sock_fd( s, fd );
2033                              WSASetLastError(WSAEINVAL);
2034                              return SOCKET_ERROR;
2035                          }
2036                          /* Calculate the size of the array being returned */
2037                          *lpcbBytesReturned = sizeof(INTERFACE_INFO) * numInt;
2038                          break;
2039                      }
2040               
2041 cs130_tom 1.1    case SIO_ADDRESS_LIST_CHANGE:
2042                      FIXME("-> SIO_ADDRESS_LIST_CHANGE request: stub\n");
2043                      /* FIXME: error and return code depend on whether socket was created
2044                       * with WSA_FLAG_OVERLAPPED, but there is no easy way to get this */
2045                      break;
2046               
2047                  default:
2048                      WARN("\tunsupported WS_IOCTL cmd (%08lx)\n", dwIoControlCode);
2049                      release_sock_fd( s, fd );
2050                      WSASetLastError(WSAEOPNOTSUPP);
2051                      return SOCKET_ERROR;
2052                  }
2053               
2054                  /* Function executed with no errors */
2055                  release_sock_fd( s, fd );
2056                  return 0;
2057               }
2058               
2059               
2060               /***********************************************************************
2061                *		ioctlsocket		(WS2_32.10)
2062 cs130_tom 1.1  */
2063               int WINAPI WS_ioctlsocket(SOCKET s, long cmd, u_long *argp)
2064               {
2065                   int fd;
2066                   long newcmd  = cmd;
2067               
2068                   TRACE("socket %04x, cmd %08lx, ptr %p\n", s, cmd, argp);
2069               
2070                   switch( cmd )
2071                   {
2072                   case WS_FIONREAD:
2073                       newcmd=FIONREAD;
2074                       break;
2075               
2076                   case WS_FIONBIO:
2077                       if( _get_sock_mask(s) )
2078                       {
2079                           /* AsyncSelect()'ed sockets are always nonblocking */
2080                           if (*argp) return 0;
2081                           SetLastError(WSAEINVAL);
2082                           return SOCKET_ERROR;
2083 cs130_tom 1.1         }
2084                       fd = get_sock_fd( s, 0, NULL );
2085                       if (fd != -1)
2086                       {
2087                           int ret;
2088                           if (*argp)
2089                           {
2090                               _enable_event(SOCKET2HANDLE(s), 0, FD_WINE_NONBLOCKING, 0);
2091                               ret = fcntl( fd, F_SETFL, O_NONBLOCK );
2092                           }
2093                           else
2094                           {
2095                               _enable_event(SOCKET2HANDLE(s), 0, 0, FD_WINE_NONBLOCKING);
2096                               ret = fcntl( fd, F_SETFL, 0 );
2097                           }
2098                           release_sock_fd( s, fd );
2099                           if (!ret) return 0;
2100                           SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2101                       }
2102                       return SOCKET_ERROR;
2103               
2104 cs130_tom 1.1     case WS_SIOCATMARK:
2105                       newcmd=SIOCATMARK;
2106                       break;
2107               
2108                   case WS__IOW('f',125,u_long):
2109                       WARN("Warning: WS1.1 shouldn't be using async I/O\n");
2110                       SetLastError(WSAEINVAL);
2111                       return SOCKET_ERROR;
2112               
2113                   case SIOCGIFBRDADDR:
2114                   case SIOCGIFNETMASK:
2115                   case SIOCGIFADDR:
2116                       /* These don't need any special handling.  They are used by
2117                          WsControl, and are here to suppress an unnecessary warning. */
2118                       break;
2119               
2120                   default:
2121                       /* Netscape tries hard to use bogus ioctl 0x667e */
2122                       WARN("\tunknown WS_IOCTL cmd (%08lx)\n", cmd);
2123                       break;
2124                   }
2125 cs130_tom 1.1 
2126                   fd = get_sock_fd( s, 0, NULL );
2127                   if (fd != -1)
2128                   {
2129                       if( ioctl(fd, newcmd, (char*)argp ) == 0 )
2130                       {
2131                           release_sock_fd( s, fd );
2132                           return 0;
2133                       }
2134                       SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno());
2135                       release_sock_fd( s, fd );
2136                   }
2137                   return SOCKET_ERROR;
2138               }
2139               
2140               /***********************************************************************
2141                *		listen		(WS2_32.13)
2142                */
2143               int WINAPI WS_listen(SOCKET s, int backlog)
2144               {
2145                   int fd = get_sock_fd( s, GENERIC_READ, NULL );
2146 cs130_tom 1.1 
2147                   TRACE("socket %04x, backlog %d\n", s, backlog);
2148                   if (fd != -1)
2149                   {
2150               	if (listen(fd, backlog) == 0)
2151               	{
2152                           release_sock_fd( s, fd );
2153               	    _enable_event(SOCKET2HANDLE(s), FD_ACCEPT,
2154               			  FD_WINE_LISTENING,
2155               			  FD_CONNECT|FD_WINE_CONNECTED);
2156               	    return 0;
2157               	}
2158               	SetLastError(wsaErrno());
2159                       release_sock_fd( s, fd );
2160                   }
2161                   return SOCKET_ERROR;
2162               }
2163               
2164               /***********************************************************************
2165                *		recv			(WS2_32.16)
2166                */
2167 cs130_tom 1.1 int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
2168               {
2169                   DWORD n, dwFlags = flags;
2170                   WSABUF wsabuf;
2171               
2172                   wsabuf.len = len;
2173                   wsabuf.buf = buf;
2174               
2175                   if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
2176                       return SOCKET_ERROR;
2177                   else
2178                       return n;
2179               }
2180               
2181               /***********************************************************************
2182                *		recvfrom		(WS2_32.17)
2183                */
2184               int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
2185                                      struct WS_sockaddr *from, int *fromlen)
2186               {
2187                   DWORD n, dwFlags = flags;
2188 cs130_tom 1.1     WSABUF wsabuf;
2189               
2190                   wsabuf.len = len;
2191                   wsabuf.buf = buf;
2192               
2193                   if ( WSARecvFrom(s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
2194                       return SOCKET_ERROR;
2195                   else
2196                       return n;
2197               }
2198               
2199               /***********************************************************************
2200                *		select			(WS2_32.18)
2201                */
2202               int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
2203                                    WS_fd_set *ws_writefds, WS_fd_set *ws_exceptfds,
2204                                    const struct WS_timeval* ws_timeout)
2205               {
2206                   int         highfd = 0;
2207                   fd_set      readfds, writefds, exceptfds;
2208                   fd_set     *p_read, *p_write, *p_except;
2209 cs130_tom 1.1     int         readfd[FD_SETSIZE], writefd[FD_SETSIZE], exceptfd[FD_SETSIZE];
2210                   struct timeval timeout, *timeoutaddr = NULL;
2211               
2212                   TRACE("read %p, write %p, excp %p timeout %p\n",
2213                         ws_readfds, ws_writefds, ws_exceptfds, ws_timeout);
2214               
2215                   p_read = fd_set_import(&readfds, ws_readfds, GENERIC_READ, &highfd, readfd);
2216                   p_write = fd_set_import(&writefds, ws_writefds, GENERIC_WRITE, &highfd, writefd);
2217                   p_except = fd_set_import(&exceptfds, ws_exceptfds, 0, &highfd, exceptfd);
2218                   if (ws_timeout)
2219                   {
2220                       timeoutaddr = &timeout;
2221                       timeout.tv_sec=ws_timeout->tv_sec;
2222                       timeout.tv_usec=ws_timeout->tv_usec;
2223                   }
2224               
2225                   if( (highfd = select(highfd + 1, p_read, p_write, p_except, timeoutaddr)) > 0 )
2226                   {
2227                       fd_set_export(&readfds, p_except, ws_readfds, readfd);
2228                       fd_set_export(&writefds, p_except, ws_writefds, writefd);
2229               
2230 cs130_tom 1.1         if (p_except && ws_exceptfds)
2231                       {
2232                           unsigned int i, j;
2233               
2234                           for (i = j = 0; i < ws_exceptfds->fd_count; i++)
2235                           {
2236                               int fd = exceptfd[i];
2237                               SOCKET s = ws_exceptfds->fd_array[i];
2238                               if (fd == -1) continue;
2239                               if (FD_ISSET(fd, &exceptfds)) ws_exceptfds->fd_array[j++] = s;
2240                               release_sock_fd( s, fd );
2241                           }
2242                           ws_exceptfds->fd_count = j;
2243                       }
2244                       return highfd;
2245                   }
2246                   fd_set_unimport(ws_readfds, readfd);
2247                   fd_set_unimport(ws_writefds, writefd);
2248                   fd_set_unimport(ws_exceptfds, exceptfd);
2249               
2250                   if( highfd == 0 ) return 0;
2251 cs130_tom 1.1     SetLastError(wsaErrno());
2252                   return SOCKET_ERROR;
2253               }
2254               
2255               
2256               /***********************************************************************
2257                *		send			(WS2_32.19)
2258                */
2259               int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
2260               {
2261                   DWORD n;
2262                   WSABUF wsabuf;
2263               
2264                   wsabuf.len = len;
2265                   wsabuf.buf = (char*) buf;
2266               
2267                   if ( WSASendTo( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
2268                       return SOCKET_ERROR;
2269                   else
2270                       return n;
2271               }
2272 cs130_tom 1.1 
2273               /***********************************************************************
2274                *		WSASend			(WS2_32.72)
2275                */
2276               INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2277                                   LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2278                                   LPWSAOVERLAPPED lpOverlapped,
2279                                   LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2280               {
2281                   return WSASendTo( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
2282                                     NULL, 0, lpOverlapped, lpCompletionRoutine );
2283               }
2284               
2285               /***********************************************************************
2286                *              WSASendDisconnect       (WS2_32.73)
2287                */
2288               INT WINAPI WSASendDisconnect( SOCKET s, LPWSABUF lpBuffers )
2289               {
2290                   return WS_shutdown( s, SD_SEND );
2291               }
2292               
2293 cs130_tom 1.1 
2294               /***********************************************************************
2295                *		WSASendTo		(WS2_32.74)
2296                */
2297               INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
2298                                     LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
2299                                     const struct WS_sockaddr *to, int tolen,
2300                                     LPWSAOVERLAPPED lpOverlapped,
2301                                     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
2302               {
2303                   unsigned int i;
2304                   int n, fd, err = WSAENOTSOCK, flags, ret;
2305                   struct iovec* iovec;
2306                   struct ws2_async *wsa;
2307                   IO_STATUS_BLOCK* iosb;
2308               
2309                   TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
2310                         s, lpBuffers, dwBufferCount, dwFlags,
2311                         to, tolen, lpOverlapped, lpCompletionRoutine);
2312               
2313                   fd = get_sock_fd( s, GENERIC_WRITE, &flags );
2314 cs130_tom 1.1     TRACE( "fd=%d, flags=%x\n", fd, flags );
2315               
2316                   if ( fd == -1 ) return SOCKET_ERROR;
2317               
2318                   if (flags & FD_FLAG_SEND_SHUTDOWN)
2319                   {
2320                       WSASetLastError( WSAESHUTDOWN );
2321                       goto err_close;
2322                   }
2323               
2324                   if ( !lpNumberOfBytesSent )
2325                   {
2326                       err = WSAEFAULT;
2327                       goto err_close;
2328                   }
2329               
2330                   iovec = HeapAlloc(GetProcessHeap(), 0, dwBufferCount * sizeof(struct iovec) );
2331               
2332                   if ( !iovec )
2333                   {
2334                       err = WSAEFAULT;
2335 cs130_tom 1.1         goto err_close;
2336                   }
2337               
2338                   for ( i = 0; i < dwBufferCount; i++ )
2339                   {
2340                       iovec[i].iov_base = lpBuffers[i].buf;
2341                       iovec[i].iov_len  = lpBuffers[i].len;
2342                   }
2343               
2344                   if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
2345                   {
2346                       wsa = WS2_make_async( s, fd, ws2m_write, iovec, dwBufferCount,
2347                                             &dwFlags, (struct WS_sockaddr*) to, &tolen,
2348                                             lpOverlapped, lpCompletionRoutine, &iosb );
2349                       if ( !wsa )
2350                       {
2351                           err = WSAEFAULT;
2352                           goto err_free;
2353                       }
2354               
2355                       if ( ( ret = ws2_queue_async( wsa, iosb ) ) )
2356 cs130_tom 1.1         {
2357                           err = NtStatusToWSAError( ret );
2358               
2359                           if ( !lpOverlapped )
2360                               HeapFree( GetProcessHeap(), 0, iosb );
2361                           HeapFree( GetProcessHeap(), 0, wsa );
2362                           goto err_free;
2363                       }
2364               
2365                       /* Try immediate completion */
2366                       if ( lpOverlapped )
2367                       {
2368                           if  ( WSAGetOverlappedResult( s, lpOverlapped,
2369                                                         lpNumberOfBytesSent, FALSE, &dwFlags) )
2370                               return 0;
2371               
2372                           if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
2373                               goto error;
2374                       }
2375               
2376                       WSASetLastError( WSA_IO_PENDING );
2377 cs130_tom 1.1         return SOCKET_ERROR;
2378                   }
2379               
2380                   if (_is_blocking(s))
2381                   {
2382                       /* FIXME: exceptfds? */
2383                       int timeout = GET_SNDTIMEO(fd);
2384                       if( !do_block(fd, POLLOUT, timeout)) {
2385                           err = WSAETIMEDOUT;
2386                           goto err_free; /* msdn says a timeout in send is fatal */
2387                       }
2388                   }
2389               
2390                   n = WS2_send( fd, iovec, dwBufferCount, to, tolen, dwFlags );
2391                   if ( n == -1 )
2392                   {
2393                       err = wsaErrno();
2394                       if ( err == WSAEWOULDBLOCK )
2395                           _enable_event(SOCKET2HANDLE(s), FD_WRITE, 0, 0);
2396                       goto err_free;
2397                   }
2398 cs130_tom 1.1 
2399                   TRACE(" -> %i bytes\n", n);
2400                   *lpNumberOfBytesSent = n;
2401               
2402                   HeapFree( GetProcessHeap(), 0, iovec );
2403                   release_sock_fd( s, fd );
2404                   return 0;
2405               
2406               err_free:
2407                   HeapFree( GetProcessHeap(), 0, iovec );
2408               
2409               err_close:
2410                   release_sock_fd( s, fd );
2411               
2412               error:
2413                   WARN(" -> ERROR %d\n", err);
2414                   WSASetLastError(err);
2415                   return SOCKET_ERROR;
2416               }
2417               
2418               /***********************************************************************
2419 cs130_tom 1.1  *		sendto		(WS2_32.20)
2420                */
2421               int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
2422                                             const struct WS_sockaddr *to, int tolen)
2423               {
2424                   DWORD n;
2425                   WSABUF wsabuf;
2426               
2427                   wsabuf.len = len;
2428                   wsabuf.buf = (char*) buf;
2429               
2430                   if ( WSASendTo(s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
2431                       return SOCKET_ERROR;
2432                   else
2433                       return n;
2434               }
2435               
2436               /***********************************************************************
2437                *		setsockopt		(WS2_32.21)
2438                */
2439               int WINAPI WS_setsockopt(SOCKET s, int level, int optname,
2440 cs130_tom 1.1                                   const char *optval, int optlen)
2441               {
2442                   int fd;
2443                   int woptval;
2444                   struct linger linger;
2445                   struct timeval tval;
2446               
2447                   TRACE("socket: %04x, level %d, name %d, ptr %p, len %d\n",
2448                         s, level, optname, optval, optlen);
2449               
2450                   /* SO_OPENTYPE does not require a valid socket handle. */
2451                   if (level == WS_SOL_SOCKET && optname == WS_SO_OPENTYPE)
2452                   {
2453                       if (optlen < sizeof(int) || !optval)
2454                       {
2455                           SetLastError(WSAEFAULT);
2456                           return SOCKET_ERROR;
2457                       }
2458                       get_per_thread_data()->opentype = *(int *)optval;
2459                       TRACE("setting global SO_OPENTYPE to 0x%x\n", *(int *)optval );
2460                       return 0;
2461 cs130_tom 1.1     }
2462               
2463                   /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
2464                    * socket. This will either not happen under windows or it is ignored in
2465                    * windows (but it works in linux and therefore prevents the game from
2466                    * finding games outside the current network) */
2467                   if ( level==WS_SOL_SOCKET && optname==WS_SO_DONTROUTE ) 
2468                   {
2469                       FIXME("Does windows ignore SO_DONTROUTE?\n");
2470                       return 0;
2471                   }
2472               
2473               #ifdef HAVE_IPX
2474                   if(level == NSPROTO_IPX)
2475                   {
2476               	switch(optname)
2477               	{
2478               	    case IPX_PTYPE:
2479               		fd = get_sock_fd( s, 0, NULL );
2480               		TRACE("trying to set IPX_PTYPE: %d (fd: %d)\n", *(int*)optval, fd);
2481               		
2482 cs130_tom 1.1 		/* We try to set the ipx type on ipx socket level. */
2483               #ifdef SOL_IPX
2484               		if(setsockopt(fd, SOL_IPX, IPX_TYPE, optval, optlen) == -1)
2485               		{
2486               		    ERR("IPX: could not set ipx option type; expect weird behaviour\n");
2487               		    return SOCKET_ERROR;
2488               		}
2489               #else
2490                               {
2491                                   struct ipx val;
2492                                   /* Should we retrieve val using a getsockopt call and then
2493                                    * set the modified one? */
2494                                   val.ipx_pt = *optval;
2495                                   setsockopt(fd, 0, SO_DEFAULT_HEADERS, &val, sizeof(struct ipx));
2496                               }
2497               #endif
2498                   		release_sock_fd( s, fd );
2499               		return 0;
2500               	    case IPX_FILTERPTYPE:
2501               		/* Sets the receive filter packet type, at the moment we don't support it */
2502               		FIXME("IPX_FILTERPTYPE: %x\n", *optval);
2503 cs130_tom 1.1 		
2504               		/* Returning 0 is better for now than returning a SOCKET_ERROR */
2505               		return 0;
2506               	    default:
2507               		FIXME("opt_name:%x\n", optname);
2508               		return SOCKET_ERROR;
2509               	}
2510               	return 0;
2511                   }
2512               #endif
2513               
2514                   /* Is a privileged and useless operation, so we don't. */
2515                   if ((optname == WS_SO_DEBUG) && (level == WS_SOL_SOCKET))
2516                   {
2517                       FIXME("(%d,SOL_SOCKET,SO_DEBUG,%p(%ld)) attempted (is privileged). Ignoring.\n",s,optval,*(DWORD*)optval);
2518                       return 0;
2519                   }
2520               
2521                   if(optname == WS_SO_DONTLINGER && level == WS_SOL_SOCKET) {
2522                       /* This is unique to WinSock and takes special conversion */
2523                       linger.l_onoff  = *((int*)optval) ? 0: 1;
2524 cs130_tom 1.1         linger.l_linger = 0;
2525                       optname=SO_LINGER;
2526                       optval = (char*)&linger;
2527                       optlen = sizeof(struct linger);
2528                       level = SOL_SOCKET;
2529                   }
2530                   else
2531                   {
2532                       if (!convert_sockopt(&level, &optname)) {
2533                           ERR("Invalid level (%d) or optname (%d)\n", level, optname);
2534                           SetLastError(WSAENOPROTOOPT);
2535                           return SOCKET_ERROR;
2536                       }
2537                       if (optname == SO_LINGER && optval) {
2538                           linger.l_onoff  = ((LINGER*)optval)->l_onoff;
2539                           linger.l_linger  = ((LINGER*)optval)->l_linger;
2540                           /* FIXME: what is documented behavior if SO_LINGER optval
2541                              is null?? */
2542                           optval = (char*)&linger;
2543                           optlen = sizeof(struct linger);
2544                       }
2545 cs130_tom 1.1         else if (optval && optlen < sizeof(int))
2546                       {
2547                           woptval= *((INT16 *) optval);
2548                           optval= (char*) &woptval;
2549                           optlen=sizeof(int);
2550                       }
2551                       if (level == SOL_SOCKET && is_timeout_option(optname))
2552                       {
2553                           if (optlen == sizeof(UINT32)) {
2554                               /* WinSock passes miliseconds instead of struct timeval */
2555                               tval.tv_usec = (*(PUINT32)optval % 1000) * 1000;
2556                               tval.tv_sec = *(PUINT32)optval / 1000;
2557                               /* min of 500 milisec */
2558                               if (tval.tv_sec == 0 && tval.tv_usec < 500000)
2559                                   tval.tv_usec = 500000;
2560                               optlen = sizeof(struct timeval);
2561                               optval = (char*)&tval;
2562                           } else if (optlen == sizeof(struct timeval)) {
2563                               WARN("SO_SND/RCVTIMEO for %d bytes: assuming unixism\n", optlen);
2564                           } else {
2565                               WARN("SO_SND/RCVTIMEO for %d bytes is weird: ignored\n", optlen);
2566 cs130_tom 1.1                 return 0;
2567                           }
2568                       }
2569                       if (level == SOL_SOCKET && optname == SO_RCVBUF && *(int*)optval < 2048)
2570                       {
2571                           WARN("SO_RCVBF for %d bytes is too small: ignored\n", *(int*)optval );
2572                           return 0;
2573                       }
2574                   }
2575               
2576               
2577                   fd = get_sock_fd( s, 0, NULL );
2578                   if (fd == -1) return SOCKET_ERROR;
2579               
2580                   if (setsockopt(fd, level, optname, optval, optlen) == 0)
2581                   {
2582                       release_sock_fd( s, fd );
2583                       return 0;
2584                   }
2585                   TRACE("Setting socket error, %d\n", wsaErrno());
2586                   SetLastError(wsaErrno());
2587 cs130_tom 1.1     release_sock_fd( s, fd );
2588                   return SOCKET_ERROR;
2589               }
2590               
2591               /***********************************************************************
2592                *		shutdown		(WS2_32.22)
2593                */
2594               int WINAPI WS_shutdown(SOCKET s, int how)
2595               {
2596                   int fd, fd0 = -1, fd1 = -1, flags, err = WSAENOTSOCK;
2597                   unsigned int clear_flags = 0;
2598               
2599                   fd = get_sock_fd( s, 0, &flags );
2600                   TRACE("socket %04x, how %i %x\n", s, how, flags );
2601               
2602                   if (fd == -1)
2603                       return SOCKET_ERROR;
2604               
2605                   switch( how )
2606                   {
2607                   case 0: /* drop receives */
2608 cs130_tom 1.1         clear_flags |= FD_READ;
2609                       break;
2610                   case 1: /* drop sends */
2611                       clear_flags |= FD_WRITE;
2612                       break;
2613                   case 2: /* drop all */
2614                       clear_flags |= FD_READ|FD_WRITE;
2615                   default:
2616                       clear_flags |= FD_WINE_LISTENING;
2617                   }
2618               
2619                   if ( flags & FD_FLAG_OVERLAPPED ) {
2620               
2621                       switch ( how )
2622                       {
2623                       case SD_RECEIVE:
2624                           fd0 = fd;
2625                           break;
2626                       case SD_SEND:
2627                           fd1 = fd;
2628                           break;
2629 cs130_tom 1.1         case SD_BOTH:
2630                       default:
2631                           fd0 = fd;
2632                           fd1 = get_sock_fd( s, 0, NULL );
2633                           break;
2634                       }
2635               
2636                       if ( fd0 != -1 )
2637                       {
2638                           err = WS2_register_async_shutdown( s, fd0, ws2m_sd_read );
2639                           if ( err )
2640                           {
2641                               release_sock_fd( s, fd0 );
2642                               goto error;
2643                           }
2644                       }
2645                       if ( fd1 != -1 )
2646                       {
2647                           err = WS2_register_async_shutdown( s, fd1, ws2m_sd_write );
2648                           if ( err )
2649                           {
2650 cs130_tom 1.1                 release_sock_fd( s, fd1 );
2651                               goto error;
2652                           }
2653                       }
2654                   }
2655                   else /* non-overlapped mode */
2656                   {
2657                       if ( shutdown( fd, how ) )
2658                       {
2659                           err = wsaErrno();
2660                           release_sock_fd( s, fd );
2661                           goto error;
2662                       }
2663                       release_sock_fd( s, fd );
2664                   }
2665               
2666                   _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2667                   if ( how > 1) WSAAsyncSelect( s, 0, 0, 0 );
2668                   return 0;
2669               
2670               error:
2671 cs130_tom 1.1     _enable_event( SOCKET2HANDLE(s), 0, 0, clear_flags );
2672                   WSASetLastError( err );
2673                   return SOCKET_ERROR;
2674               }
2675               
2676               /***********************************************************************
2677                *		socket		(WS2_32.23)
2678                */
2679               SOCKET WINAPI WS_socket(int af, int type, int protocol)
2680               {
2681                   TRACE("af=%d type=%d protocol=%d\n", af, type, protocol);
2682               
2683                   return WSASocketA( af, type, protocol, NULL, 0,
2684                                      get_per_thread_data()->opentype ? 0 : WSA_FLAG_OVERLAPPED );
2685               }
2686               
2687               
2688               /***********************************************************************
2689                *		gethostbyaddr		(WS2_32.51)
2690                */
2691               struct WS_hostent* WINAPI WS_gethostbyaddr(const char *addr, int len, int type)
2692 cs130_tom 1.1 {
2693                   struct WS_hostent *retval = NULL;
2694                   struct hostent* host;
2695               
2696               #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
2697                   char *extrabuf;
2698                   int ebufsize=1024;
2699                   struct hostent hostentry;
2700                   int locerr=ENOBUFS;
2701                   host = NULL;
2702                   extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2703                   while(extrabuf) {
2704                       int res = gethostbyaddr_r(addr, len, type,
2705                                                 &hostentry, extrabuf, ebufsize, &host, &locerr);
2706                       if( res != ERANGE) break;
2707                       ebufsize *=2;
2708                       extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2709                   }
2710                   if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2711               #else
2712                   EnterCriticalSection( &csWSgetXXXbyYYY );
2713 cs130_tom 1.1     host = gethostbyaddr(addr, len, type);
2714                   if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2715               #endif
2716                   if( host != NULL ) retval = WS_dup_he(host);
2717               #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2718                   HeapFree(GetProcessHeap(),0,extrabuf);
2719               #else
2720                   LeaveCriticalSection( &csWSgetXXXbyYYY );
2721               #endif
2722                   TRACE("ptr %p, len %d, type %d ret %p\n", addr, len, type, retval);
2723                   return retval;
2724               }
2725               
2726               /***********************************************************************
2727                *		gethostbyname		(WS2_32.52)
2728                */
2729               struct WS_hostent* WINAPI WS_gethostbyname(const char* name)
2730               {
2731                   struct WS_hostent *retval = NULL;
2732                   struct hostent*     host;
2733               #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2734 cs130_tom 1.1     char *extrabuf;
2735                   int ebufsize=1024;
2736                   struct hostent hostentry;
2737                   int locerr = ENOBUFS;
2738               #endif
2739                   char buf[100];
2740                   if( !name) {
2741                       name = buf;
2742                       if( gethostname( buf, 100) == -1) {
2743                           SetLastError( WSAENOBUFS); /* appropriate ? */
2744                           return retval;
2745                       }
2746                   }
2747               #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2748                   host = NULL;
2749                   extrabuf=HeapAlloc(GetProcessHeap(),0,ebufsize) ;
2750                   while(extrabuf) {
2751                       int res = gethostbyname_r(name, &hostentry, extrabuf, ebufsize, &host, &locerr);
2752                       if( res != ERANGE) break;
2753                       ebufsize *=2;
2754                       extrabuf=HeapReAlloc(GetProcessHeap(),0,extrabuf,ebufsize) ;
2755 cs130_tom 1.1     }
2756                   if (!host) SetLastError((locerr < 0) ? wsaErrno() : wsaHerrno(locerr));
2757               #else
2758                   EnterCriticalSection( &csWSgetXXXbyYYY );
2759                   host = gethostbyname(name);
2760                   if (!host) SetLastError((h_errno < 0) ? wsaErrno() : wsaHerrno(h_errno));
2761               #endif
2762                   if (host) retval = WS_dup_he(host);
2763               #ifdef  HAVE_LINUX_GETHOSTBYNAME_R_6
2764                   HeapFree(GetProcessHeap(),0,extrabuf);
2765               #else
2766                   LeaveCriticalSection( &csWSgetXXXbyYYY );
2767               #endif
2768                   TRACE( "%s ret %p\n", debugstr_a(name), retval );
2769                   return retval;
2770               }
2771               
2772               
2773               /***********************************************************************
2774                *		getprotobyname		(WS2_32.53)
2775                */
2776 cs130_tom 1.1 struct WS_protoent* WINAPI WS_getprotobyname(const char* name)
2777               {
2778                   struct WS_protoent* retval = NULL;
2779               #ifdef HAVE_GETPROTOBYNAME
2780                   struct protoent*     proto;
2781                   EnterCriticalSection( &csWSgetXXXbyYYY );
2782                   if( (proto = getprotobyname(name)) != NULL )
2783                   {
2784                       retval = WS_dup_pe(proto);
2785                   }
2786                   else {
2787                       MESSAGE("protocol %s not found; You might want to add "
2788                               "this to /etc/protocols\n", debugstr_a(name) );
2789                       SetLastError(WSANO_DATA);
2790                   }
2791                   LeaveCriticalSection( &csWSgetXXXbyYYY );
2792               #endif
2793                   TRACE( "%s ret %p\n", debugstr_a(name), retval );
2794                   return retval;
2795               }
2796               
2797 cs130_tom 1.1 
2798               /***********************************************************************
2799                *		getprotobynumber	(WS2_32.54)
2800                */
2801               struct WS_protoent* WINAPI WS_getprotobynumber(int number)
2802               {
2803                   struct WS_protoent* retval = NULL;
2804               #ifdef HAVE_GETPROTOBYNUMBER
2805                   struct protoent*     proto;
2806                   EnterCriticalSection( &csWSgetXXXbyYYY );
2807                   if( (proto = getprotobynumber(number)) != NULL )
2808                   {
2809                       retval = WS_dup_pe(proto);
2810                   }
2811                   else {
2812                       MESSAGE("protocol number %d not found; You might want to add "
2813                               "this to /etc/protocols\n", number );
2814                       SetLastError(WSANO_DATA);
2815                   }
2816                   LeaveCriticalSection( &csWSgetXXXbyYYY );
2817               #endif
2818 cs130_tom 1.1     TRACE("%i ret %p\n", number, retval);
2819                   return retval;
2820               }
2821               
2822               
2823               /***********************************************************************
2824                *		getservbyname		(WS2_32.55)
2825                */
2826               struct WS_servent* WINAPI WS_getservbyname(const char *name, const char *proto)
2827               {
2828                   struct WS_servent* retval = NULL;
2829                   struct servent*     serv;
2830                   char *name_str;
2831                   char *proto_str = NULL;
2832               
2833                   if (!(name_str = strdup_lower(name))) return NULL;
2834               
2835                   if (proto && *proto)
2836                   {
2837                       if (!(proto_str = strdup_lower(proto)))
2838                       {
2839 cs130_tom 1.1             HeapFree( GetProcessHeap(), 0, name_str );
2840                           return NULL;
2841                       }
2842                   }
2843               
2844                   EnterCriticalSection( &csWSgetXXXbyYYY );
2845                   serv = getservbyname(name_str, proto_str);
2846                   if( serv != NULL )
2847                   {
2848                       retval = WS_dup_se(serv);
2849                   }
2850                   else SetLastError(WSANO_DATA);
2851                   LeaveCriticalSection( &csWSgetXXXbyYYY );
2852                   HeapFree( GetProcessHeap(), 0, proto_str );
2853                   HeapFree( GetProcessHeap(), 0, name_str );
2854                   TRACE( "%s, %s ret %p\n", debugstr_a(name), debugstr_a(proto), retval );
2855                   return retval;
2856               }
2857               
2858               
2859               /***********************************************************************
2860 cs130_tom 1.1  *		getservbyport		(WS2_32.56)
2861                */
2862               struct WS_servent* WINAPI WS_getservbyport(int port, const char *proto)
2863               {
2864                   struct WS_servent* retval = NULL;
2865               #ifdef HAVE_GETSERVBYPORT
2866                   struct servent*     serv;
2867                   char *proto_str = NULL;
2868               
2869                   if (proto && *proto)
2870                   {
2871                       if (!(proto_str = strdup_lower(proto))) return NULL;
2872                   }
2873                   EnterCriticalSection( &csWSgetXXXbyYYY );
2874                   if( (serv = getservbyport(port, proto_str)) != NULL ) {
2875                       retval = WS_dup_se(serv);
2876                   }
2877                   else SetLastError(WSANO_DATA);
2878                   LeaveCriticalSection( &csWSgetXXXbyYYY );
2879                   HeapFree( GetProcessHeap(), 0, proto_str );
2880               #endif
2881 cs130_tom 1.1     TRACE("%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval);
2882                   return retval;
2883               }
2884               
2885               
2886               /***********************************************************************
2887                *              gethostname           (WS2_32.57)
2888                */
2889               int WINAPI WS_gethostname(char *name, int namelen)
2890               {
2891                   TRACE("name %p, len %d\n", name, namelen);
2892               
2893                   if (gethostname(name, namelen) == 0)
2894                   {
2895                       TRACE("<- '%s'\n", name);
2896                       return 0;
2897                   }
2898                   SetLastError((errno == EINVAL) ? WSAEFAULT : wsaErrno());
2899                   TRACE("<- ERROR !\n");
2900                   return SOCKET_ERROR;
2901               }
2902 cs130_tom 1.1 
2903               
2904               /* ------------------------------------- Windows sockets extensions -- *
2905                *								       *
2906                * ------------------------------------------------------------------- */
2907               
2908               /***********************************************************************
2909                *		WSAEnumNetworkEvents (WS2_32.36)
2910                */
2911               int WINAPI WSAEnumNetworkEvents(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
2912               {
2913                   int ret;
2914               
2915                   TRACE("%08x, hEvent %p, lpEvent %08x\n", s, hEvent, (unsigned)lpEvent );
2916               
2917                   SERVER_START_REQ( get_socket_event )
2918                   {
2919                       req->handle  = SOCKET2HANDLE(s);
2920                       req->service = TRUE;
2921                       req->c_event = hEvent;
2922                       wine_server_set_reply( req, lpEvent->iErrorCode, sizeof(lpEvent->iErrorCode) );
2923 cs130_tom 1.1         if (!(ret = wine_server_call(req))) lpEvent->lNetworkEvents = reply->pmask & reply->mask;
2924                   }
2925                   SERVER_END_REQ;
2926                   if (!ret) return 0;
2927                   SetLastError(WSAEINVAL);
2928                   return SOCKET_ERROR;
2929               }
2930               
2931               /***********************************************************************
2932                *		WSAEventSelect (WS2_32.39)
2933                */
2934               int WINAPI WSAEventSelect(SOCKET s, WSAEVENT hEvent, long lEvent)
2935               {
2936                   int ret;
2937               
2938                   TRACE("%08x, hEvent %p, event %08x\n", s, hEvent, (unsigned)lEvent );
2939               
2940                   SERVER_START_REQ( set_socket_event )
2941                   {
2942                       req->handle = SOCKET2HANDLE(s);
2943                       req->mask   = lEvent;
2944 cs130_tom 1.1         req->event  = hEvent;
2945                       req->window = 0;
2946                       req->msg    = 0;
2947                       ret = wine_server_call( req );
2948                   }
2949                   SERVER_END_REQ;
2950                   if (!ret) return 0;
2951                   SetLastError(WSAEINVAL);
2952                   return SOCKET_ERROR;
2953               }
2954               
2955               /**********************************************************************
2956                *      WSAGetOverlappedResult (WS2_32.40)
2957                */
2958               BOOL WINAPI WSAGetOverlappedResult( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
2959                                                   LPDWORD lpcbTransfer, BOOL fWait,
2960                                                   LPDWORD lpdwFlags )
2961               {
2962                   DWORD r;
2963               
2964                   TRACE( "socket %04x ovl %p trans %p, wait %d flags %p\n",
2965 cs130_tom 1.1            s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
2966               
2967                   if ( lpOverlapped == NULL )
2968                   {
2969                       ERR( "Invalid pointer\n" );
2970                       WSASetLastError(WSA_INVALID_PARAMETER);
2971                       return FALSE;
2972                   }
2973               
2974                   if ( fWait )
2975                   {
2976                       if (lpOverlapped->hEvent)
2977                           while ( WaitForSingleObjectEx(lpOverlapped->hEvent, 
2978                                                         INFINITE, TRUE) == STATUS_USER_APC );
2979                       else /* busy loop */
2980                           while ( ((volatile OVERLAPPED*)lpOverlapped)->Internal == STATUS_PENDING )
2981                               Sleep( 10 );
2982               
2983                   }
2984                   else if ( lpOverlapped->Internal == STATUS_PENDING )
2985                   {
2986 cs130_tom 1.1         /* Wait in order to give APCs a chance to run. */
2987                       /* This is cheating, so we must set the event again in case of success -
2988                          it may be a non-manual reset event. */
2989                       while ( (r = WaitForSingleObjectEx(lpOverlapped->hEvent, 0, TRUE)) == STATUS_USER_APC );
2990                       if ( r == WAIT_OBJECT_0 && lpOverlapped->hEvent )
2991                           NtSetEvent( lpOverlapped->hEvent, NULL );
2992                   }
2993               
2994                   if ( lpcbTransfer )
2995                       *lpcbTransfer = lpOverlapped->InternalHigh;
2996               
2997                   if ( lpdwFlags )
2998                       *lpdwFlags = lpOverlapped->Offset;
2999               
3000                   switch ( lpOverlapped->Internal )
3001                   {
3002                   case STATUS_SUCCESS:
3003                       return TRUE;
3004                   case STATUS_PENDING:
3005                       WSASetLastError( WSA_IO_INCOMPLETE );
3006                       if (fWait) ERR("PENDING status after waiting!\n");
3007 cs130_tom 1.1         return FALSE;
3008                   default:
3009                       WSASetLastError( NtStatusToWSAError( lpOverlapped->Internal ));
3010                       return FALSE;
3011                   }
3012               }
3013               
3014               
3015               /***********************************************************************
3016                *      WSAAsyncSelect			(WS2_32.101)
3017                */
3018               INT WINAPI WSAAsyncSelect(SOCKET s, HWND hWnd, UINT uMsg, long lEvent)
3019               {
3020                   int ret;
3021               
3022                   TRACE("%x, hWnd %p, uMsg %08x, event %08lx\n", s, hWnd, uMsg, lEvent );
3023               
3024                   SERVER_START_REQ( set_socket_event )
3025                   {
3026                       req->handle = SOCKET2HANDLE(s);
3027                       req->mask   = lEvent;
3028 cs130_tom 1.1         req->event  = 0;
3029                       req->window = hWnd;
3030                       req->msg    = uMsg;
3031                       ret = wine_server_call( req );
3032                   }
3033                   SERVER_END_REQ;
3034                   if (!ret) return 0;
3035                   SetLastError(WSAEINVAL);
3036                   return SOCKET_ERROR;
3037               }
3038               
3039               /***********************************************************************
3040                *      WSACreateEvent          (WS2_32.31)
3041                *
3042                */
3043               WSAEVENT WINAPI WSACreateEvent(void)
3044               {
3045                   /* Create a manual-reset event, with initial state: unsignaled */
3046                   TRACE("\n");
3047               
3048                   return CreateEventW(NULL, TRUE, FALSE, NULL);
3049 cs130_tom 1.1 }
3050               
3051               /***********************************************************************
3052                *      WSACloseEvent          (WS2_32.29)
3053                *
3054                */
3055               BOOL WINAPI WSACloseEvent(WSAEVENT event)
3056               {
3057                   TRACE ("event=%p\n", event);
3058               
3059                   return CloseHandle(event);
3060               }
3061               
3062               /***********************************************************************
3063                *      WSASocketA          (WS2_32.78)
3064                *
3065                */
3066               SOCKET WINAPI WSASocketA(int af, int type, int protocol,
3067                                        LPWSAPROTOCOL_INFOA lpProtocolInfo,
3068                                        GROUP g, DWORD dwFlags)
3069               {
3070 cs130_tom 1.1     INT len;
3071                   WSAPROTOCOL_INFOW info;
3072               
3073                   TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3074                         af, type, protocol, lpProtocolInfo, g, dwFlags);
3075               
3076                   if (!lpProtocolInfo) return WSASocketW(af, type, protocol, NULL, g, dwFlags);
3077               
3078                   memcpy(&info, lpProtocolInfo, FIELD_OFFSET(WSAPROTOCOL_INFOW, szProtocol));
3079                   len = MultiByteToWideChar(CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3080                                             info.szProtocol, WSAPROTOCOL_LEN * sizeof(WCHAR) + 1);
3081               
3082                   if (!len)
3083                   {
3084                       WSASetLastError( WSAEINVAL);
3085                       return SOCKET_ERROR;
3086                   }
3087               
3088                   return WSASocketW(af, type, protocol, &info, g, dwFlags);
3089               }
3090               
3091 cs130_tom 1.1 /***********************************************************************
3092                *      WSASocketW          (WS2_32.79)
3093                *
3094                */
3095               SOCKET WINAPI WSASocketW(int af, int type, int protocol,
3096                                        LPWSAPROTOCOL_INFOW lpProtocolInfo,
3097                                        GROUP g, DWORD dwFlags)
3098               {
3099                   SOCKET ret;
3100               
3101                  /*
3102                     FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
3103                     g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3104                  */
3105               
3106                  TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%lx\n",
3107                        af, type, protocol, lpProtocolInfo, g, dwFlags );
3108               
3109                   /* hack for WSADuplicateSocket */
3110                   if (lpProtocolInfo && lpProtocolInfo->dwServiceFlags4 == 0xff00ff00) {
3111                     ret = lpProtocolInfo->dwCatalogEntryId;
3112 cs130_tom 1.1       TRACE("\tgot duplicate %04x\n", ret);
3113                     return ret;
3114                   }
3115               
3116                   /* check the socket family */
3117                   switch(af)
3118                   {
3119               #ifdef HAVE_IPX
3120                       case WS_AF_IPX: af = AF_IPX;
3121               #endif
3122                       case AF_INET:
3123                       case AF_UNSPEC:
3124                           break;
3125                       default:
3126                           SetLastError(WSAEAFNOSUPPORT);
3127                           return INVALID_SOCKET;
3128                   }
3129               
3130                   /* check the socket type */
3131                   switch(type)
3132                   {
3133 cs130_tom 1.1         case WS_SOCK_STREAM:
3134                           type=SOCK_STREAM;
3135                           break;
3136                       case WS_SOCK_DGRAM:
3137                           type=SOCK_DGRAM;
3138                           break;
3139                       case WS_SOCK_RAW:
3140                           type=SOCK_RAW;
3141                           break;
3142                       default:
3143                           SetLastError(WSAESOCKTNOSUPPORT);
3144                           return INVALID_SOCKET;
3145                   }
3146               
3147                   /* check the protocol type */
3148                   if ( protocol < 0 )  /* don't support negative values */
3149                   {
3150                       SetLastError(WSAEPROTONOSUPPORT);
3151                       return INVALID_SOCKET;
3152                   }
3153               
3154 cs130_tom 1.1     if ( af == AF_UNSPEC)  /* did they not specify the address family? */
3155                       switch(protocol)
3156               	{
3157                         case IPPROTO_TCP:
3158                            if (type == SOCK_STREAM) { af = AF_INET; break; }
3159                         case IPPROTO_UDP:
3160                            if (type == SOCK_DGRAM)  { af = AF_INET; break; }
3161                         default: SetLastError(WSAEPROTOTYPE); return INVALID_SOCKET;
3162                       }
3163               
3164                   SERVER_START_REQ( create_socket )
3165                   {
3166                       req->family   = af;
3167                       req->type     = type;
3168                       req->protocol = protocol;
3169                       req->access   = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
3170                       req->flags    = dwFlags;
3171                       req->inherit  = TRUE;
3172                       set_error( wine_server_call( req ) );
3173                       ret = HANDLE2SOCKET( reply->handle );
3174                   }
3175 cs130_tom 1.1     SERVER_END_REQ;
3176                   if (ret)
3177                   {
3178                       TRACE("\tcreated %04x\n", ret );
3179                       return ret;
3180                   }
3181               
3182                   if (GetLastError() == WSAEACCES) /* raw socket denied */
3183                   {
3184                       if (type == SOCK_RAW)
3185                           MESSAGE("WARNING: Trying to create a socket of type SOCK_RAW, will fail unless running as root\n");
3186                       else
3187                           MESSAGE("WS_SOCKET: not enough privileges to create socket, try running as root\n");
3188                       SetLastError(WSAESOCKTNOSUPPORT);
3189                   }
3190               
3191                   WARN("\t\tfailed!\n");
3192                   return INVALID_SOCKET;
3193               }
3194               
3195               /***********************************************************************
3196 cs130_tom 1.1  *      WSAJoinLeaf          (WS2_32.58)
3197                *
3198                */
3199               SOCKET WINAPI WSAJoinLeaf(
3200                       SOCKET s,
3201                       const struct WS_sockaddr *addr,
3202                       int addrlen,
3203                       LPWSABUF lpCallerData,
3204                       LPWSABUF lpCalleeData,
3205                       LPQOS lpSQOS,
3206                       LPQOS lpGQOS,
3207                       DWORD dwFlags)
3208               {
3209                   FIXME("stub.\n");
3210                   return INVALID_SOCKET;
3211               }
3212               
3213               /***********************************************************************
3214                *      __WSAFDIsSet			(WS2_32.151)
3215                */
3216               int WINAPI __WSAFDIsSet(SOCKET s, WS_fd_set *set)
3217 cs130_tom 1.1 {
3218                 int i = set->fd_count;
3219               
3220                 TRACE("(%d,%8lx(%i))\n", s,(unsigned long)set, i);
3221               
3222                 while (i--)
3223                     if (set->fd_array[i] == s) return 1;
3224                 return 0;
3225               }
3226               
3227               /***********************************************************************
3228                *      WSAIsBlocking			(WINSOCK.114)
3229                *      WSAIsBlocking			(WS2_32.114)
3230                */
3231               BOOL WINAPI WSAIsBlocking(void)
3232               {
3233                 /* By default WinSock should set all its sockets to non-blocking mode
3234                  * and poll in PeekMessage loop when processing "blocking" ones. This
3235                  * function is supposed to tell if the program is in this loop. Our
3236                  * blocking calls are truly blocking so we always return FALSE.
3237                  *
3238 cs130_tom 1.1    * Note: It is allowed to call this function without prior WSAStartup().
3239                  */
3240               
3241                 TRACE("\n");
3242                 return FALSE;
3243               }
3244               
3245               /***********************************************************************
3246                *      WSACancelBlockingCall		(WINSOCK.113)
3247                *      WSACancelBlockingCall		(WS2_32.113)
3248                */
3249               INT WINAPI WSACancelBlockingCall(void)
3250               {
3251                   TRACE("\n");
3252                   return 0;
3253               }
3254               
3255               static INT WINAPI WSA_DefaultBlockingHook( FARPROC x )
3256               {
3257                   FIXME("How was this called?\n");
3258                   return x();
3259 cs130_tom 1.1 }
3260               
3261               
3262               /***********************************************************************
3263                *      WSASetBlockingHook (WS2_32.109)
3264                */
3265               FARPROC WINAPI WSASetBlockingHook(FARPROC lpBlockFunc)
3266               {
3267                 FARPROC prev = blocking_hook;
3268                 blocking_hook = lpBlockFunc;
3269                 TRACE("hook %p\n", lpBlockFunc);
3270                 return prev;
3271               }
3272               
3273               
3274               /***********************************************************************
3275                *      WSAUnhookBlockingHook (WS2_32.110)
3276                */
3277               INT WINAPI WSAUnhookBlockingHook(void)
3278               {
3279                   blocking_hook = WSA_DefaultBlockingHook;
3280 cs130_tom 1.1     return 0;
3281               }
3282               
3283               
3284               /* ----------------------------------- end of API stuff */
3285               
3286               /* ----------------------------------- helper functions -
3287                *
3288                * TODO: Merge WS_dup_..() stuff into one function that
3289                * would operate with a generic structure containing internal
3290                * pointers (via a template of some kind).
3291                */
3292               
3293               static int list_size(char** l, int item_size)
3294               {
3295                 int i,j = 0;
3296                 if(l)
3297                 { for(i=0;l[i];i++)
3298               	j += (item_size) ? item_size : strlen(l[i]) + 1;
3299                   j += (i + 1) * sizeof(char*); }
3300                 return j;
3301 cs130_tom 1.1 }
3302               
3303               static int list_dup(char** l_src, char** l_to, int item_size)
3304               {
3305                  char *p;
3306                  int i;
3307               
3308                  for (i = 0; l_src[i]; i++) ;
3309                  p = (char *)(l_to + i + 1);
3310                  for (i = 0; l_src[i]; i++)
3311                  {
3312                      int count = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
3313                      memcpy(p, l_src[i], count);
3314                      l_to[i] = p;
3315                      p += count;
3316                  }
3317                  l_to[i] = NULL;
3318                  return p - (char *)l_to;
3319               }
3320               
3321               /* ----- hostent */
3322 cs130_tom 1.1 
3323               /* duplicate hostent entry
3324                * and handle all Win16/Win32 dependent things (struct size, ...) *correctly*.
3325                * Dito for protoent and servent.
3326                */
3327               static struct WS_hostent *WS_dup_he(const struct hostent* p_he)
3328               {
3329                   char *p;
3330                   struct WS_hostent *p_to;
3331               
3332                   int size = (sizeof(*p_he) +
3333                               strlen(p_he->h_name) + 1 +
3334                               list_size(p_he->h_aliases, 0) +
3335                               list_size(p_he->h_addr_list, p_he->h_length));
3336               
3337                   if (!(p_to = check_buffer_he(size))) return NULL;
3338                   p_to->h_addrtype = p_he->h_addrtype;
3339                   p_to->h_length = p_he->h_length;
3340               
3341                   p = (char *)(p_to + 1);
3342                   p_to->h_name = p;
3343 cs130_tom 1.1     strcpy(p, p_he->h_name);
3344                   p += strlen(p) + 1;
3345               
3346                   p_to->h_aliases = (char **)p;
3347                   p += list_dup(p_he->h_aliases, p_to->h_aliases, 0);
3348               
3349                   p_to->h_addr_list = (char **)p;
3350                   list_dup(p_he->h_addr_list, p_to->h_addr_list, p_he->h_length);
3351                   return p_to;
3352               }
3353               
3354               /* ----- protoent */
3355               
3356               static struct WS_protoent *WS_dup_pe(const struct protoent* p_pe)
3357               {
3358                   char *p;
3359                   struct WS_protoent *p_to;
3360               
3361                   int size = (sizeof(*p_pe) +
3362                               strlen(p_pe->p_name) + 1 +
3363                               list_size(p_pe->p_aliases, 0));
3364 cs130_tom 1.1 
3365                   if (!(p_to = check_buffer_pe(size))) return NULL;
3366                   p_to->p_proto = p_pe->p_proto;
3367               
3368                   p = (char *)(p_to + 1);
3369                   p_to->p_name = p;
3370                   strcpy(p, p_pe->p_name);
3371                   p += strlen(p) + 1;
3372               
3373                   p_to->p_aliases = (char **)p;
3374                   list_dup(p_pe->p_aliases, p_to->p_aliases, 0);
3375                   return p_to;
3376               }
3377               
3378               /* ----- servent */
3379               
3380               static struct WS_servent *WS_dup_se(const struct servent* p_se)
3381               {
3382                   char *p;
3383 cs130_tom 1.2     struct per_thread_data * ptb = get_per_thread_data();
3384 cs130_tom 1.1 
3385 cs130_tom 1.2     int size = (strlen(p_se->s_proto) + 1 +
3386 cs130_tom 1.1                 strlen(p_se->s_name) + 1 +
3387                               list_size(p_se->s_aliases, 0));
3388               
3389 cs130_tom 1.2     if (!(p = check_buffer_se(size))) return NULL;
3390                   ptb->se.s_port = p_se->s_port;
3391 cs130_tom 1.1 
3392 cs130_tom 1.2     ptb->se.s_name = p;
3393 cs130_tom 1.1     strcpy(p, p_se->s_name);
3394                   p += strlen(p) + 1;
3395               
3396 cs130_tom 1.2     ptb->se.s_proto = p;
3397 cs130_tom 1.1     strcpy(p, p_se->s_proto);
3398                   p += strlen(p) + 1;
3399               
3400 cs130_tom 1.2     ptb->se.s_aliases = (char **)p;
3401                   list_dup(p_se->s_aliases, ptb->se.s_aliases, 0);
3402               
3403                   return &ptb->se;
3404 cs130_tom 1.1 }
3405               
3406               /* ----------------------------------- error handling */
3407               
3408               UINT wsaErrno(void)
3409               {
3410                   int	loc_errno = errno;
3411                   WARN("errno %d, (%s).\n", loc_errno, strerror(loc_errno));
3412               
3413                   switch(loc_errno)
3414                   {
3415               	case EINTR:		return WSAEINTR;
3416               	case EBADF:		return WSAEBADF;
3417               	case EPERM:
3418               	case EACCES:		return WSAEACCES;
3419               	case EFAULT:		return WSAEFAULT;
3420               	case EINVAL:		return WSAEINVAL;
3421               	case EMFILE:		return WSAEMFILE;
3422               	case EWOULDBLOCK:	return WSAEWOULDBLOCK;
3423               	case EINPROGRESS:	return WSAEINPROGRESS;
3424               	case EALREADY:		return WSAEALREADY;
3425 cs130_tom 1.1 	case ENOTSOCK:		return WSAENOTSOCK;
3426               	case EDESTADDRREQ:	return WSAEDESTADDRREQ;
3427               	case EMSGSIZE:		return WSAEMSGSIZE;
3428               	case EPROTOTYPE:	return WSAEPROTOTYPE;
3429               	case ENOPROTOOPT:	return WSAENOPROTOOPT;
3430               	case EPROTONOSUPPORT:	return WSAEPROTONOSUPPORT;
3431               	case ESOCKTNOSUPPORT:	return WSAESOCKTNOSUPPORT;
3432               	case EOPNOTSUPP:	return WSAEOPNOTSUPP;
3433               	case EPFNOSUPPORT:	return WSAEPFNOSUPPORT;
3434               	case EAFNOSUPPORT:	return WSAEAFNOSUPPORT;
3435               	case EADDRINUSE:	return WSAEADDRINUSE;
3436               	case EADDRNOTAVAIL:	return WSAEADDRNOTAVAIL;
3437               	case ENETDOWN:		return WSAENETDOWN;
3438               	case ENETUNREACH:	return WSAENETUNREACH;
3439               	case ENETRESET:		return WSAENETRESET;
3440               	case ECONNABORTED:	return WSAECONNABORTED;
3441               	case EPIPE:
3442               	case ECONNRESET:	return WSAECONNRESET;
3443               	case ENOBUFS:		return WSAENOBUFS;
3444               	case EISCONN:		return WSAEISCONN;
3445               	case ENOTCONN:		return WSAENOTCONN;
3446 cs130_tom 1.1 	case ESHUTDOWN:		return WSAESHUTDOWN;
3447               	case ETOOMANYREFS:	return WSAETOOMANYREFS;
3448               	case ETIMEDOUT:		return WSAETIMEDOUT;
3449               	case ECONNREFUSED:	return WSAECONNREFUSED;
3450               	case ELOOP:		return WSAELOOP;
3451               	case ENAMETOOLONG:	return WSAENAMETOOLONG;
3452               	case EHOSTDOWN:		return WSAEHOSTDOWN;
3453               	case EHOSTUNREACH:	return WSAEHOSTUNREACH;
3454               	case ENOTEMPTY:		return WSAENOTEMPTY;
3455               #ifdef EPROCLIM
3456               	case EPROCLIM:		return WSAEPROCLIM;
3457               #endif
3458               #ifdef EUSERS
3459               	case EUSERS:		return WSAEUSERS;
3460               #endif
3461               #ifdef EDQUOT
3462               	case EDQUOT:		return WSAEDQUOT;
3463               #endif
3464               #ifdef ESTALE
3465               	case ESTALE:		return WSAESTALE;
3466               #endif
3467 cs130_tom 1.1 #ifdef EREMOTE
3468               	case EREMOTE:		return WSAEREMOTE;
3469               #endif
3470               
3471                      /* just in case we ever get here and there are no problems */
3472               	case 0:			return 0;
3473                       default:
3474               		WARN("Unknown errno %d!\n", loc_errno);
3475               		return WSAEOPNOTSUPP;
3476                   }
3477               }
3478               
3479               UINT wsaHerrno(int loc_errno)
3480               {
3481               
3482                   WARN("h_errno %d.\n", loc_errno);
3483               
3484                   switch(loc_errno)
3485                   {
3486               	case HOST_NOT_FOUND:	return WSAHOST_NOT_FOUND;
3487               	case TRY_AGAIN:		return WSATRY_AGAIN;
3488 cs130_tom 1.1 	case NO_RECOVERY:	return WSANO_RECOVERY;
3489               	case NO_DATA:		return WSANO_DATA;
3490               	case ENOBUFS:		return WSAENOBUFS;
3491               
3492               	case 0:			return 0;
3493                       default:
3494               		WARN("Unknown h_errno %d!\n", loc_errno);
3495               		return WSAEOPNOTSUPP;
3496                   }
3497               }
3498               
3499               
3500               /***********************************************************************
3501                *		WSARecv			(WS2_32.67)
3502                */
3503               int WINAPI WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3504                                  LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
3505                                  LPWSAOVERLAPPED lpOverlapped,
3506                                  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
3507               {
3508                   return WSARecvFrom(s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
3509 cs130_tom 1.1                        NULL, NULL, lpOverlapped, lpCompletionRoutine);
3510               }
3511               
3512               /***********************************************************************
3513                *              WSARecvFrom             (WS2_32.69)
3514                */
3515               INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
3516                                       LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
3517                                       LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
3518                                       LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
3519               
3520               {
3521                   unsigned int i;
3522                   int n, fd, err = WSAENOTSOCK, flags, ret;
3523                   struct iovec* iovec;
3524                   struct ws2_async *wsa;
3525                   IO_STATUS_BLOCK* iosb;
3526               
3527                   TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
3528                         s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
3529                         (lpFromlen ? *lpFromlen : -1L),
3530 cs130_tom 1.1           lpOverlapped, lpCompletionRoutine);
3531               
3532                   fd = get_sock_fd( s, GENERIC_READ, &flags );
3533                   TRACE( "fd=%d, flags=%x\n", fd, flags );
3534               
3535                   if (fd == -1) return SOCKET_ERROR;
3536               
3537                   if (flags & FD_FLAG_RECV_SHUTDOWN)
3538                   {
3539                       WSASetLastError( WSAESHUTDOWN );
3540                       goto err_close;
3541                   }
3542               
3543                   iovec = HeapAlloc( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
3544                   if ( !iovec )
3545                   {
3546                       err = WSAEFAULT;
3547                       goto err_close;
3548                   }
3549               
3550                   for (i = 0; i < dwBufferCount; i++)
3551 cs130_tom 1.1     {
3552                       iovec[i].iov_base = lpBuffers[i].buf;
3553                       iovec[i].iov_len  = lpBuffers[i].len;
3554                   }
3555               
3556                   if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
3557                   {
3558                       wsa = WS2_make_async( s, fd, ws2m_read, iovec, dwBufferCount,
3559                                             lpFlags, lpFrom, lpFromlen,
3560                                             lpOverlapped, lpCompletionRoutine, &iosb );
3561               
3562                       if ( !wsa )
3563                       {
3564                           err = WSAEFAULT;
3565                           goto err_free;
3566                       }
3567               
3568                       if ( ( ret = ws2_queue_async( wsa, iosb )) )
3569                       {
3570                           err = NtStatusToWSAError( ret );
3571               
3572 cs130_tom 1.1             if ( !lpOverlapped )
3573                               HeapFree( GetProcessHeap(), 0, iosb );
3574                           HeapFree( GetProcessHeap(), 0, wsa );
3575                           goto err_free;
3576                       }
3577               
3578                       /* Try immediate completion */
3579                       if ( lpOverlapped )
3580                       {
3581                           if  ( WSAGetOverlappedResult( s, lpOverlapped,
3582                                                          lpNumberOfBytesRecvd, FALSE, lpFlags) )
3583                               return 0;
3584               
3585                           if ( (err = WSAGetLastError()) != WSA_IO_INCOMPLETE )
3586                               goto error;
3587                       }
3588               
3589                       WSASetLastError( WSA_IO_PENDING );
3590                       return SOCKET_ERROR;
3591                   }
3592               
3593 cs130_tom 1.1     if ( _is_blocking(s) )
3594                   {
3595                       /* block here */
3596                       /* FIXME: OOB and exceptfds? */
3597                       int timeout = GET_RCVTIMEO(fd);
3598                       if( !do_block(fd, POLLIN, timeout)) {
3599                           err = WSAETIMEDOUT;
3600                           /* a timeout is not fatal */
3601                           _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3602                           goto err_free;
3603                       }
3604                   }
3605               
3606                   n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
3607                   if ( n == -1 )
3608                   {
3609                       err = wsaErrno();
3610                       goto err_free;
3611                   }
3612               
3613                   TRACE(" -> %i bytes\n", n);
3614 cs130_tom 1.1     *lpNumberOfBytesRecvd = n;
3615               
3616                   HeapFree(GetProcessHeap(), 0, iovec);
3617                   release_sock_fd( s, fd );
3618                   _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
3619               
3620                   return 0;
3621               
3622               err_free:
3623                   HeapFree(GetProcessHeap(), 0, iovec);
3624               
3625               err_close:
3626                   release_sock_fd( s, fd );
3627               
3628               error:
3629                   WARN(" -> ERROR %d\n", err);
3630                   WSASetLastError( err );
3631                   return SOCKET_ERROR;
3632               }
3633               
3634               /***********************************************************************
3635 cs130_tom 1.1  *              WSCInstallProvider             (WS2_32.88)
3636                */
3637               INT WINAPI WSCInstallProvider( const LPGUID lpProviderId,
3638                                              LPCWSTR lpszProviderDllPath,
3639                                              const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
3640                                              DWORD dwNumberOfEntries,
3641                                              LPINT lpErrno )
3642               {
3643                   FIXME("(%s, %s, %p, %ld, %p): stub !\n", debugstr_guid(lpProviderId),
3644                         debugstr_w(lpszProviderDllPath), lpProtocolInfoList,
3645                         dwNumberOfEntries, lpErrno);
3646                   *lpErrno = 0;
3647                   return 0;
3648               }
3649               
3650               
3651               /***********************************************************************
3652                *              WSCDeinstallProvider             (WS2_32.83)
3653                */
3654               INT WINAPI WSCDeinstallProvider(LPGUID lpProviderId, LPINT lpErrno)
3655               {
3656 cs130_tom 1.1     FIXME("(%s, %p): stub !\n", debugstr_guid(lpProviderId), lpErrno);
3657                   *lpErrno = 0;
3658                   return 0;
3659               }
3660               
3661               
3662               /***********************************************************************
3663                *              WSAAccept                        (WS2_32.26)
3664                */
3665               SOCKET WINAPI WSAAccept( SOCKET s, struct WS_sockaddr *addr, LPINT addrlen,
3666                              LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData)
3667               {
3668               
3669                      int ret = 0, size = 0;
3670                      WSABUF CallerId, CallerData, CalleeId, CalleeData;
3671                      /*        QOS SQOS, GQOS; */
3672                      GROUP g;
3673                      SOCKET cs;
3674                      SOCKADDR src_addr, dst_addr;
3675               
3676                      TRACE("Socket  %04x, sockaddr %p, addrlen %p, fnCondition %p, dwCallbackData %ld\n",
3677 cs130_tom 1.1                s, addr, addrlen, lpfnCondition, dwCallbackData);
3678               
3679               
3680                      size = sizeof(src_addr);
3681                      cs = WS_accept(s, &src_addr, &size);
3682               
3683                      if (cs == SOCKET_ERROR) return SOCKET_ERROR;
3684               
3685                      CallerId.buf = (char *)&src_addr;
3686                      CallerId.len = sizeof(src_addr);
3687               
3688                      CallerData.buf = NULL;
3689                      CallerData.len = (ULONG)NULL;
3690               
3691                      WS_getsockname(cs, &dst_addr, &size);
3692               
3693                      CalleeId.buf = (char *)&dst_addr;
3694                      CalleeId.len = sizeof(dst_addr);
3695               
3696               
3697                      ret = (*lpfnCondition)(&CallerId, &CallerData, NULL, NULL,
3698 cs130_tom 1.1                        &CalleeId, &CalleeData, &g, dwCallbackData);
3699               
3700                      switch (ret)
3701                      {
3702                              case CF_ACCEPT:
3703                                      if (addr && addrlen)
3704                                              addr = memcpy(addr, &src_addr, (*addrlen > size) ?  size : *addrlen );
3705                                      return cs;
3706                              case CF_DEFER:
3707                                      SERVER_START_REQ( set_socket_deferred )
3708                                      {
3709                                          req->handle = SOCKET2HANDLE(s);
3710                                          req->deferred = SOCKET2HANDLE(cs);
3711                                          if ( !wine_server_call_err ( req ) )
3712                                          {
3713                                              SetLastError( WSATRY_AGAIN );
3714                                              WS_closesocket( cs );
3715                                          }
3716                                      }
3717                                      SERVER_END_REQ;
3718                                      return SOCKET_ERROR;
3719 cs130_tom 1.1                case CF_REJECT:
3720                                      WS_closesocket(cs);
3721                                      SetLastError(WSAECONNREFUSED);
3722                                      return SOCKET_ERROR;
3723                              default:
3724                                      FIXME("Unknown return type from Condition function\n");
3725                                      SetLastError(WSAENOTSOCK);
3726                                      return SOCKET_ERROR;
3727                              }
3728               }
3729               
3730               /***********************************************************************
3731                *              WSADuplicateSocketA                      (WS2_32.32)
3732                */
3733               int WINAPI WSADuplicateSocketA( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOA lpProtocolInfo )
3734               {
3735                  HANDLE hProcess;
3736               
3737                  TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3738                  memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3739                  /* FIXME: WS_getsockopt(s, WS_SOL_SOCKET, SO_PROTOCOL_INFO, lpProtocolInfo, sizeof(*lpProtocolInfo)); */
3740 cs130_tom 1.1    /* I don't know what the real Windoze does next, this is a hack */
3741                  /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
3742                   * the target use the global duplicate, or we could copy a reference to us to the structure
3743                   * and let the target duplicate it from us, but let's do it as simple as possible */
3744                  hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3745                  DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3746                                  hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3747                                  0, FALSE, DUPLICATE_SAME_ACCESS);
3748                  CloseHandle(hProcess);
3749                  lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3750                  return 0;
3751               }
3752               
3753               /***********************************************************************
3754                *              WSADuplicateSocketW                      (WS2_32.33)
3755                */
3756               int WINAPI WSADuplicateSocketW( SOCKET s, DWORD dwProcessId, LPWSAPROTOCOL_INFOW lpProtocolInfo )
3757               {
3758                  HANDLE hProcess;
3759               
3760                  TRACE("(%d,%lx,%p)\n", s, dwProcessId, lpProtocolInfo);
3761 cs130_tom 1.1 
3762                  memset(lpProtocolInfo, 0, sizeof(*lpProtocolInfo));
3763                  hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
3764                  DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s),
3765                                  hProcess, (LPHANDLE)&lpProtocolInfo->dwCatalogEntryId,
3766                                  0, FALSE, DUPLICATE_SAME_ACCESS);
3767                  CloseHandle(hProcess);
3768                  lpProtocolInfo->dwServiceFlags4 = 0xff00ff00; /* magic */
3769                  return 0;
3770               }
3771               
3772               /***********************************************************************
3773                *              WSAInstallServiceClassA                  (WS2_32.48)
3774                */
3775               int WINAPI WSAInstallServiceClassA(LPWSASERVICECLASSINFOA info)
3776               {
3777                   FIXME("Request to install service %s\n",debugstr_a(info->lpszServiceClassName));
3778                   WSASetLastError(WSAEACCES);
3779                   return SOCKET_ERROR;
3780               }
3781               
3782 cs130_tom 1.1 /***********************************************************************
3783                *              WSAInstallServiceClassW                  (WS2_32.49)
3784                */
3785               int WINAPI WSAInstallServiceClassW(LPWSASERVICECLASSINFOW info)
3786               {
3787                   FIXME("Request to install service %s\n",debugstr_w(info->lpszServiceClassName));
3788                   WSASetLastError(WSAEACCES);
3789                   return SOCKET_ERROR;
3790               }
3791               
3792               /***********************************************************************
3793                *              WSARemoveServiceClass                    (WS2_32.70)
3794                */
3795               int WINAPI WSARemoveServiceClass(LPGUID info)
3796               {
3797                   FIXME("Request to remove service %p\n",info);
3798                   WSASetLastError(WSATYPE_NOT_FOUND);
3799                   return SOCKET_ERROR;
3800               }
3801               
3802               /***********************************************************************
3803 cs130_tom 1.1  *              WSAStringToAddressA                      (WS2_32.80)
3804                */
3805               INT WINAPI WSAStringToAddressA(LPSTR AddressString,
3806                                              INT AddressFamily,
3807                                              LPWSAPROTOCOL_INFOA lpProtocolInfo,
3808                                              LPSOCKADDR lpAddress,
3809                                              LPINT lpAddressLength)
3810               {
3811                   INT res=0;
3812                   LONG inetaddr;
3813                   LPSTR workBuffer=NULL,ptrPort;
3814               
3815                   TRACE( "(%s, %x, %p, %p, %p)\n", AddressString, AddressFamily, lpProtocolInfo,
3816                          lpAddress, lpAddressLength );
3817               
3818                   if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
3819               
3820                   if (AddressString)
3821                   {
3822                       workBuffer = HeapAlloc( GetProcessHeap(), 0, strlen(AddressString)+1 );
3823                       if (workBuffer)
3824 cs130_tom 1.1         {
3825                           strcpy(workBuffer,AddressString);
3826                           switch (AddressFamily)
3827                           {
3828                           case AF_INET:
3829                               /* caller wants to know the size of the socket buffer */
3830                               if (*lpAddressLength < sizeof(SOCKADDR_IN))
3831                               {
3832                                   *lpAddressLength = sizeof(SOCKADDR_IN);
3833                                   res = WSAEFAULT;
3834                               }
3835                               else
3836                               {
3837                                   /* caller wants to translate an AdressString into a SOCKADDR */
3838                                   if (lpAddress)
3839                                   {
3840                                       memset(lpAddress,0,sizeof(SOCKADDR_IN));
3841                                       ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET;
3842                                       ptrPort = strchr(workBuffer,':');
3843                                       if (ptrPort)
3844                                       {
3845 cs130_tom 1.1                             ((LPSOCKADDR_IN)lpAddress)->sin_port = (u_short)atoi(ptrPort+1);
3846                                           *ptrPort = '\0';
3847                                       }
3848                                       else
3849                                           ((LPSOCKADDR_IN)lpAddress)->sin_port = 0;
3850                                       inetaddr = inet_addr(workBuffer);
3851                                       if (inetaddr != INADDR_NONE)
3852                                       {
3853                                           ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr;
3854                                           res = 0;
3855                                       }
3856                                       else
3857                                           res = WSAEINVAL;
3858                                   }
3859                               }
3860                               if (lpProtocolInfo)
3861                                   FIXME("(%s, %x, %p, %p, %p) - ProtocolInfo not implemented!\n",
3862                                       AddressString, AddressFamily,
3863                                       lpProtocolInfo, lpAddress, lpAddressLength);
3864               
3865                               break;
3866 cs130_tom 1.1             default:
3867                               FIXME("(%s, %x, %p, %p, %p) - AddressFamiliy not implemented!\n",
3868                                   AddressString, AddressFamily,
3869                                   lpProtocolInfo, lpAddress, lpAddressLength);
3870                           }
3871                           HeapFree( GetProcessHeap(), 0, workBuffer );
3872                       }
3873                       else
3874                           res = WSA_NOT_ENOUGH_MEMORY;
3875                   }
3876                   else
3877                       res = WSAEINVAL;
3878               
3879                   if (!res) return 0;
3880                   WSASetLastError(res);
3881                   return SOCKET_ERROR;
3882               }
3883               
3884               /***********************************************************************
3885                *              WSAStringToAddressW                      (WS2_32.81)
3886                *
3887 cs130_tom 1.1  * Does anybody know if this functions allows to use hebrew/arabic/chinese... digits?
3888                * If this should be the case, it would be required to map these digits
3889                * to Unicode digits (0-9) using FoldString first.
3890                */
3891               INT WINAPI WSAStringToAddressW(LPWSTR AddressString,
3892                                              INT AddressFamily,
3893                                              LPWSAPROTOCOL_INFOW lpProtocolInfo,
3894                                              LPSOCKADDR lpAddress,
3895                                              LPINT lpAddressLength)
3896               {
3897                   INT sBuffer,res=0;
3898                   LPSTR workBuffer=NULL;
3899                   WSAPROTOCOL_INFOA infoA;
3900                   LPWSAPROTOCOL_INFOA lpProtoInfoA = NULL;
3901               
3902                   TRACE( "(%s, %x, %p, %p, %p)\n", debugstr_w(AddressString), AddressFamily, lpProtocolInfo,
3903                          lpAddress, lpAddressLength );
3904               
3905                   if (!lpAddressLength || !lpAddress) return SOCKET_ERROR;
3906               
3907                   /* if ProtocolInfo is available - convert to ANSI variant */
3908 cs130_tom 1.1     if (lpProtocolInfo)
3909                   {
3910                       lpProtoInfoA = &infoA;
3911                       memcpy( lpProtoInfoA, lpProtocolInfo, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
3912               
3913                       if (!WideCharToMultiByte( CP_ACP, 0, lpProtocolInfo->szProtocol, -1,
3914                                                 lpProtoInfoA->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL ))
3915                       {
3916                           WSASetLastError( WSAEINVAL);
3917                           return SOCKET_ERROR;
3918                       }
3919                   }
3920               
3921                   if (AddressString)
3922                   {
3923                       /* Translate AddressString to ANSI code page - assumes that only
3924                          standard digits 0-9 are used with this API call */
3925                       sBuffer = WideCharToMultiByte( CP_ACP, 0, AddressString, -1, NULL, 0, NULL, NULL );
3926                       workBuffer = HeapAlloc( GetProcessHeap(), 0, sBuffer );
3927               
3928                       if (workBuffer)
3929 cs130_tom 1.1         {
3930                           WideCharToMultiByte( CP_ACP, 0, AddressString, -1, workBuffer, sBuffer, NULL, NULL );
3931                           res = WSAStringToAddressA(workBuffer,AddressFamily,lpProtoInfoA,
3932                                                     lpAddress,lpAddressLength);
3933                           HeapFree( GetProcessHeap(), 0, workBuffer );
3934                           return res;
3935                       }
3936                       else
3937                           res = WSA_NOT_ENOUGH_MEMORY;
3938                   }
3939                   else
3940                       res = WSAEINVAL;
3941               
3942                   WSASetLastError(res);
3943                   return SOCKET_ERROR;
3944               }
3945               
3946               /***********************************************************************
3947                *              WSAAddressToStringA                      (WS2_32.27)
3948                *
3949                *  See WSAAddressToStringW
3950 cs130_tom 1.1  */
3951               INT WINAPI WSAAddressToStringA( LPSOCKADDR sockaddr, DWORD len,
3952                                               LPWSAPROTOCOL_INFOA info, LPSTR string,
3953                                               LPDWORD lenstr )
3954               {
3955                   INT size;
3956                   CHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
3957                   CHAR *p;
3958               
3959                   TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
3960               
3961                   if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
3962                   if (!string || !lenstr) return SOCKET_ERROR;
3963               
3964                   /* sin_family is garanteed to be the first u_short */
3965                   if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
3966               
3967                   sprintf( buffer, "%u.%u.%u.%u:%u",
3968                            (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
3969                            (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
3970                            (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
3971 cs130_tom 1.1              (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
3972                            ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
3973               
3974                   p = strchr( buffer, ':' );
3975                   if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
3976               
3977                   size = strlen( buffer );
3978               
3979                   if (*lenstr <  size)
3980                   {
3981                       *lenstr = size;
3982                       return SOCKET_ERROR;
3983                   }
3984               
3985                   strcpy( string, buffer );
3986                   return 0;
3987               }
3988               
3989               /***********************************************************************
3990                *              WSAAddressToStringW                      (WS2_32.28)
3991                *
3992 cs130_tom 1.1  * Convert a sockaddr address into a readable address string. 
3993                *
3994                * PARAMS
3995                *  sockaddr [I]    Pointer to a sockaddr structure.
3996                *  len      [I]    Size of the sockaddr structure.
3997                *  info     [I]    Pointer to a WSAPROTOCOL_INFOW structure (optional).
3998                *  string   [I/O]  Pointer to a buffer to receive the address string.
3999                *  lenstr   [I/O]  Size of the receive buffer in WCHARs.
4000                *
4001                * RETURNS
4002                *  Success: 0
4003                *  Failure: SOCKET_ERROR
4004                *
4005                * NOTES
4006                *  The 'info' parameter is ignored.
4007                *
4008                * BUGS
4009                *  Only supports AF_INET addresses.
4010                */
4011               INT WINAPI WSAAddressToStringW( LPSOCKADDR sockaddr, DWORD len,
4012                                               LPWSAPROTOCOL_INFOW info, LPWSTR string,
4013 cs130_tom 1.1                                 LPDWORD lenstr )
4014               {
4015                   INT size;
4016                   WCHAR buffer[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
4017                   static const WCHAR format[] = { '%','u','.','%','u','.','%','u','.','%','u',':','%','u',0 };
4018                   WCHAR *p;
4019               
4020                   TRACE( "(%p, %lx, %p, %p, %p)\n", sockaddr, len, info, string, lenstr );
4021               
4022                   if (!sockaddr || len < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
4023                   if (!string || !lenstr) return SOCKET_ERROR;
4024               
4025                   /* sin_family is garanteed to be the first u_short */
4026                   if (((SOCKADDR_IN *)sockaddr)->sin_family != AF_INET) return SOCKET_ERROR;
4027               
4028                   sprintfW( buffer, format,
4029                             (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 24 & 0xff),
4030                             (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 16 & 0xff),
4031                             (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) >> 8 & 0xff),
4032                             (unsigned int)(ntohl( ((SOCKADDR_IN *)sockaddr)->sin_addr.WS_s_addr ) & 0xff),
4033                             ntohs( ((SOCKADDR_IN *)sockaddr)->sin_port ) );
4034 cs130_tom 1.1 
4035                   p = strchrW( buffer, ':' );
4036                   if (!((SOCKADDR_IN *)sockaddr)->sin_port) *p = 0;
4037               
4038                   size = lstrlenW( buffer );
4039               
4040                   if (*lenstr <  size)
4041                   {
4042                       *lenstr = size;
4043                       return SOCKET_ERROR;
4044                   }
4045               
4046                   lstrcpyW( string, buffer );
4047                   return 0;
4048               }
4049               
4050               /***********************************************************************
4051                *              WSAEnumNameSpaceProvidersA                  (WS2_32.34)
4052                */
4053               INT WINAPI WSAEnumNameSpaceProvidersA( LPDWORD len, LPWSANAMESPACE_INFOA buffer )
4054               {
4055 cs130_tom 1.1     FIXME( "(%p %p) Stub!\n", len, buffer );
4056                   return 0;
4057               }
4058               
4059               /***********************************************************************
4060                *              WSAEnumNameSpaceProvidersW                  (WS2_32.35)
4061                */
4062               INT WINAPI WSAEnumNameSpaceProvidersW( LPDWORD len, LPWSANAMESPACE_INFOW buffer )
4063               {
4064                   FIXME( "(%p %p) Stub!\n", len, buffer );
4065                   return 0;
4066               }
4067               
4068               /***********************************************************************
4069                *              WSAGetQOSByName                             (WS2_32.41)
4070                */
4071               BOOL WINAPI WSAGetQOSByName( SOCKET s, LPWSABUF lpQOSName, LPQOS lpQOS )
4072               {
4073                   FIXME( "(0x%04x %p %p) Stub!\n", s, lpQOSName, lpQOS );
4074                   return FALSE;
4075               }
4076 cs130_tom 1.1 
4077               /***********************************************************************
4078                *              WSAGetServiceClassInfoA                     (WS2_32.42)
4079                */
4080               INT WINAPI WSAGetServiceClassInfoA( LPGUID provider, LPGUID service, LPDWORD len,
4081                                                   LPWSASERVICECLASSINFOA info )
4082               {
4083                   FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4084                          len, info );
4085                   WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4086                   return SOCKET_ERROR; 
4087               }
4088               
4089               /***********************************************************************
4090                *              WSAGetServiceClassInfoW                     (WS2_32.43)
4091                */
4092               INT WINAPI WSAGetServiceClassInfoW( LPGUID provider, LPGUID service, LPDWORD len,
4093                                                   LPWSASERVICECLASSINFOW info )
4094               {
4095                   FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service),
4096                          len, info );
4097 cs130_tom 1.1     WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4098                   return SOCKET_ERROR;
4099               }
4100               
4101               /***********************************************************************
4102                *              WSAGetServiceClassNameByClassIdA            (WS2_32.44)
4103                */
4104               INT WINAPI WSAGetServiceClassNameByClassIdA( LPGUID class, LPSTR service, LPDWORD len )
4105               {
4106                   FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4107                   WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4108                   return SOCKET_ERROR;
4109               }
4110               
4111               /***********************************************************************
4112                *              WSAGetServiceClassNameByClassIdW            (WS2_32.45)
4113                */
4114               INT WINAPI WSAGetServiceClassNameByClassIdW( LPGUID class, LPWSTR service, LPDWORD len )
4115               {
4116                   FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
4117                   WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4118 cs130_tom 1.1     return SOCKET_ERROR;
4119               }
4120               
4121               /***********************************************************************
4122                *              WSALookupServiceBeginA                       (WS2_32.59)
4123                */
4124               INT WINAPI WSALookupServiceBeginA( LPWSAQUERYSETA lpqsRestrictions,
4125                                                  DWORD dwControlFlags,
4126                                                  LPHANDLE lphLookup)
4127               {
4128                   FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4129                           lphLookup);
4130                   WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4131                   return SOCKET_ERROR;
4132               }
4133               
4134               /***********************************************************************
4135                *              WSALookupServiceBeginW                       (WS2_32.60)
4136                */
4137               INT WINAPI WSALookupServiceBeginW( LPWSAQUERYSETW lpqsRestrictions,
4138                                                  DWORD dwControlFlags,
4139 cs130_tom 1.1                                    LPHANDLE lphLookup)
4140               {
4141                   FIXME("(%p 0x%08lx %p) Stub!\n", lpqsRestrictions, dwControlFlags,
4142                           lphLookup);
4143                   WSASetLastError(WSA_NOT_ENOUGH_MEMORY);
4144                   return SOCKET_ERROR;
4145               }
4146               
4147               /***********************************************************************
4148                *              WSALookupServiceBeginW                       (WS2_32.61)
4149                */
4150               INT WINAPI WSALookupServiceEnd( HANDLE lookup )
4151               {
4152                   FIXME("(%p) Stub!\n", lookup );
4153                   return 0;
4154               }
4155               
4156               /***********************************************************************
4157                *              WSALookupServiceNextA                       (WS2_32.62)
4158                */
4159               INT WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETA results )
4160 cs130_tom 1.1 {
4161                   FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4162                   return 0;
4163               }
4164               
4165               /***********************************************************************
4166                *              WSALookupServiceNextW                       (WS2_32.63)
4167                */
4168               INT WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, LPDWORD len, LPWSAQUERYSETW results )
4169               {
4170                   FIXME( "(%p 0x%08lx %p %p) Stub!\n", lookup, flags, len, results );
4171                   return 0;
4172               }
4173               
4174               /***********************************************************************
4175                *              WSANtohl                                   (WS2_32.64)
4176                */
4177               INT WINAPI WSANtohl( SOCKET s, u_long netlong, u_long* lphostlong )
4178               {
4179                   TRACE( "(0x%04x 0x%08lx %p)\n", s, netlong, lphostlong );
4180               
4181 cs130_tom 1.1     if (!lphostlong) return WSAEFAULT;
4182               
4183                   *lphostlong = ntohl( netlong );
4184                   return 0;
4185               }
4186               
4187               /***********************************************************************
4188                *              WSANtohs                                   (WS2_32.65)
4189                */
4190               INT WINAPI WSANtohs( SOCKET s, u_short netshort, u_short* lphostshort )
4191               {
4192                   TRACE( "(0x%04x 0x%08x %p)\n", s, netshort, lphostshort );
4193               
4194                   if (!lphostshort) return WSAEFAULT;
4195               
4196                   *lphostshort = ntohs( netshort );
4197                   return 0;
4198               }
4199               
4200               /***********************************************************************
4201                *              WSAProviderConfigChange                     (WS2_32.66)
4202 cs130_tom 1.1  */
4203               INT WINAPI WSAProviderConfigChange( LPHANDLE handle, LPWSAOVERLAPPED overlapped,
4204                                                   LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
4205               {
4206                   FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
4207                   return SOCKET_ERROR;
4208               }
4209               
4210               /***********************************************************************
4211                *              WSARecvDisconnect                           (WS2_32.68)
4212                */
4213               INT WINAPI WSARecvDisconnect( SOCKET s, LPWSABUF disconnectdata )
4214               {
4215                   TRACE( "(0x%04x %p)\n", s, disconnectdata ); 
4216               
4217                   return WS_shutdown( s, 0 );
4218               }
4219               
4220               /***********************************************************************
4221                *              WSASetServiceA                              (WS2_32.76)
4222                */
4223 cs130_tom 1.1 INT WINAPI WSASetServiceA( LPWSAQUERYSETA query, WSAESETSERVICEOP operation, DWORD flags )
4224               {
4225                   FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4226                   return 0;
4227               }
4228               
4229               /***********************************************************************
4230                *              WSASetServiceW                              (WS2_32.77)
4231                */
4232               INT WINAPI WSASetServiceW( LPWSAQUERYSETW query, WSAESETSERVICEOP operation, DWORD flags )
4233               {
4234                   FIXME( "(%p 0x%08x 0x%08lx) Stub!\n", query, operation, flags );
4235                   return 0;
4236               }
4237               
4238               /***********************************************************************
4239                *              WSCEnableNSProvider                         (WS2_32.84)
4240                */
4241               INT WINAPI WSCEnableNSProvider( LPGUID provider, BOOL enable )
4242               {
4243                   FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
4244 cs130_tom 1.1     return 0;
4245               }
4246               
4247               /***********************************************************************
4248                *              WSCGetProviderPath                          (WS2_32.86)
4249                */
4250               INT WINAPI WSCGetProviderPath( LPGUID provider, LPWSTR path, LPINT len, LPINT errno )
4251               {
4252                   FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errno );
4253               
4254                   if (!errno || !provider || !len) return WSAEFAULT;
4255               
4256                   *errno = WSAEINVAL;
4257                   return SOCKET_ERROR;
4258               }
4259               
4260               /***********************************************************************
4261                *              WSCInstallNameSpace                         (WS2_32.87)
4262                */
4263               INT WINAPI WSCInstallNameSpace( LPWSTR identifier, LPWSTR path, DWORD namespace,
4264                                               DWORD version, LPGUID provider )
4265 cs130_tom 1.1 {
4266                   FIXME( "(%s %s 0x%08lx 0x%08lx %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
4267                          namespace, version, debugstr_guid(provider) );
4268                   return 0;
4269               }
4270               
4271               /***********************************************************************
4272                *              WSCUnInstallNameSpace                       (WS2_32.89)
4273                */
4274               INT WINAPI WSCUnInstallNameSpace( LPGUID lpProviderId )
4275               {
4276                   FIXME("(%p) Stub!\n", lpProviderId);
4277                   return NO_ERROR;
4278               }
4279               
4280               /***********************************************************************
4281                *              WSCWriteProviderOrder                       (WS2_32.91)
4282                */
4283               INT WINAPI WSCWriteProviderOrder( LPDWORD entry, DWORD number )
4284               {
4285                   FIXME("(%p 0x%08lx) Stub!\n", entry, number);
4286 cs130_tom 1.1     return 0;
4287               }

Rizwan Kassim
Powered by
ViewCVS 0.9.2