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

Rizwan Kassim
Powered by
ViewCVS 0.9.2