hnetcfg: Make NetFwOpenPort_create() static.
[wine] / dlls / wsock32 / socket.c
index 3ed74ee..74df2e3 100644 (file)
  * WSOCK32 specific functions
  *
  * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
+ * Copyright (C) 2003 Juan Lang.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+
 #include "config.h"
+#include <stdarg.h>
 
-#include <sys/types.h>
 #include "windef.h"
 #include "winbase.h"
-#include "debugtools.h"
+#include "wine/debug.h"
 #include "winsock2.h"
 #include "winnt.h"
 #include "wscontrol.h"
-#include <ctype.h>
-#include <sys/ioctl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#ifdef HAVE_SYS_SOCKIO_H
-# include <sys/sockio.h>
-#endif
-#ifdef HAVE_NET_IF_H
-# include <net/if.h>
-#endif
+#include "iphlpapi.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(winsock);
+
+/* internal remapper function for the IP_ constants */
+static INT _remap_optname(INT level, INT optname)
+{
+  TRACE("level=%d, optname=%d\n", level, optname);
+  if (level == IPPROTO_IP) {
+    switch (optname) {       /***** from value *****/
+      case 2: return 9;      /* IP_MULTICAST_IF    */
+      case 3: return 10;     /* IP_MULTICAST_TTL   */
+      case 4: return 11;     /* IP_MULTICAST_LOOP  */
+      case 5: return 12;     /* IP_ADD_MEMBERSHIP  */
+      case 6: return 13;     /* IP_DROP_MEMBERSHIP */
+      case 7: return 4;      /* IP_TTL             */
+      case 8: return 3;      /* IP_TOS             */
+      case 9: return 14;     /* IP_DONTFRAGMENT    */
+      default: FIXME("Unknown optname %d, can't remap!\n", optname); return optname; 
+    }
+  } else {
+    /* don't need to do anything */
+    return optname;
+  }
+}
 
-DEFAULT_DEBUG_CHANNEL(winsock);
+/***********************************************************************
+ *             setsockopt              (WSOCK32.21)
+ *
+ * We have these forwarders because, for reasons unknown to us mere mortals,
+ * the values of the IP_ constants changed between winsock.h and winsock2.h.
+ * So, we need to remap them here.
+ */
+INT WINAPI WS1_setsockopt(SOCKET s, INT level, INT optname, char *optval, INT optlen)
+{
+  return setsockopt(s, level, _remap_optname(level, optname), optval, optlen);
+}
 
-static INT (WINAPI *WS2_recv)(SOCKET s, char *buf, INT len, INT flags);
+/***********************************************************************
+ *             getsockopt              (WSOCK32.7)
+ */
+INT WINAPI WS1_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen)
+{
+  return getsockopt(s, level, _remap_optname(level, optname), optval, optlen);
+}
 
 /***********************************************************************
- *      WsControl()
+ *             WsControl (WSOCK32.1001)
  *
- * WsControl seems to be an undocumented Win95 function. A lot of 
+ * WsControl seems to be an undocumented Win95 function. A lot of
  * discussion about WsControl can be found on the net, e.g.
  * Subject:      Re: WSOCK32.DLL WsControl Exported Function
  * From:         "Peter Rindfuss" <rindfuss-s@medea.wz-berlin.de>
  * Date:         1997/08/17
  *
- * WSCNTL_TCPIP_QUERY_INFO option is partially implemeted based
- * on observing the behaviour of WsControl with an app in 
+ * The WSCNTL_TCPIP_QUERY_INFO option is partially implemented based
+ * on observing the behaviour of WsControl with an app in
  * Windows 98.  It is not fully implemented, and there could
  * be (are?) errors due to incorrect assumptions made.
  *
  *
  * WsControl returns WSCTL_SUCCESS on success.
- * STATUS_BUFFER_TOO_SMALL is returned if the output buffer length
- * (*pcbResponseInfoLen) is too small, otherwise errors return -1.
- *
- * It doesn't seem to generate errors that can be retrieved by 
- * WSAGetLastError().
+ * ERROR_LOCK_VIOLATION is returned if the output buffer length
+ * (*pcbResponseInfoLen) is too small.  This is an unusual error code, but
+ * it matches Win98's behavior.  Other errors come from winerror.h, not from
+ * winsock.h.  Again, this is to match Win98 behavior.
  *
  */
 
-DWORD WINAPI WsControl(DWORD protocoll,
+DWORD WINAPI WsControl(DWORD protocol,
                        DWORD action,
                        LPVOID pRequestInfo,
                        LPDWORD pcbRequestInfoLen,
                        LPVOID pResponseInfo,
-                       LPDWORD pcbResponseInfoLen) 
+                       LPDWORD pcbResponseInfoLen)
 {
+
    /* Get the command structure into a pointer we can use,
       rather than void */
-   TDIObjectID *pcommand = (TDIObjectID *)pRequestInfo;
-  
-   TRACE ("   WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n",
-          pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance,
-          pcommand->toi_class, pcommand->toi_type );
-  
+   TDIObjectID *pcommand = pRequestInfo;
+
+   /* validate input parameters.  Error codes are from winerror.h, not from
+    * winsock.h.  pcbResponseInfoLen is apparently allowed to be NULL for some
+    * commands, since winipcfg.exe fails if we ensure it's non-NULL in every
+    * case.
+    */
+   if (protocol != IPPROTO_TCP) return ERROR_INVALID_PARAMETER;
+   if (!pcommand) return ERROR_INVALID_PARAMETER;
+   if (!pcbRequestInfoLen) return ERROR_INVALID_ACCESS;
+   if (*pcbRequestInfoLen < sizeof(TDIObjectID)) return ERROR_INVALID_ACCESS;
+   if (!pResponseInfo) return ERROR_INVALID_PARAMETER;
+   if (pcommand->toi_type != INFO_TYPE_PROVIDER) return ERROR_INVALID_PARAMETER;
 
+   TRACE ("   WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n",
+      pcommand->toi_id, pcommand->toi_entity.tei_entity,
+      pcommand->toi_entity.tei_instance,
+      pcommand->toi_class, pcommand->toi_type );
 
-   switch (action) 
+   switch (action)
+   {
+   case WSCNTL_TCPIP_QUERY_INFO:
    {
-      case WSCNTL_TCPIP_QUERY_INFO: 
+      if (pcommand->toi_class != INFO_CLASS_GENERIC &&
+       pcommand->toi_class != INFO_CLASS_PROTOCOL)
+      {
+         ERR("Unexpected class %ld for WSCNTL_TCPIP_QUERY_INFO\n",
+          pcommand->toi_class);
+         return ERROR_BAD_ENVIRONMENT;
+      }
+
+      switch (pcommand->toi_id)
       {
-         switch (pcommand->toi_id)
+         /* ENTITY_LIST_ID gets the list of "entity IDs", where an entity
+            may represent an interface, or a datagram service, or address
+            translation, or other fun things.  Typically an entity ID represents
+            a class of service, which is further queried for what type it is.
+            Different types will then have more specific queries defined.
+         */
+         case ENTITY_LIST_ID:
          {
-            /* 
-               ENTITY_LIST_ID seems to get number of adapters in the system.
-               (almost like an index to be used when calling other WsControl options)
-            */
-            case ENTITY_LIST_ID: 
+            TDIEntityID *baseptr = pResponseInfo;
+            DWORD numInt, i, ifTable, spaceNeeded;
+            PMIB_IFTABLE table;
+
+            if (!pcbResponseInfoLen)
+               return ERROR_BAD_ENVIRONMENT;
+            if (pcommand->toi_class != INFO_CLASS_GENERIC)
             {
-               TDIEntityID *baseptr = pResponseInfo;
-               int numInt = 0, i;
-
-               if (pcommand->toi_class != INFO_CLASS_GENERIC &&
-                   pcommand->toi_type != INFO_TYPE_PROVIDER) 
-               { 
-                  FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
-                       pcommand->toi_class, pcommand->toi_type);
-                  return (WSAEOPNOTSUPP); 
-               }
-           
-               numInt = WSCNTL_GetInterfaceCount(); 
-               if (numInt < 0)
-               {
-                  ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
-                  return (-1); 
-               }
+               FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx\n",
+                    pcommand->toi_class);
+               return (ERROR_BAD_ENVIRONMENT);
+            }
 
-               if (*pcbResponseInfoLen < sizeof(TDIEntityID)*(numInt*2) ) 
-               {
-                  return (STATUS_BUFFER_TOO_SMALL);
-               }
-           
-               /* 0 it out first */
-               memset(baseptr, 0, sizeof(TDIEntityID)*(numInt*2)); 
-               
-               for (i=0; i<numInt; i++)
-               {
-                  /* tei_instance is an network interface identifier.
-                     I'm not quite sure what the difference is between tei_entity values of 
-                     CL_NL_ENTITY and IF_ENTITY */
-                  baseptr->tei_entity = CL_NL_ENTITY;  baseptr->tei_instance = i; baseptr++;
-                  baseptr->tei_entity = IF_ENTITY;     baseptr->tei_instance = i; baseptr++; 
-               }
+            GetNumberOfInterfaces(&numInt);
+            spaceNeeded = sizeof(TDIEntityID) * (numInt * 2 + 3);
 
-               /* Calculate size of out buffer */
-               *pcbResponseInfoLen = sizeof(TDIEntityID)*(numInt*2);
-            
-               break;
+            if (*pcbResponseInfoLen < spaceNeeded)
+               return (ERROR_LOCK_VIOLATION);
+
+            ifTable = 0;
+            GetIfTable(NULL, &ifTable, FALSE);
+            table = HeapAlloc( GetProcessHeap(), 0, ifTable );
+            if (!table)
+               return ERROR_NOT_ENOUGH_MEMORY;
+            GetIfTable(table, &ifTable, FALSE);
+
+            spaceNeeded = sizeof(TDIEntityID) * (table->dwNumEntries + 4);
+            if (*pcbResponseInfoLen < spaceNeeded)
+            {
+               HeapFree( GetProcessHeap(), 0, table );
+               return ERROR_LOCK_VIOLATION;
             }
-          
-          
-            /* ENTITY_TYPE_ID is used to obtain simple information about a 
-               network card, such as MAC Address, description, interface type,
-               number of network addresses, etc. */
-            case ENTITY_TYPE_ID:  /* ALSO: IP_MIB_STATS_ID */
+
+            memset(baseptr, 0, spaceNeeded);
+
+            for (i = 0; i < table->dwNumEntries; i++)
             {
-               if (pcommand->toi_class == INFO_CLASS_GENERIC && pcommand->toi_type == INFO_TYPE_PROVIDER) 
+               /* Return IF_GENERIC and CL_NL_ENTITY on every interface, and
+                * AT_ENTITY, CL_TL_ENTITY, and CO_TL_ENTITY on the first
+                * interface.  MS returns them only on the loopback interface,
+                * but it doesn't seem to matter.
+                */
+               if (i == 0)
                {
-                  if (pcommand->toi_entity.tei_entity == IF_ENTITY)
-                  {
-                     * ((ULONG *)pResponseInfo) = IF_MIB; 
-
-                     /* Calculate size of out buffer */
-                     *pcbResponseInfoLen = sizeof (ULONG);
+                  baseptr->tei_entity = CO_TL_ENTITY;
+                  baseptr->tei_instance = table->table[i].dwIndex;
+                  baseptr++;
+                  baseptr->tei_entity = CL_TL_ENTITY;
+                  baseptr->tei_instance = table->table[i].dwIndex;
+                  baseptr++;
+                  baseptr->tei_entity = AT_ENTITY;
+                  baseptr->tei_instance = table->table[i].dwIndex;
+                  baseptr++;
+               }
+               baseptr->tei_entity = CL_NL_ENTITY;
+               baseptr->tei_instance = table->table[i].dwIndex;
+               baseptr++;
+               baseptr->tei_entity = IF_GENERIC;
+               baseptr->tei_instance = table->table[i].dwIndex;
+               baseptr++;
+            }
 
-                  }
-                  else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY) 
-                  {
-                     * ((ULONG *)pResponseInfo) = CL_NL_IP;  
+            *pcbResponseInfoLen = spaceNeeded;
+            HeapFree( GetProcessHeap(), 0, table );
+            break;
+         }
 
-                     /* Calculate size of out buffer */
-                     *pcbResponseInfoLen = sizeof (ULONG); 
-                  }
+         /* Returns MIB-II statistics for an interface */
+         case ENTITY_TYPE_ID:
+            switch (pcommand->toi_entity.tei_entity)
+            {
+            case IF_GENERIC:
+               if (pcommand->toi_class == INFO_CLASS_GENERIC)
+               {
+                  if (!pcbResponseInfoLen)
+                     return ERROR_BAD_ENVIRONMENT;
+                  *((ULONG *)pResponseInfo) = IF_MIB;
+                  *pcbResponseInfoLen = sizeof(ULONG);
                }
-               else if (pcommand->toi_class == INFO_CLASS_PROTOCOL &&
-                        pcommand->toi_type == INFO_TYPE_PROVIDER)
+               else if (pcommand->toi_class == INFO_CLASS_PROTOCOL)
                {
-                  if (pcommand->toi_entity.tei_entity == IF_ENTITY)
-                  {
-                     /* In this case, we are requesting specific information about a 
-                        a particular network adapter. (MAC Address, speed, data transmitted/received,
-                        etc.)
-                     */ 
-                     IFEntry *IntInfo = (IFEntry *) pResponseInfo;
-                     char ifName[512];
-                     struct ifreq ifInfo;
-                     int sock;
-
-                     
-                     if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
-                     {
-                        ERR ("Unable to parse /proc filesystem!\n");
-                        return (-1);
-                     }
-               
-                     /* Get a socket so that we can use ioctl */
-                     if ( (sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
-                     {
-                        ERR ("Error creating socket!\n");
-                        return (-1);
-                     }
-                   
-                     /* 0 out return structure first */
-                     memset (IntInfo, 0, sizeof(IFEntry));
-                     
-                     /* Interface ID */
-                     IntInfo->if_index = pcommand->toi_entity.tei_instance;
-                     
-                     /* MAC Address - Let's try to do this in a cross-platform way... */
-                     #if defined(SIOCGIFHWADDR) /* Linux */
-                        strcpy(ifInfo.ifr_name, ifName);
-                        if (ioctl(sock, SIOCGIFHWADDR, &ifInfo) < 0)
-                        {
-                           ERR ("Error obtaining MAC Address!\n");
-                           close(sock);
-                           return (-1);
-                        }
-                        else
-                        {
-                           /* FIXME: Is it correct to assume size of 6? */
-                           memcpy(IntInfo->if_physaddr, ifInfo.ifr_hwaddr.sa_data, 6);
-                           IntInfo->if_physaddrlen=6;
-                        }
-                     #elif defined(SIOCGENADDR) /* Solaris */
-                        if (ioctl(sock, SIOCGENADDR, &ifInfo) < 0)
-                        {
-                           ERR ("Error obtaining MAC Address!\n");
-                           close(sock);
-                           return (-1);
-                        }
-                        else
-                        {
-                           /* FIXME: Is it correct to assume size of 6? */
-                          memcpy(IntInfo->if_physaddr, ifInfo.ifr_enaddr, 6);
-                           IntInfo->if_physaddrlen=6;
-                        }
-                     #else
-                        memset (IntInfo->if_physaddr, 0, 6);
-                        ERR ("Unable to determine MAC Address on your platform!\n");
-                     #endif
-
-                     
-                     /* Interface name and length */
-                     strcpy (IntInfo->if_descr, ifName);
-                     IntInfo->if_descrlen= strlen (IntInfo->if_descr);
-                     
-                     /* Obtain bytes transmitted/received for interface */
-                     if ( (WSCNTL_GetTransRecvStat(pcommand->toi_entity.tei_instance, 
-                           &IntInfo->if_inoctets, &IntInfo->if_outoctets)) < 0)
-                     {
-                        ERR ("Error obtaining transmit/receive stats for the network interface!\n");
-                        close(sock);
-                        return (-1);
-                     }
-                     
-                     
-                     /* FIXME: How should the below be properly calculated? ******************/
-                     IntInfo->if_type =  0x6; /* Ethernet (?) */
-                    IntInfo->if_speed = 1000000; /* Speed of interface (bits per second?) */
-                     /************************************************************************/
-
-                     close(sock);
-                     *pcbResponseInfoLen = sizeof (IFEntry) + IntInfo->if_descrlen; 
-                  }
-                  else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY) 
+                  MIB_IFROW row;
+                  DWORD index = pcommand->toi_entity.tei_instance, ret;
+                  DWORD size = sizeof(row) - sizeof(row.wszName) -
+                   sizeof(row.bDescr);
+
+                  if (!pcbResponseInfoLen)
+                     return ERROR_BAD_ENVIRONMENT;
+                  if (*pcbResponseInfoLen < size)
+                     return (ERROR_LOCK_VIOLATION);
+                  row.dwIndex = index;
+                  ret = GetIfEntry(&row);
+                  if (ret != NO_ERROR)
                   {
-                     IPSNMPInfo *infoStruc = (IPSNMPInfo *) pResponseInfo;
-                     int numInt;
-                     
-                     /* This case is used to obtain general statistics about the 
-                        network */
-                     
-                     if (*pcbResponseInfoLen < sizeof(IPSNMPInfo) )
-                     {
-                        return (STATUS_BUFFER_TOO_SMALL);
-                     }
-                     else
-                     {
-                        /* 0 it out first */
-                        memset(infoStruc, 0, sizeof(IPSNMPInfo));
-            
-                        /* Get the number of interfaces */
-                        numInt = WSCNTL_GetInterfaceCount(); 
-                        if (numInt < 0)
-                        {
-                           ERR ("Unable to open /proc filesystem to determine number of network interfaces!\n");
-                           return (-1); 
-                        }
-
-                        infoStruc->ipsi_numif           = numInt; /* # of interfaces */
-                        infoStruc->ipsi_numaddr         = numInt; /* # of addresses */
-                        infoStruc->ipsi_numroutes       = numInt; /* # of routes ~ FIXME - Is this right? */
-
-                        /* FIXME: How should the below be properly calculated? ******************/
-                        infoStruc->ipsi_forwarding      = 0x0;
-                        infoStruc->ipsi_defaultttl      = 0x0;
-                        infoStruc->ipsi_inreceives      = 0x0;
-                        infoStruc->ipsi_inhdrerrors     = 0x0;
-                        infoStruc->ipsi_inaddrerrors    = 0x0;
-                        infoStruc->ipsi_forwdatagrams   = 0x0;
-                        infoStruc->ipsi_inunknownprotos = 0x0;
-                        infoStruc->ipsi_indiscards      = 0x0;
-                        infoStruc->ipsi_indelivers      = 0x0;
-                        infoStruc->ipsi_outrequests     = 0x0;
-                        infoStruc->ipsi_routingdiscards = 0x0;
-                        infoStruc->ipsi_outdiscards     = 0x0;
-                        infoStruc->ipsi_outnoroutes     = 0x0;
-                        infoStruc->ipsi_reasmtimeout    = 0x0;
-                        infoStruc->ipsi_reasmreqds      = 0x0;
-                        infoStruc->ipsi_reasmoks        = 0x0;
-                        infoStruc->ipsi_reasmfails      = 0x0;
-                        infoStruc->ipsi_fragoks         = 0x0;
-                        infoStruc->ipsi_fragfails       = 0x0;
-                        infoStruc->ipsi_fragcreates     = 0x0;
-                        /************************************************************************/
-                      
-                        /* Calculate size of out buffer */
-                        *pcbResponseInfoLen = sizeof(IPSNMPInfo);
-                     }
+                     /* FIXME: Win98's arp.exe insists on querying index 1 for
+                      * its MIB-II stats, regardless of the tei_instances
+                      * returned in the ENTITY_LIST query above.  If the query
+                      * fails, arp.exe fails.  So, I do this hack return value
+                      * if index is 1 and the query failed just to get arp.exe
+                      * to continue.
+                      */
+                     if (index == 1)
+                        return NO_ERROR;
+                     ERR ("Error retrieving data for interface index %u\n",
+                      index);
+                     return ret;
                   }
+                  size = sizeof(row) - sizeof(row.wszName) -
+                   sizeof(row.bDescr) + row.dwDescrLen;
+                  if (*pcbResponseInfoLen < size)
+                     return (ERROR_LOCK_VIOLATION);
+                  memcpy(pResponseInfo, &row.dwIndex, size);
+                  *pcbResponseInfoLen = size;
                }
-               else
-               {
-                  FIXME ("Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx\n",
-                       pcommand->toi_class, pcommand->toi_type);
-                  
-                  return (WSAEOPNOTSUPP); 
-               }
-
                break;
-            }
-
 
-            /* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a 
-               particular network adapter */
-            case IP_MIB_ADDRTABLE_ENTRY_ID: 
-            {
-               IPAddrEntry *baseIPInfo = (IPAddrEntry *) pResponseInfo;
-               char ifName[512];
-               struct ifreq ifInfo;
-               int sock;
-
-               if (*pcbResponseInfoLen < sizeof(IPAddrEntry))
+            /* Returns address-translation related data.  In our case, this is
+             * ARP.
+             */
+            case AT_ENTITY:
+               if (pcommand->toi_class == INFO_CLASS_GENERIC)
                {
-                  return (STATUS_BUFFER_TOO_SMALL); 
+                  if (!pcbResponseInfoLen)
+                     return ERROR_BAD_ENVIRONMENT;
+                  *((ULONG *)pResponseInfo) = AT_ARP;
+                  *pcbResponseInfoLen = sizeof(ULONG);
                }
-               
-               if (!WSCNTL_GetInterfaceName(pcommand->toi_entity.tei_instance, ifName))
+               else if (pcommand->toi_class == INFO_CLASS_PROTOCOL)
                {
-                  ERR ("Unable to parse /proc filesystem!\n");
-                  return (-1);
+                  PMIB_IPNETTABLE table;
+                  DWORD size;
+                  PULONG output = pResponseInfo;
+
+                  if (!pcbResponseInfoLen)
+                     return ERROR_BAD_ENVIRONMENT;
+                  if (*pcbResponseInfoLen < sizeof(ULONG) * 2)
+                     return (ERROR_LOCK_VIOLATION);
+                  GetIpNetTable(NULL, &size, FALSE);
+                  table = HeapAlloc( GetProcessHeap(), 0, size );
+                  if (!table)
+                     return ERROR_NOT_ENOUGH_MEMORY;
+                  GetIpNetTable(table, &size, FALSE);
+                  /* FIXME: I don't understand the meaning of the ARP output
+                   * very well, but it seems to indicate how many ARP entries
+                   * exist.  I don't know whether this should reflect the
+                   * number per interface, as I'm only testing with a single
+                   * interface.  So, I lie and say all ARP entries exist on
+                   * a single interface--the first one that appears in the
+                   * ARP table.
+                   */
+                  *(output++) = table->dwNumEntries;
+                  *output = table->table[0].dwIndex;
+                  HeapFree( GetProcessHeap(), 0, table );
+                  *pcbResponseInfoLen = sizeof(ULONG) * 2;
                }
-               
-               
-               /* Get a socket so we can use ioctl */
-               if ( (sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
+               break;
+
+            /* Returns connectionless network layer statistics--in our case,
+             * this is IP.
+             */
+            case CL_NL_ENTITY:
+               if (pcommand->toi_class == INFO_CLASS_GENERIC)
                {
-                  ERR ("Error creating socket!\n");
-                  return (-1);
+                  if (!pcbResponseInfoLen)
+                     return ERROR_BAD_ENVIRONMENT;
+                  *((ULONG *)pResponseInfo) = CL_NL_IP;
+                  *pcbResponseInfoLen = sizeof(ULONG);
                }
-              
-               /* 0 it out first */
-               memset(baseIPInfo, 0, sizeof(IPAddrEntry) );
-               
-               /* Interface Id */
-               baseIPInfo->iae_index     = pcommand->toi_entity.tei_instance;
-               
-               /* IP Address */
-               strcpy (ifInfo.ifr_name, ifName);
-              ifInfo.ifr_addr.sa_family = AF_INET;
-              if (ioctl(sock, SIOCGIFADDR, &ifInfo) < 0) 
+               else if (pcommand->toi_class == INFO_CLASS_PROTOCOL)
                {
-                  baseIPInfo->iae_addr = 0x0;
+                  if (!pcbResponseInfoLen)
+                     return ERROR_BAD_ENVIRONMENT;
+                  if (*pcbResponseInfoLen < sizeof(MIB_IPSTATS))
+                     return ERROR_LOCK_VIOLATION;
+                  GetIpStatistics(pResponseInfo);
+
+                  *pcbResponseInfoLen = sizeof(MIB_IPSTATS);
                }
-               else
+               break;
+
+            /* Returns connectionless transport layer statistics--in our case,
+             * this is UDP.
+             */
+            case CL_TL_ENTITY:
+               if (pcommand->toi_class == INFO_CLASS_GENERIC)
                {
-                  struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
-                  baseIPInfo->iae_addr = ipTemp->sin_addr.S_un.S_addr;
+                  if (!pcbResponseInfoLen)
+                     return ERROR_BAD_ENVIRONMENT;
+                  *((ULONG *)pResponseInfo) = CL_TL_UDP;
+                  *pcbResponseInfoLen = sizeof(ULONG);
                }
-               
-               /* Broadcast Address */
-               strcpy (ifInfo.ifr_name, ifName);
-              if (ioctl(sock, SIOCGIFBRDADDR, &ifInfo) < 0)
+               else if (pcommand->toi_class == INFO_CLASS_PROTOCOL)
                {
-                  baseIPInfo->iae_bcastaddr = 0x0;
+                  if (!pcbResponseInfoLen)
+                     return ERROR_BAD_ENVIRONMENT;
+                  if (*pcbResponseInfoLen < sizeof(MIB_UDPSTATS))
+                     return ERROR_LOCK_VIOLATION;
+                  GetUdpStatistics(pResponseInfo);
+                  *pcbResponseInfoLen = sizeof(MIB_UDPSTATS);
                }
-              else
+               break;
+
+            /* Returns connection-oriented transport layer statistics--in our
+             * case, this is TCP.
+             */
+            case CO_TL_ENTITY:
+               if (pcommand->toi_class == INFO_CLASS_GENERIC)
                {
-                  struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_broadaddr;
-                  baseIPInfo->iae_bcastaddr = ipTemp->sin_addr.S_un.S_addr; 
+                  if (!pcbResponseInfoLen)
+                     return ERROR_BAD_ENVIRONMENT;
+                  *((ULONG *)pResponseInfo) = CO_TL_TCP;
+                  *pcbResponseInfoLen = sizeof(ULONG);
                }
-
-               /* Subnet Mask */
-              strcpy(ifInfo.ifr_name, ifName);
-              if (ioctl(sock, SIOCGIFNETMASK, &ifInfo) < 0)
+               else if (pcommand->toi_class == INFO_CLASS_PROTOCOL)
                {
-                  baseIPInfo->iae_mask = 0x0;
-              }
-               else
-              {
-                  /* Trying to avoid some compile problems across platforms.
-                     (Linux, FreeBSD, Solaris...) */
-                  #ifndef ifr_netmask
-                     #ifndef ifr_addr
-                        baseIPInfo->iae_mask = 0;
-                        ERR ("Unable to determine Netmask on your platform!\n");
-                     #else
-                        struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_addr;
-                        baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr; 
-                     #endif
-                  #else  
-                     struct ws_sockaddr_in *ipTemp = (struct ws_sockaddr_in *)&ifInfo.ifr_netmask;
-                     baseIPInfo->iae_mask = ipTemp->sin_addr.S_un.S_addr; 
-                  #endif
+                  if (!pcbResponseInfoLen)
+                     return ERROR_BAD_ENVIRONMENT;
+                  if (*pcbResponseInfoLen < sizeof(MIB_TCPSTATS))
+                     return ERROR_LOCK_VIOLATION;
+                  GetTcpStatistics(pResponseInfo);
+                  *pcbResponseInfoLen = sizeof(MIB_TCPSTATS);
                }
-
-               /* FIXME: How should the below be properly calculated? ******************/
-               baseIPInfo->iae_reasmsize = 0x0;
-               baseIPInfo->iae_context   = 0x0;
-               baseIPInfo->iae_pad       = 0x0;
-               /************************************************************************/
-             
-               /* Calculate size of out buffer */
-               *pcbResponseInfoLen = sizeof(IPAddrEntry);
-               close(sock);
                break;
-            }
 
-
-            default: 
-            {
-               FIXME ("Command ID Not Supported -> toi_id=0x%lx, toi_entity={tei_entity=0x%lx, tei_instance=0x%lx}, toi_class=0x%lx, toi_type=0x%lx\n",
-                       pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance, 
-                       pcommand->toi_class, pcommand->toi_type);
-              
-               return (WSAEOPNOTSUPP); 
-            }
+            default:
+               ERR("Unknown entity %ld for ENTITY_TYPE_ID query\n",
+                pcommand->toi_entity.tei_entity);
          }
-      
-         break;
-      }
-    
-      case WSCNTL_TCPIP_ICMP_ECHO:
-      {
-         unsigned int addr = *(unsigned int*)pRequestInfo;
-         #if 0
-            int timeout= *(unsigned int*)(inbuf+4);
-            short x1 = *(unsigned short*)(inbuf+8);
-            short sendbufsize = *(unsigned short*)(inbuf+10);
-            char x2 = *(unsigned char*)(inbuf+12);
-            char ttl = *(unsigned char*)(inbuf+13);
-            char service = *(unsigned char*)(inbuf+14);
-            char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
-         #endif      
-      
-         FIXME("(ICMP_ECHO) to 0x%08x stub \n", addr);
          break;
-      }
-
-      default:
-      {
-         FIXME("Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
-              protocoll, action, pRequestInfo, pcbRequestInfoLen, pResponseInfo, pcbResponseInfoLen);
-      
-         return (WSAEOPNOTSUPP); 
-      }
-   }
-   
-   
-   return (WSCTL_SUCCESS); 
-}
-
-
-
-/* 
-  Helper function for WsControl - Get count of the number of interfaces
-  by parsing /proc filesystem.
-*/
-int WSCNTL_GetInterfaceCount(void)
-{
-   FILE *procfs;
-   char buf[512];  /* Size doesn't matter, something big */
-   int  intcnt=0;
-   /* Open /proc filesystem file for network devices */ 
-   procfs = fopen(PROCFS_NETDEV_FILE, "r");
-   if (!procfs) 
-   {
-      /* If we can't open the file, return an error */
-      return (-1);
-   }
-   
-   /* Omit first two lines, they are only headers */
-   fgets(buf, sizeof buf, procfs);     
-   fgets(buf, sizeof buf, procfs);
-
-   while (fgets(buf, sizeof buf, procfs)) 
-   {
-      /* Each line in the file represents a network interface */
-      intcnt++;
-   }
-
-   fclose(procfs);
-   return(intcnt);
-}
-
-
-/*
-   Helper function for WsControl - Get name of device from interface number
-   by parsing /proc filesystem.
-*/
-int WSCNTL_GetInterfaceName(int intNumber, char *intName)
-{
-   FILE *procfs;
-   char buf[512]; /* Size doesn't matter, something big */
-   int  i;
 
-   /* Open /proc filesystem file for network devices */ 
-   procfs = fopen(PROCFS_NETDEV_FILE, "r");
-   if (!procfs) 
-   {
-      /* If we can't open the file, return an error */
-      return (-1);
-   }
-   
-   /* Omit first two lines, they are only headers */
-   fgets(buf, sizeof(buf), procfs);    
-   fgets(buf, sizeof(buf), procfs);
-
-   for (i=0; i<intNumber; i++)
-   {
-      /* Skip the lines that don't interest us. */
-      fgets(buf, sizeof(buf), procfs);
-   }
-   fgets(buf, sizeof(buf), procfs); /* This is the line we want */
-
-   
-   /* Parse out the line, grabbing only the name of the device
-      to the intName variable 
-      
-      The Line comes in like this: (we only care about the device name)
-      lo:   21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
-   */
-   i=0; 
-   while (isspace(buf[i])) /* Skip initial space(s) */
-   {
-      i++;
-   }
-
-   while (buf[i]) 
-   {
-      if (isspace(buf[i]))
-      {
-         break;
-      }
-      
-      if (buf[i] == ':')  /* FIXME: Not sure if this block (alias detection) works properly */
-      {
-         /* This interface could be an alias... */
-         int hold = i;
-         char *dotname = intName;
-         *intName++ = buf[i++];
-         
-         while (isdigit(buf[i]))
-         {
-            *intName++ = buf[i++];
-         }
-         
-         if (buf[i] != ':') 
+         /* This call returns the IP address, subnet mask, and broadcast
+          * address for an interface.  If there are multiple IP addresses for
+          * the interface with the given index, returns the "first" one.
+          */
+         case IP_MIB_ADDRTABLE_ENTRY_ID:
          {
-            /* ... It wasn't, so back up */
-            i = hold;
-            intName = dotname;
+            DWORD index = pcommand->toi_entity.tei_instance;
+            PMIB_IPADDRROW baseIPInfo = pResponseInfo;
+            PMIB_IPADDRTABLE table;
+            DWORD tableSize, i;
+
+            if (!pcbResponseInfoLen)
+               return ERROR_BAD_ENVIRONMENT;
+            if (*pcbResponseInfoLen < sizeof(MIB_IPADDRROW))
+               return (ERROR_LOCK_VIOLATION);
+
+            /* get entire table, because there isn't an exported function that
+               gets just one entry. */
+            tableSize = 0;
+            GetIpAddrTable(NULL, &tableSize, FALSE);
+            table = HeapAlloc( GetProcessHeap(), 0, tableSize );
+            if (!table)
+               return ERROR_NOT_ENOUGH_MEMORY;
+            GetIpAddrTable(table, &tableSize, FALSE);
+            for (i = 0; i < table->dwNumEntries; i++)
+            {
+               if (table->table[i].dwIndex == index)
+               {
+                  TRACE("Found IP info for tei_instance 0x%x:\n", index);
+                  TRACE("IP 0x%08x, mask 0x%08x\n", table->table[i].dwAddr,
+                   table->table[i].dwMask);
+                  *baseIPInfo = table->table[i];
+                  break;
+               }
+            }
+            HeapFree( GetProcessHeap(), 0, table );
+
+            *pcbResponseInfoLen = sizeof(MIB_IPADDRROW);
+            break;
          }
-         if (buf[i] == '\0')
+
+         case IP_MIB_TABLE_ENTRY_ID:
          {
-            fclose(procfs);
-            return(FALSE);
-         }
-         
-         i++;
-         break;
-      }
-      
-      *intName++ = buf[i++];
-   }
-   *intName++ = '\0';
+            switch (pcommand->toi_entity.tei_entity)
+            {
+            /* This call returns the routing table.
+             * No official documentation found, even the name of the command is unknown.
+             * Work is based on
+             * http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html
+             * and testings done with winipcfg.exe, route.exe and ipconfig.exe.
+             * pcommand->toi_entity.tei_instance seems to be the interface number
+             * but route.exe outputs only the information for the last interface
+             * if only the routes for the pcommand->toi_entity.tei_instance
+             * interface are returned. */
+               case CL_NL_ENTITY:
+               {
+                  DWORD routeTableSize, numRoutes, ndx, ret;
+                  PMIB_IPFORWARDTABLE table;
+                  IPRouteEntry *winRouteTable  = pResponseInfo;
+
+                  if (!pcbResponseInfoLen)
+                     return ERROR_BAD_ENVIRONMENT;
+                  ret = GetIpForwardTable(NULL, &routeTableSize, FALSE);
+                  if (ret != ERROR_INSUFFICIENT_BUFFER)
+                      return ret;
+                  numRoutes = (routeTableSize - sizeof(MIB_IPFORWARDTABLE))
+                   / sizeof(MIB_IPFORWARDROW) + 1;
+                  if (*pcbResponseInfoLen < sizeof(IPRouteEntry) * numRoutes)
+                     return (ERROR_LOCK_VIOLATION);
+                  table = HeapAlloc( GetProcessHeap(), 0, routeTableSize );
+                  if (!table)
+                     return ERROR_NOT_ENOUGH_MEMORY;
+                  ret = GetIpForwardTable(table, &routeTableSize, FALSE);
+                  if (ret != NO_ERROR) {
+                     HeapFree( GetProcessHeap(), 0, table );
+                     return ret;
+                  }
 
-   fclose(procfs);
-   return(TRUE);
-}
+                  memset(pResponseInfo, 0, sizeof(IPRouteEntry) * numRoutes);
+                  for (ndx = 0; ndx < table->dwNumEntries; ndx++)
+                  {
+                     winRouteTable->ire_addr = table->table[ndx].dwForwardDest;
+                     winRouteTable->ire_index =
+                      table->table[ndx].dwForwardIfIndex;
+                     winRouteTable->ire_metric =
+                      table->table[ndx].dwForwardMetric1;
+                     /* winRouteTable->ire_option4 =
+                     winRouteTable->ire_option5 =
+                     winRouteTable->ire_option6 = */
+                     winRouteTable->ire_gw = table->table[ndx].dwForwardNextHop;
+                     /* winRouteTable->ire_option8 =
+                     winRouteTable->ire_option9 =
+                     winRouteTable->ire_option10 = */
+                     winRouteTable->ire_mask = table->table[ndx].dwForwardMask;
+                     /* winRouteTable->ire_option12 = */
+                     winRouteTable++;
+                  }
 
+                  /* calculate the length of the data in the output buffer */
+                  *pcbResponseInfoLen = sizeof(IPRouteEntry) *
+                   table->dwNumEntries;
 
-/*
-   Helper function for WsControl - This function returns the bytes (octets) transmitted
-   and received for the supplied interface number from the /proc fs. 
-*/
-int WSCNTL_GetTransRecvStat(int intNumber, unsigned long *transBytes, unsigned long *recvBytes)
-{
-   FILE *procfs;
-   char buf[512], result[512]; /* Size doesn't matter, something big */
-   int  i, bufPos, resultPos;
+                  HeapFree( GetProcessHeap(), 0, table );
+               }
+               break;
 
-   /* Open /proc filesystem file for network devices */ 
-   procfs = fopen(PROCFS_NETDEV_FILE, "r");
-   if (!procfs) 
-   {
-      /* If we can't open the file, return an error */
-      return (-1);
-   }
-   
-   /* Omit first two lines, they are only headers */
-   fgets(buf, sizeof(buf), procfs);    
-   fgets(buf, sizeof(buf), procfs);
+               case AT_ARP:
+               {
+                  DWORD arpTableSize, numEntries, ret;
+                  PMIB_IPNETTABLE table;
+
+                  if (!pcbResponseInfoLen)
+                     return ERROR_BAD_ENVIRONMENT;
+                  ret = GetIpNetTable(NULL, &arpTableSize, FALSE);
+                  if (ret != ERROR_INSUFFICIENT_BUFFER)
+                      return ret;
+                  numEntries = (arpTableSize - sizeof(MIB_IPNETTABLE))
+                   / sizeof(MIB_IPNETROW) + 1;
+                  if (*pcbResponseInfoLen < sizeof(MIB_IPNETROW) * numEntries)
+                     return (ERROR_LOCK_VIOLATION);
+                  table = HeapAlloc( GetProcessHeap(), 0, arpTableSize );
+                  if (!table)
+                     return ERROR_NOT_ENOUGH_MEMORY;
+                  ret = GetIpNetTable(table, &arpTableSize, FALSE);
+                  if (ret != NO_ERROR) {
+                     HeapFree( GetProcessHeap(), 0, table );
+                     return ret;
+                  }
+                  if (*pcbResponseInfoLen < sizeof(MIB_IPNETROW) *
+                   table->dwNumEntries)
+                  {
+                     HeapFree( GetProcessHeap(), 0, table );
+                     return ERROR_LOCK_VIOLATION;
+                  }
+                  memcpy(pResponseInfo, table->table, sizeof(MIB_IPNETROW) *
+                   table->dwNumEntries);
 
-   for (i=0; i<intNumber; i++)
-   {
-      /* Skip the lines that don't interest us. */
-      fgets(buf, sizeof(buf), procfs);
-   }
-   fgets(buf, sizeof(buf), procfs); /* This is the line we want */
+                  /* calculate the length of the data in the output buffer */
+                  *pcbResponseInfoLen = sizeof(MIB_IPNETROW) *
+                   table->dwNumEntries;
 
+                  HeapFree( GetProcessHeap(), 0, table );
+               }
+               break;
 
+               case CO_TL_ENTITY:
+               {
+                  DWORD tcpTableSize, numEntries, ret;
+                  PMIB_TCPTABLE table;
+                  DWORD i;
+
+                  if (!pcbResponseInfoLen)
+                     return ERROR_BAD_ENVIRONMENT;
+                  ret = GetTcpTable(NULL, &tcpTableSize, FALSE);
+                  if (ret != ERROR_INSUFFICIENT_BUFFER)
+                      return ret;
+                  numEntries = (tcpTableSize - sizeof(MIB_TCPTABLE))
+                   / sizeof(MIB_TCPROW) + 1;
+                  if (*pcbResponseInfoLen < sizeof(MIB_TCPROW) * numEntries)
+                     return (ERROR_LOCK_VIOLATION);
+                  table = HeapAlloc( GetProcessHeap(), 0, tcpTableSize );
+                  if (!table)
+                     return ERROR_NOT_ENOUGH_MEMORY;
+                  ret = GetTcpTable(table, &tcpTableSize, FALSE);
+                  if (ret != NO_ERROR) {
+                     HeapFree( GetProcessHeap(), 0, table );
+                     return ret;
+                  }
+                  if (*pcbResponseInfoLen < sizeof(MIB_TCPROW) *
+                   table->dwNumEntries)
+                  {
+                     HeapFree( GetProcessHeap(), 0, table );
+                     return ERROR_LOCK_VIOLATION;
+                  }
+                  for (i = 0; i < table->dwNumEntries; i++)
+                  {
+                     USHORT sPort;
 
-   /* Parse out the line, grabbing the number of bytes transmitted
-      and received on the interface.
-      
-      The Line comes in like this: (we care about columns 2 and 10)
-      lo:   21970 377 0 0 0 0 0 0 21970 377 0 0 0 0 0 0
-   */
+                     sPort = ntohs((USHORT)table->table[i].dwLocalPort);
+                     table->table[i].dwLocalPort = (DWORD)sPort;
+                     sPort = ntohs((USHORT)table->table[i].dwRemotePort);
+                     table->table[i].dwRemotePort = (DWORD)sPort;
+                  }
+                  memcpy(pResponseInfo, table->table, sizeof(MIB_TCPROW) *
+                   table->dwNumEntries);
 
-   /* Start at character 0 in the buffer */
-   bufPos=0;
-   
-   /* Skip initial space(s) */ 
-   while (isspace(buf[bufPos])) 
-      bufPos++;
+                  /* calculate the length of the data in the output buffer */
+                  *pcbResponseInfoLen = sizeof(MIB_TCPROW) *
+                   table->dwNumEntries;
 
+                  HeapFree( GetProcessHeap(), 0, table );
+               }
+               break;
 
-   /* Skip the name and its trailing spaces (if any) */
-   while (buf[bufPos]) 
-   {
-      if (isspace(buf[bufPos]))
+               default:
+               {
+                  FIXME ("Command ID Not Supported -> toi_id=0x%lx, toi_entity={tei_entity=0x%lx, tei_instance=0x%lx}, toi_class=0x%lx\n",
+                     pcommand->toi_id, pcommand->toi_entity.tei_entity,
+                     pcommand->toi_entity.tei_instance, pcommand->toi_class);
+
+                  return (ERROR_BAD_ENVIRONMENT);
+               }
+            }
+         }
          break;
-      if (buf[bufPos] == ':') /* Could be an alias */
-      {
-         int hold = bufPos;
 
-         while(isdigit (buf[bufPos]))
-            bufPos++;
-         if (buf[bufPos] != ':')
-            bufPos = hold;
-         if (buf[bufPos] == '\0')
+
+         default:
          {
-            fclose(procfs);
-            return(FALSE);
+            FIXME ("Command ID Not Supported -> toi_id=0x%lx, toi_entity={tei_entity=0x%lx, tei_instance=0x%lx}, toi_class=0x%lx\n",
+               pcommand->toi_id, pcommand->toi_entity.tei_entity,
+               pcommand->toi_entity.tei_instance, pcommand->toi_class);
+
+            return (ERROR_BAD_ENVIRONMENT);
          }
-         
-         bufPos++;
-         break;
       }
 
-      bufPos++;
+      break;
    }
-   while (isspace(buf[bufPos]))
-      bufPos++;
-
 
-   /* This column (#2) is the number of bytes received. */
-   resultPos = 0;
-   while (!isspace(buf[bufPos]))
+   case WSCNTL_TCPIP_ICMP_ECHO:
    {
-      result[resultPos] = buf[bufPos];
-      result[resultPos+1]='\0';
-      resultPos++; bufPos++;
-   }
-   *recvBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
+      unsigned int addr = *(unsigned int*)pRequestInfo;
+#if 0
+         int timeout= *(unsigned int*)(inbuf+4);
+         short x1 = *(unsigned short*)(inbuf+8);
+         short sendbufsize = *(unsigned short*)(inbuf+10);
+         char x2 = *(unsigned char*)(inbuf+12);
+         char ttl = *(unsigned char*)(inbuf+13);
+         char service = *(unsigned char*)(inbuf+14);
+         char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/
+#endif
 
-   
-   /* Skip columns #3 to #9 (Don't need them) */
-   for  (i=0; i<7; i++)
-   {
-      while (isspace(buf[bufPos]))
-         bufPos++;
-      while (!isspace(buf[bufPos])) 
-         bufPos++;
+      FIXME("(ICMP_ECHO) to 0x%08x stub\n", addr);
+      break;
    }
 
+   default:
+      FIXME("Protocol Not Supported -> protocol=0x%x, action=0x%x, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n",
+       protocol, action, pRequestInfo, pcbRequestInfoLen, pResponseInfo, pcbResponseInfoLen);
 
-   /* This column (#10) is the number of bytes transmitted */
-   while (isspace(buf[bufPos]))
-       bufPos++;
+      return (WSAEOPNOTSUPP);
 
-   resultPos = 0;
-   while (!isspace(buf[bufPos]))
-   {
-      result[resultPos] = buf[bufPos];
-      result[resultPos+1]='\0';
-      resultPos++; bufPos++;
    }
-   *transBytes = strtoul (result, NULL, 10); /* convert string to unsigned long, using base 10 */
-
 
-   fclose(procfs);
-   return(TRUE);
+   return (WSCTL_SUCCESS);
 }
 
 
+
 /***********************************************************************
- *             WSARecvEx()                     (WSOCK32.1107)
+ *             WSARecvEx                       (WSOCK32.1107)
  *
  * WSARecvEx is a Microsoft specific extension to winsock that is identical to recv
  * except that has an in/out argument call flags that has the value MSG_PARTIAL ored
@@ -696,44 +641,16 @@ int WSCNTL_GetTransRecvStat(int intNumber, unsigned long *transBytes, unsigned l
  */
 INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags)
 {
-    FIXME("(WSARecvEx) partial packet return value not set \n");
-    return WS2_recv(s, buf, len, *flags);
+    FIXME("(WSARecvEx) partial packet return value not set\n");
+    return recv(s, buf, len, *flags);
 }
 
 
 /***********************************************************************
- *       WS_s_perror         (WSOCK32.1108)
+ *       s_perror         (WSOCK32.1108)
  */
-void WINAPI WS_s_perror(LPCSTR message)
+void WINAPI s_perror(LPCSTR message)
 {
     FIXME("(%s): stub\n",message);
     return;
 }
-
-
-/***********************************************************************
- *             WSOCK_LibMain
- */
-BOOL WINAPI WSOCK_LibMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
-{
-    static HMODULE ws2_32;
-    switch (reason)
-    {
-    case DLL_PROCESS_ATTACH:
-        /* we import ws2_32 by hand, because we don't want to implicitly */
-        /* link to it; otherwise Unix calls like socket() get redirected */
-        /* to ws2_32.dll and this is not what we want. */
-
-        if (!(ws2_32 = LoadLibraryA( "ws2_32.dll" )))
-        {
-            ERR("could not load ws2_32\n" );
-            return FALSE;
-        }
-        WS2_recv = (void *)GetProcAddress( ws2_32, "recv" );
-        break;
-    case DLL_PROCESS_DETACH:
-        FreeLibrary( ws2_32 );
-        break;
-    }
-    return TRUE;
-}