[WS2_32]
[reactos.git] / reactos / dll / win32 / ws2_32 / misc / ns.c
index 85c84bd..04e5b4b 100644 (file)
@@ -7,7 +7,6 @@
  * REVISIONS:
  *   CSH 01/09-2000 Created
  */
-#define __NO_CTYPE_INLINES
 #include <ctype.h>
 #include <ws2_32.h>
 #include <winbase.h>
  */
 INT
 EXPORT
-WSAAddressToStringA(
-    IN      LPSOCKADDR lpsaAddress,
-    IN      DWORD dwAddressLength,
-    IN      LPWSAPROTOCOL_INFOA lpProtocolInfo,
-    OUT     LPSTR lpszAddressString,
-    IN OUT  LPDWORD lpdwAddressStringLength)
+WSAAddressToStringA(IN      LPSOCKADDR lpsaAddress,
+                    IN      DWORD dwAddressLength,
+                    IN      LPWSAPROTOCOL_INFOA lpProtocolInfo,
+                    OUT     LPSTR lpszAddressString,
+                    IN OUT  LPDWORD lpdwAddressStringLength)
 {
-    UNIMPLEMENTED
+    DWORD size;
+    CHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
+    CHAR *p;
+
+    if (!lpsaAddress) return SOCKET_ERROR;
+    if (!lpszAddressString || !lpdwAddressStringLength) return SOCKET_ERROR;
+
+    switch(lpsaAddress->sa_family)
+    {
+    case AF_INET:
+        if (dwAddressLength < sizeof(SOCKADDR_IN)) return SOCKET_ERROR;
+        sprintf( buffer, "%u.%u.%u.%u:%u",
+               (unsigned int)(ntohl( ((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr ) >> 24 & 0xff),
+               (unsigned int)(ntohl( ((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr ) >> 16 & 0xff),
+               (unsigned int)(ntohl( ((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr ) >> 8 & 0xff),
+               (unsigned int)(ntohl( ((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr ) & 0xff),
+               ntohs( ((SOCKADDR_IN *)lpsaAddress)->sin_port ) );
+
+        p = strchr( buffer, ':' );
+        if (!((SOCKADDR_IN *)lpsaAddress)->sin_port) *p = 0;
+        break;
+    default:
+        WSASetLastError(WSAEINVAL);
+        return SOCKET_ERROR;
+    }
+
+    size = strlen( buffer ) + 1;
 
+    if (*lpdwAddressStringLength <  size)
+    {
+        *lpdwAddressStringLength = size;
+        WSASetLastError(WSAEFAULT);
+        return SOCKET_ERROR;
+    }
+
+    *lpdwAddressStringLength = size;
+    strcpy( lpszAddressString, buffer );
     return 0;
 }
 
@@ -45,15 +78,33 @@ WSAAddressToStringA(
  */
 INT
 EXPORT
-WSAAddressToStringW(
-    IN      LPSOCKADDR lpsaAddress,
-    IN      DWORD dwAddressLength,
-    IN      LPWSAPROTOCOL_INFOW lpProtocolInfo,
-    OUT     LPWSTR lpszAddressString,
-    IN OUT  LPDWORD lpdwAddressStringLength)
+WSAAddressToStringW(IN      LPSOCKADDR lpsaAddress,
+                    IN      DWORD dwAddressLength,
+                    IN      LPWSAPROTOCOL_INFOW lpProtocolInfo,
+                    OUT     LPWSTR lpszAddressString,
+                    IN OUT  LPDWORD lpdwAddressStringLength)
 {
-    UNIMPLEMENTED
+    INT   ret;
+    DWORD size;
+    WCHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
+    CHAR bufAddr[54];
+
+    size = *lpdwAddressStringLength;
+    ret = WSAAddressToStringA(lpsaAddress, dwAddressLength, NULL, bufAddr, &size);
 
+    if (ret) return ret;
+
+    MultiByteToWideChar( CP_ACP, 0, bufAddr, size, buffer, sizeof( buffer )/sizeof(WCHAR));
+
+    if (*lpdwAddressStringLength <  size)
+    {
+        *lpdwAddressStringLength = size;
+        WSASetLastError(WSAEFAULT);
+        return SOCKET_ERROR;
+    }
+
+    *lpdwAddressStringLength = size;
+    lstrcpyW( lpszAddressString, buffer );
     return 0;
 }
 
@@ -63,13 +114,13 @@ WSAAddressToStringW(
  */
 INT
 EXPORT
-WSAEnumNameSpaceProvidersA(
-    IN OUT  LPDWORD lpdwBufferLength,
-    OUT     LPWSANAMESPACE_INFOA lpnspBuffer)
+WSAEnumNameSpaceProvidersA(IN OUT  LPDWORD lpdwBufferLength,
+                           OUT     LPWSANAMESPACE_INFOA lpnspBuffer)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -78,13 +129,13 @@ WSAEnumNameSpaceProvidersA(
  */
 INT
 EXPORT
-WSAEnumNameSpaceProvidersW(
-    IN OUT  LPDWORD lpdwBufferLength,
-    OUT     LPWSANAMESPACE_INFOW lpnspBuffer)
+WSAEnumNameSpaceProvidersW(IN OUT  LPDWORD lpdwBufferLength,
+                           OUT     LPWSANAMESPACE_INFOW lpnspBuffer)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -93,15 +144,15 @@ WSAEnumNameSpaceProvidersW(
  */
 INT
 EXPORT
-WSAGetServiceClassInfoA(
-    IN      LPGUID lpProviderId,
-    IN      LPGUID lpServiceClassId,
-    IN OUT  LPDWORD lpdwBufferLength,
-    OUT     LPWSASERVICECLASSINFOA lpServiceClassInfo)
+WSAGetServiceClassInfoA(IN      LPGUID lpProviderId,
+                        IN      LPGUID lpServiceClassId,
+                        IN OUT  LPDWORD lpdwBufferLength,
+                        OUT     LPWSASERVICECLASSINFOA lpServiceClassInfo)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -110,15 +161,15 @@ WSAGetServiceClassInfoA(
  */
 INT
 EXPORT
-WSAGetServiceClassInfoW(
-    IN      LPGUID lpProviderId,
-    IN      LPGUID lpServiceClassId,
-    IN OUT  LPDWORD lpdwBufferLength,
-    OUT     LPWSASERVICECLASSINFOW lpServiceClassInfo)
+WSAGetServiceClassInfoW(IN      LPGUID lpProviderId,
+                        IN      LPGUID lpServiceClassId,
+                        IN OUT  LPDWORD lpdwBufferLength,
+                        OUT     LPWSASERVICECLASSINFOW lpServiceClassInfo)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -127,14 +178,14 @@ WSAGetServiceClassInfoW(
  */
 INT
 EXPORT
-WSAGetServiceClassNameByClassIdA(
-    IN      LPGUID lpServiceClassId,
-    OUT     LPSTR lpszServiceClassName,
-    IN OUT  LPDWORD lpdwBufferLength)
+WSAGetServiceClassNameByClassIdA(IN      LPGUID lpServiceClassId,
+                                 OUT     LPSTR lpszServiceClassName,
+                                 IN OUT  LPDWORD lpdwBufferLength)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -143,14 +194,14 @@ WSAGetServiceClassNameByClassIdA(
  */
 INT
 EXPORT
-WSAGetServiceClassNameByClassIdW(
-    IN      LPGUID lpServiceClassId,
-    OUT     LPWSTR lpszServiceClassName,
-    IN OUT  LPDWORD lpdwBufferLength)
+WSAGetServiceClassNameByClassIdW(IN      LPGUID lpServiceClassId,
+                                 OUT     LPWSTR lpszServiceClassName,
+                                 IN OUT  LPDWORD lpdwBufferLength)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -159,12 +210,12 @@ WSAGetServiceClassNameByClassIdW(
  */
 INT
 EXPORT
-WSAInstallServiceClassA(
-    IN  LPWSASERVICECLASSINFOA lpServiceClassInfo)
+WSAInstallServiceClassA(IN  LPWSASERVICECLASSINFOA lpServiceClassInfo)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -173,12 +224,12 @@ WSAInstallServiceClassA(
  */
 INT
 EXPORT
-WSAInstallServiceClassW(
-    IN  LPWSASERVICECLASSINFOW lpServiceClassInfo)
+WSAInstallServiceClassW(IN  LPWSASERVICECLASSINFOW lpServiceClassInfo)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -187,14 +238,14 @@ WSAInstallServiceClassW(
  */
 INT
 EXPORT
-WSALookupServiceBeginA(
-    IN  LPWSAQUERYSETA lpqsRestrictions,
-    IN  DWORD dwControlFlags,
-    OUT LPHANDLE lphLookup)
+WSALookupServiceBeginA(IN  LPWSAQUERYSETA lpqsRestrictions,
+                       IN  DWORD dwControlFlags,
+                       OUT LPHANDLE lphLookup)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -203,14 +254,14 @@ WSALookupServiceBeginA(
  */
 INT
 EXPORT
-WSALookupServiceBeginW(
-    IN  LPWSAQUERYSETW lpqsRestrictions,
-    IN  DWORD dwControlFlags,
-    OUT LPHANDLE lphLookup)
+WSALookupServiceBeginW(IN  LPWSAQUERYSETW lpqsRestrictions,
+                       IN  DWORD dwControlFlags,
+                       OUT LPHANDLE lphLookup)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -219,12 +270,12 @@ WSALookupServiceBeginW(
  */
 INT
 EXPORT
-WSALookupServiceEnd(
-    IN  HANDLE hLookup)
+WSALookupServiceEnd(IN  HANDLE hLookup)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -233,15 +284,15 @@ WSALookupServiceEnd(
  */
 INT
 EXPORT
-WSALookupServiceNextA(
-    IN      HANDLE hLookup,
-    IN      DWORD dwControlFlags,
-    IN OUT  LPDWORD lpdwBufferLength,
-    OUT     LPWSAQUERYSETA lpqsResults)
+WSALookupServiceNextA(IN      HANDLE hLookup,
+                      IN      DWORD dwControlFlags,
+                      IN OUT  LPDWORD lpdwBufferLength,
+                      OUT     LPWSAQUERYSETA lpqsResults)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -250,15 +301,15 @@ WSALookupServiceNextA(
  */
 INT
 EXPORT
-WSALookupServiceNextW(
-    IN      HANDLE hLookup,
-    IN      DWORD dwControlFlags,
-    IN OUT  LPDWORD lpdwBufferLength,
-    OUT     LPWSAQUERYSETW lpqsResults)
+WSALookupServiceNextW(IN      HANDLE hLookup,
+                      IN      DWORD dwControlFlags,
+                      IN OUT  LPDWORD lpdwBufferLength,
+                      OUT     LPWSAQUERYSETW lpqsResults)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -267,12 +318,12 @@ WSALookupServiceNextW(
  */
 INT
 EXPORT
-WSARemoveServiceClass(
-    IN  LPGUID lpServiceClassId)
+WSARemoveServiceClass(IN  LPGUID lpServiceClassId)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -281,14 +332,14 @@ WSARemoveServiceClass(
  */
 INT
 EXPORT
-WSASetServiceA(
-    IN  LPWSAQUERYSETA lpqsRegInfo,
-    IN  WSAESETSERVICEOP essOperation,
-    IN  DWORD dwControlFlags)
+WSASetServiceA(IN  LPWSAQUERYSETA lpqsRegInfo,
+               IN  WSAESETSERVICEOP essOperation,
+               IN  DWORD dwControlFlags)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -297,14 +348,14 @@ WSASetServiceA(
  */
 INT
 EXPORT
-WSASetServiceW(
-    IN  LPWSAQUERYSETW lpqsRegInfo,
-    IN  WSAESETSERVICEOP essOperation,
-    IN  DWORD dwControlFlags)
+WSASetServiceW(IN  LPWSAQUERYSETW lpqsRegInfo,
+               IN  WSAESETSERVICEOP essOperation,
+               IN  DWORD dwControlFlags)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -313,171 +364,244 @@ WSASetServiceW(
  */
 INT
 EXPORT
-WSAStringToAddressA(
-    IN      LPSTR AddressString,
-    IN      INT AddressFamily,
-    IN      LPWSAPROTOCOL_INFOA lpProtocolInfo,
-    OUT     LPSOCKADDR lpAddress,
-    IN OUT  LPINT lpAddressLength)
+WSAStringToAddressA(IN     LPSTR AddressString,
+                    IN     INT AddressFamily,
+                    IN     LPWSAPROTOCOL_INFOA lpProtocolInfo,
+                    OUT    LPSOCKADDR lpAddress,
+                    IN OUT LPINT lpAddressLength)
 {
     INT ret, len;
-       LPWSTR szTemp;
-       LPWSAPROTOCOL_INFOW lpProtoInfoW = NULL;
+    LPWSTR szTemp;
+    LPWSAPROTOCOL_INFOW lpProtoInfoW = NULL;
+
+    len = MultiByteToWideChar(CP_ACP,
+                              0,
+                              AddressString,
+                              -1,
+                              NULL,
+                              0);
+
+    szTemp = HeapAlloc(GetProcessHeap(),
+                       0,
+                       len * sizeof(WCHAR));
+
+    MultiByteToWideChar(CP_ACP,
+                        0,
+                        AddressString,
+                        -1,
+                        szTemp,
+                        len);
 
-       len = MultiByteToWideChar( CP_ACP, 0, AddressString, -1, NULL, 0 );
-       szTemp = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); 
-       MultiByteToWideChar( CP_ACP, 0, AddressString, -1, szTemp, len );
-       
     if (lpProtocolInfo)
-       {
-        len =   WSAPROTOCOL_LEN+1;
-        lpProtoInfoW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );  
-   
-        memcpy( lpProtoInfoW, lpProtocolInfo, sizeof(LPWSAPROTOCOL_INFOA));
-
-        MultiByteToWideChar( CP_ACP, 0, lpProtocolInfo->szProtocol, -1, lpProtoInfoW->szProtocol, len );
-       }
-         
-       ret = WSAStringToAddressW(szTemp, AddressFamily, lpProtoInfoW, lpAddress, lpAddressLength);
-
-       HeapFree( GetProcessHeap(), 0, szTemp );
-
-       if (lpProtocolInfo)
-          HeapFree( GetProcessHeap(), 0, lpProtoInfoW );
-       
-       WSASetLastError(ret);
-    return ret;
+    {
+        len =   WSAPROTOCOL_LEN+1;
+        lpProtoInfoW = HeapAlloc(GetProcessHeap(),
+                                 0,
+                                 len * sizeof(WCHAR) );
+
+        memcpy(lpProtoInfoW,
+               lpProtocolInfo,
+               sizeof(LPWSAPROTOCOL_INFOA));
+
+        MultiByteToWideChar(CP_ACP,
+                            0,
+                            lpProtocolInfo->szProtocol,
+                            -1,
+                            lpProtoInfoW->szProtocol,
+                            len);
+    }
+
+    ret = WSAStringToAddressW(szTemp,
+                              AddressFamily,
+                              lpProtoInfoW,
+                              lpAddress,
+                              lpAddressLength);
+
+    HeapFree(GetProcessHeap(),
+             0,
+             szTemp );
+
+    if (lpProtocolInfo)
+        HeapFree(GetProcessHeap(),
+                 0,
+                 lpProtoInfoW);
+
+    WSASetLastError(ret);
+        return ret;
 }
 
 
 
 /*
- * @implement 
+ * @implemented
  */
 INT
 EXPORT
-WSAStringToAddressW(
-    IN      LPWSTR AddressString,
-    IN      INT AddressFamily,
-    IN      LPWSAPROTOCOL_INFOW lpProtocolInfo,
-    OUT     LPSOCKADDR lpAddress,
-    IN OUT  LPINT lpAddressLength)
+WSAStringToAddressW(IN      LPWSTR AddressString,
+                    IN      INT AddressFamily,
+                    IN      LPWSAPROTOCOL_INFOW lpProtocolInfo,
+                    OUT     LPSOCKADDR lpAddress,
+                    IN OUT  LPINT lpAddressLength)
 {
-    int pos=0;         
-       int res=0;
-       LONG inetaddr = 0;      
+    int pos=0;
+    int res=0;
+    LONG inetaddr = 0;
     LPWSTR *bp=NULL;
+    SOCKADDR_IN *sockaddr;
 
-       SOCKADDR_IN *sockaddr = (SOCKADDR_IN *) lpAddress;
+    if (!lpAddressLength || !lpAddress || !AddressString)
+    {
+        WSASetLastError(WSAEINVAL);
+        return SOCKET_ERROR;
+    }
+
+    sockaddr = (SOCKADDR_IN *) lpAddress;
 
-       if (!lpAddressLength || !lpAddress) 
-               return SOCKET_ERROR;
-       
-       if (AddressString==NULL) 
-               return WSAEINVAL;
-               
     /* Set right adress family */
-    if (lpProtocolInfo!=NULL) 
-          sockaddr->sin_family = lpProtocolInfo->iAddressFamily;
-
-       else sockaddr->sin_family = AddressFamily;      
-   
-       /* Report size */
-       if (AddressFamily == AF_INET)
-       {
-               if (*lpAddressLength < (INT)sizeof(SOCKADDR_IN))
-               {
-                       *lpAddressLength = sizeof(SOCKADDR_IN);
-                   res = WSAEFAULT;
-               }
-               else
-               {
-         if (!lpAddress) 
-                       res = WSAEINVAL;
-                else 
-                {
-                 // translate now ip string to ip
-
-                 /* rest sockaddr.sin_addr.s_addr  
-                    for we need to be sure it is zero when we come to while */
-                 memset(lpAddress,0,sizeof(SOCKADDR_IN));
-
-                 /* Set right adress family */
-          sockaddr->sin_family = AF_INET;
-
-                 /* Get port number */
-                 pos = wcscspn(AddressString,L":") + 1;
-                 if (pos < (int)wcslen(AddressString))
-                 sockaddr->sin_port = wcstol(&AddressString[pos],bp,10);                                  
-
-                  else
-                          sockaddr->sin_port = 0;
-                         
-                 /* Get ip number */             
-                 pos=0;
-                 inetaddr=0;
-
-          while (pos < (int)wcslen(AddressString))
-          {          
-              inetaddr = (inetaddr<<8) + ((UCHAR)wcstol(&AddressString[pos],bp,10));                      
-              pos += wcscspn( &AddressString[pos],L".") +1 ;                              
-              }
-
-          res = 0;
-                 sockaddr->sin_addr.s_addr = inetaddr;                           
-                 }
-
-               }
-       }
+    if (lpProtocolInfo!=NULL)
+       sockaddr->sin_family = lpProtocolInfo->iAddressFamily;
+
+    else sockaddr->sin_family = AddressFamily;
+
+    /* Report size */
+    if (AddressFamily == AF_INET)
+    {
+        if (*lpAddressLength < (INT)sizeof(SOCKADDR_IN))
+        {
+            *lpAddressLength = sizeof(SOCKADDR_IN);
+            res = WSAEFAULT;
+        }
+        else
+        {
+            // translate ip string to ip
+
+            /* rest sockaddr.sin_addr.s_addr
+                   for we need to be sure it is zero when we come to while */
+            memset(lpAddress,0,sizeof(SOCKADDR_IN));
+
+            /* Set right adress family */
+            sockaddr->sin_family = AF_INET;
+
+            /* Get port number */
+            pos = wcscspn(AddressString,L":") + 1;
+
+            if (pos < (int)wcslen(AddressString))
+                sockaddr->sin_port = wcstol(&AddressString[pos],
+                                            bp,
+                                            10);
+
+            else
+                sockaddr->sin_port = 0;
+
+            /* Get ip number */
+            pos=0;
+            inetaddr=0;
+
+            while (pos < (int)wcslen(AddressString))
+            {
+                inetaddr = (inetaddr<<8) + ((UCHAR)wcstol(&AddressString[pos],
+                                                          bp,
+                                                          10));
+                pos += wcscspn( &AddressString[pos],L".") +1 ;
+            }
+
+            res = 0;
+            sockaddr->sin_addr.s_addr = inetaddr;
+
+        }
+    }
 
     WSASetLastError(res);
-       if (!res) return 0;                     
-    return SOCKET_ERROR;           
+    if (!res) return 0;
+        return SOCKET_ERROR;
 }
 
-void check_hostent(struct hostent **he) {
-  struct hostent *new_he;
-  WS_DbgPrint(MID_TRACE,("*he: %x\n",*he));
-  if(!*he) {
-    new_he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent) + MAX_HOSTNAME_LEN + 1);
-    new_he->h_name = (PCHAR)(new_he + 1);
-    new_he->h_aliases = 0;
-    new_he->h_addrtype = 0; // AF_INET
-    new_he->h_length = 0;   // sizeof(in_addr)
-    new_he->h_addr_list = HeapAlloc(GlobalHeap, 0, sizeof(char *) * 2);
-    RtlZeroMemory(new_he->h_addr_list, sizeof(char *) * 2);
-    *he = new_he;
-  }
+void check_hostent(struct hostent **he)
+{
+    struct hostent *new_he;
+
+    WS_DbgPrint(MID_TRACE,("*he: %x\n",*he));
+
+    if(!*he)
+    {
+        new_he = HeapAlloc(GlobalHeap,
+                           0,
+                           sizeof(struct hostent) + MAX_HOSTNAME_LEN + 1);
+
+        new_he->h_name = (PCHAR)(new_he + 1);
+        new_he->h_aliases = 0;
+        new_he->h_addrtype = 0; // AF_INET
+        new_he->h_length = 0;   // sizeof(in_addr)
+        new_he->h_addr_list = HeapAlloc(GlobalHeap,
+                                        0,
+                                        sizeof(char *) * 2);
+
+        RtlZeroMemory(new_he->h_addr_list,
+                      sizeof(char *) * 2);
+        *he = new_he;
+    }
 }
 
-void populate_hostent(struct hostent *he, char* name, DNS_A_DATA addr) {
-  ASSERT(he);
-  //he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent));
-  //he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
-  strncpy(he->h_name, name, MAX_HOSTNAME_LEN);
-  he->h_aliases = 0;
-  he->h_addrtype = AF_INET;
-  he->h_length = sizeof(IN_ADDR); //sizeof(struct in_addr);
-  if( he->h_addr_list[0] ) HeapFree( GlobalHeap, 0, he->h_addr_list[0] );
-  he->h_addr_list[0] = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
-  WS_DbgPrint(MID_TRACE,("he->h_addr_list[0] %x\n", he->h_addr_list[0]));
-  RtlCopyMemory(he->h_addr_list[0], (char*)&addr.IpAddress, 
-               sizeof(addr.IpAddress));
-  he->h_addr_list[1] = 0;
+void populate_hostent(struct hostent *he, char* name, DNS_A_DATA addr)
+{
+    ASSERT(he);
+
+    //he = HeapAlloc(GlobalHeap, 0, sizeof(struct hostent));
+    //he->h_name = HeapAlloc(GlobalHeap, 0, MAX_HOSTNAME_LEN+1);
+
+    strncpy(he->h_name,
+            name,
+            MAX_HOSTNAME_LEN);
+
+    if( !he->h_aliases ) {
+       he->h_aliases = HeapAlloc(GlobalHeap, 0, sizeof(char *));
+       he->h_aliases[0] = 0;
+    }
+    he->h_addrtype = AF_INET;
+    he->h_length = sizeof(IN_ADDR); //sizeof(struct in_addr);
+
+    if( he->h_addr_list[0] )
+    {
+        HeapFree(GlobalHeap,
+                 0,
+                 he->h_addr_list[0]);
+    }
+
+    he->h_addr_list[0] = HeapAlloc(GlobalHeap,
+                                   0,
+                                   MAX_HOSTNAME_LEN + 1);
+
+    WS_DbgPrint(MID_TRACE,("he->h_addr_list[0] %x\n", he->h_addr_list[0]));
+
+    RtlCopyMemory(he->h_addr_list[0],
+                  (char*)&addr.IpAddress,
+                  sizeof(addr.IpAddress));
+
+    he->h_addr_list[1] = 0;
 }
 
 
 #define HFREE(x) if(x) { HeapFree(GlobalHeap, 0, (x)); x=0; }
-void free_hostent(struct hostent *he) {
-  if(he) {
-    HFREE(he->h_name);
-    char *next = he->h_aliases[0];
-    while(next) { HFREE(next); next++; }
-    next = he->h_addr_list[0];
-    while(next) { HFREE(next); next++; }
-    HFREE(he->h_addr_list);
-    HFREE(he);
-  }
+void free_hostent(struct hostent *he)
+{
+    if(he)
+    {
+       char *next = 0;
+        HFREE(he->h_name);
+        if(he->h_aliases)
+       {
+           next = he->h_aliases[0];
+           while(next) { HFREE(next); next++; }
+       }
+       if(he->h_addr_list)
+       {
+           next = he->h_addr_list[0];
+           while(next) { HFREE(next); next++; }
+       }
+        HFREE(he->h_addr_list);
+       HFREE(he->h_aliases);
+        HFREE(he);
+    }
 }
 
 /* WinSock 1.1 compatible name resolution APIs */
@@ -487,10 +611,9 @@ void free_hostent(struct hostent *he) {
  */
 LPHOSTENT
 EXPORT
-gethostbyaddr(
-    IN  CONST CHAR FAR* addr,
-    IN  INT len,
-    IN  INT type)
+gethostbyaddr(IN  CONST CHAR FAR* addr,
+              IN  INT len,
+              IN  INT type)
 {
     UNIMPLEMENTED
 
@@ -498,7 +621,7 @@ gethostbyaddr(
 }
 
 /*
-  Assumes rfc 1123 - adam * 
+  Assumes rfc 1123 - adam *
    addr[1] = 0;
     addr[0] = inet_addr(name);
     strcpy( hostname, name );
@@ -532,7 +655,7 @@ servent -- w32api/include/winsock2.h
 PWINSOCK_THREAD_BLOCK -- ws2_32.h
 dllmain.c -- threadlocal memory allocation / deallocation
 lib/dnsapi
-      
+
 
 */
       /* lib/adns/src/adns.h XXX */
@@ -558,125 +681,347 @@ struct  servent {
 struct hostent defined in w32api/include/winsock2.h
 */
 
-void free_servent(struct servent* s) {
-  HFREE(s->s_name);
-  char* next = s->s_aliases[0];
-  while(next) { HFREE(next); next++; }
-  s->s_port = 0;
-  HFREE(s->s_proto);
-  HFREE(s);
+void free_servent(struct servent* s)
+{
+    char* next;
+    HFREE(s->s_name);
+    next = s->s_aliases[0];
+    while(next) { HFREE(next); next++; }
+    s->s_port = 0;
+    HFREE(s->s_proto);
+    HFREE(s);
 }
 
-
+/* This function is far from perfect but it works enough */
+static
 LPHOSTENT
-EXPORT
-gethostbyname(
-    IN  CONST CHAR FAR* name)
+FindEntryInHosts(IN CONST CHAR FAR* name)
 {
-  enum addr_type{ GH_INVALID, GH_IPV6, GH_IPV4, GH_RFC1123_DNS };
-  typedef enum addr_type addr_type;
-  addr_type addr;
-  int ret = 0;
-  char* found = 0;
-  DNS_STATUS dns_status = {0};
-  /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
-  PDNS_RECORD dp = 0;
+    BOOL Found = FALSE;
+    HANDLE HostsFile;
+    CHAR HostsDBData[BUFSIZ] = { 0 };
+    PCHAR SystemDirectory = HostsDBData;
+    PCHAR HostsLocation = "\\drivers\\etc\\hosts";
+    PCHAR AddressStr, DnsName = NULL, AddrTerm, NameSt, NextLine, ThisLine, Comment;
+    UINT SystemDirSize = sizeof(HostsDBData) - 1, ValidData = 0;
+    DWORD ReadSize;
+    ULONG Address;
+    PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
 
-  addr = GH_INVALID;
+    /* We assume that the parameters are valid */
 
-  PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
+    if (!GetSystemDirectoryA(SystemDirectory, SystemDirSize))
+    {
+        WSASetLastError(WSANO_RECOVERY);
+        WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
+        return NULL; /* Can't get system directory */
+    }
 
-  if( !p ) {
-    WSASetLastError( WSANOTINITIALISED );
-    return NULL;
-  }
+    strncat(SystemDirectory,
+            HostsLocation,
+            SystemDirSize );
+
+    HostsFile = CreateFileA(SystemDirectory,
+                            GENERIC_READ,
+                            FILE_SHARE_READ,
+                            NULL,
+                            OPEN_EXISTING,
+                            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+                            NULL);
+    if (HostsFile == INVALID_HANDLE_VALUE)
+    {
+        WSASetLastError(WSANO_RECOVERY);
+        return NULL;
+    }
 
-  check_hostent(&p->Hostent);   /*XXX alloc_hostent*/
+    while(!Found &&
+          ReadFile(HostsFile,
+                   HostsDBData + ValidData,
+                   sizeof(HostsDBData) - ValidData,
+                   &ReadSize,
+                   NULL))
+    {
+        ValidData += ReadSize;
+        ReadSize = 0;
+        NextLine = ThisLine = HostsDBData;
+
+        /* Find the beginning of the next line */
+        while(NextLine < HostsDBData + ValidData &&
+              *NextLine != '\r' && *NextLine != '\n' )
+        {
+            NextLine++;
+        }
+
+        /* Zero and skip, so we can treat what we have as a string */
+        if( NextLine > HostsDBData + ValidData )
+            break;
+
+        *NextLine = 0; NextLine++;
+
+        Comment = strchr( ThisLine, '#' );
+        if( Comment ) *Comment = 0; /* Terminate at comment start */
+
+        AddressStr = ThisLine;
+        /* Find the first space separating the IP address from the DNS name */
+        AddrTerm = strchr(ThisLine, ' ');
+        if (AddrTerm)
+        {
+           /* Terminate the address string */
+           *AddrTerm = 0;
+
+           /* Find the last space before the DNS name */
+           NameSt = strrchr(ThisLine, ' ');
+
+           /* If there is only one space (the one we removed above), then just use the address terminator */
+           if (!NameSt)
+               NameSt = AddrTerm;
+
+           /* Move from the space to the first character of the DNS name */
+           NameSt++;
+
+           DnsName = NameSt;
+
+           if (!strcmp(name, DnsName))
+           {
+               Found = TRUE;
+               break;
+           }
+        }
+
+        /* Get rid of everything we read so far */
+        while( NextLine <= HostsDBData + ValidData &&
+               isspace (*NextLine))
+        {
+            NextLine++;
+        }
+
+        if (HostsDBData + ValidData - NextLine <= 0)
+            break;
+
+        WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
+                    HostsDBData + ValidData - NextLine));
+
+        memmove(HostsDBData,
+                NextLine,
+                HostsDBData + ValidData - NextLine );
+        ValidData -= NextLine - HostsDBData;
+        WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
+    }
+
+    CloseHandle(HostsFile);
+
+    if (!Found)
+    {
+        WS_DbgPrint(MAX_TRACE,("Not found\n"));
+        WSASetLastError(WSANO_DATA);
+        return NULL;
+    }
+
+    if( !p->Hostent )
+    {
+        p->Hostent = HeapAlloc(GlobalHeap, 0, sizeof(*p->Hostent));
+        if( !p->Hostent )
+        {
+            WSASetLastError( WSATRY_AGAIN );
+            return NULL;
+        }
+    }
+
+    p->Hostent->h_name = HeapAlloc(GlobalHeap, 0, strlen(DnsName));
+    if( !p->Hostent->h_name )
+    {
+        WSASetLastError( WSATRY_AGAIN );
+        return NULL;
+    }
+
+    RtlCopyMemory(p->Hostent->h_name,
+                  DnsName,
+                  strlen(DnsName));
+
+    p->Hostent->h_aliases = HeapAlloc(GlobalHeap, 0, sizeof(char *));
+    if( !p->Hostent->h_aliases )
+    {
+        WSASetLastError( WSATRY_AGAIN );
+        return NULL;
+    }
+
+    p->Hostent->h_aliases[0] = 0;
+
+    if (strstr(AddressStr, ":"))
+    {
+       DbgPrint("AF_INET6 NOT SUPPORTED!\n");
+       WSASetLastError(WSAEINVAL);
+       return NULL;
+    }
+    else
+       p->Hostent->h_addrtype = AF_INET;
+
+    p->Hostent->h_addr_list = HeapAlloc(GlobalHeap, 0, sizeof(char *));
+    if( !p->Hostent->h_addr_list )
+    {
+        WSASetLastError( WSATRY_AGAIN );
+        return NULL;
+    }
+
+    Address = inet_addr(AddressStr);
+    if (Address == INADDR_NONE)
+    {
+        WSASetLastError(WSAEINVAL);
+        return NULL;
+    }
+
+    p->Hostent->h_addr_list[0] = HeapAlloc(GlobalHeap, 0, sizeof(Address));
+    if( !p->Hostent->h_addr_list[0] )
+    {
+        WSASetLastError( WSATRY_AGAIN );
+        return NULL;
+    }
+
+    RtlCopyMemory(p->Hostent->h_addr_list[0],
+                  &Address,
+                  sizeof(Address));
+
+    p->Hostent->h_length = sizeof(Address);
 
-  /* Hostname NULL - behave like gethostname */
-  if(name == NULL) {
-    ret = gethostname(p->Hostent->h_name, MAX_HOSTNAME_LEN);
     return p->Hostent;
-  }
+}
 
-  if(ret) {
-    WSASetLastError( WSAHOST_NOT_FOUND ); //WSANO_DATA  ??
-    return NULL;
-  }
+LPHOSTENT
+EXPORT
+gethostbyname(IN  CONST CHAR FAR* name)
+{
+    enum addr_type
+    {
+        GH_INVALID,
+        GH_IPV6,
+        GH_IPV4,
+        GH_RFC1123_DNS
+    };
+    typedef enum addr_type addr_type;
+    addr_type addr;
+    int ret = 0;
+    char* found = 0;
+    DNS_STATUS dns_status = {0};
+    /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
+    PDNS_RECORD dp = 0;
+    PWINSOCK_THREAD_BLOCK p;
+    LPHOSTENT Hostent;
+
+    addr = GH_INVALID;
+
+    p = NtCurrentTeb()->WinSockData;
+
+    if( !p )
+    {
+        WSASetLastError( WSANOTINITIALISED );
+        return NULL;
+    }
 
-  /* Is it an IPv6 address? */
-  found = strstr(name, ":");
-  if( found != NULL ) {
-    addr = GH_IPV6;
-    goto act;
-  }
+    check_hostent(&p->Hostent);   /*XXX alloc_hostent*/
 
-  /* Is it an IPv4 address? */
-  if (!isalpha(name[0])) {
-    addr = GH_IPV4;
-    goto act;
-  }
+    /* Hostname NULL - behave like gethostname */
+    if(name == NULL)
+    {
+        ret = gethostname(p->Hostent->h_name, MAX_HOSTNAME_LEN);
+        return p->Hostent;
+    }
 
- addr = GH_RFC1123_DNS;
+    if(ret)
+    {
+        WSASetLastError( WSAHOST_NOT_FOUND ); //WSANO_DATA  ??
+        return NULL;
+    }
+
+    /* Is it an IPv6 address? */
+    found = strstr(name, ":");
+    if( found != NULL )
+    {
+        addr = GH_IPV6;
+        goto act;
+    }
+
+    /* Is it an IPv4 address? */
+    if (!isalpha(name[0]))
+    {
+        addr = GH_IPV4;
+        goto act;
+    }
+
+    addr = GH_RFC1123_DNS;
 
  /* Broken out in case we want to get fancy later */
  act:
-    switch(addr){
-      case GH_IPV6:
-       WSASetLastError(STATUS_NOT_IMPLEMENTED);
-       return NULL;
-       break;
-
-    case GH_INVALID:
-      WSASetLastError(WSAEFAULT);
-      return NULL;
-      break;
-
-    /* Note: If passed an IP address, MSDN says that gethostbyname()
-             treats it as an unknown host.
-       This is different from the unix implementation. Use inet_addr()
-    */
-    case GH_IPV4:
-    case GH_RFC1123_DNS:
-      /* DNS_TYPE_A: include/WinDNS.h */
-      /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
-      dns_status = DnsQuery_A ( name, DNS_TYPE_A, DNS_QUERY_STANDARD,
-                               0, /* extra dns servers */ &dp, 0 );
-
-      if(dns_status == 0) {
-       //ASSERT(dp->wType == DNS_TYPE_A);
-       //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
-       PDNS_RECORD curr;
-       for(curr=dp;
-           curr != NULL && curr->wType != DNS_TYPE_A;
-           curr = curr->pNext ) { 
-         WS_DbgPrint(MID_TRACE,("wType: %i\n", curr->wType));
-         /*empty */ 
-       }
-
-       if(curr) {
-         WS_DbgPrint(MID_TRACE,("populating hostent\n"));
-         WS_DbgPrint(MID_TRACE,("pName is (%s)\n", curr->pName));
-         populate_hostent(p->Hostent, (PCHAR)curr->pName, curr->Data.A);
-         DnsRecordListFree(dp, DnsFreeRecordList);
-         return p->Hostent;
-       } else {
-         DnsRecordListFree(dp, DnsFreeRecordList);
-       }
-      }
-
-      WS_DbgPrint(MID_TRACE,("Called DnsQuery, but host not found. Err: %i\n",
-                            dns_status));
-      WSASetLastError(WSAHOST_NOT_FOUND);
-      return NULL;
-      
-      break;
+    switch(addr)
+    {
+        case GH_IPV6:
+            WSASetLastError(STATUS_NOT_IMPLEMENTED);
+            return NULL;
+        break;
+
+        case GH_INVALID:
+            WSASetLastError(WSAEFAULT);
+            return NULL;
+        break;
+
+        /* Note: If passed an IP address, MSDN says that gethostbyname()
+                 treats it as an unknown host.
+           This is different from the unix implementation. Use inet_addr()
+        */
+        case GH_IPV4:
+        case GH_RFC1123_DNS:
+        /* DNS_TYPE_A: include/WinDNS.h */
+        /* DnsQuery -- lib/dnsapi/dnsapi/query.c */
+
+        /* Look for the DNS name in the hosts file */
+        Hostent = FindEntryInHosts(name);
+        if (Hostent)
+           return Hostent;
+
+        dns_status = DnsQuery_A(name,
+                                DNS_TYPE_A,
+                                DNS_QUERY_STANDARD,
+                                0,
+                                /* extra dns servers */ &dp,
+                                0);
+
+        if(dns_status == 0)
+        {
+            //ASSERT(dp->wType == DNS_TYPE_A);
+            //ASSERT(dp->wDataLength == sizeof(DNS_A_DATA));
+            PDNS_RECORD curr;
+            for(curr=dp;
+                curr != NULL && curr->wType != DNS_TYPE_A;
+                curr = curr->pNext )
+            {
+                WS_DbgPrint(MID_TRACE,("wType: %i\n", curr->wType));
+                /*empty */
+            }
+
+            if(curr)
+            {
+                WS_DbgPrint(MID_TRACE,("populating hostent\n"));
+                WS_DbgPrint(MID_TRACE,("pName is (%s)\n", curr->pName));
+                populate_hostent(p->Hostent, (PCHAR)curr->pName, curr->Data.A);
+                DnsRecordListFree(dp, DnsFreeRecordList);
+                return p->Hostent;
+            }
+            else
+            {
+                DnsRecordListFree(dp, DnsFreeRecordList);
+            }
+        }
+
+        WS_DbgPrint(MID_TRACE,("Called DnsQuery, but host not found. Err: %i\n",
+                    dns_status));
+        WSASetLastError(WSAHOST_NOT_FOUND);
+        return NULL;
 
-    default:
-      WSASetLastError(WSANO_RECOVERY);
-      return NULL;
-      break;
+        break;
+
+        default:
+            WSASetLastError(WSANO_RECOVERY);
+            return NULL;
+        break;
     }
 
     WSASetLastError(WSANO_RECOVERY);
@@ -688,20 +1033,24 @@ gethostbyname(
  */
 INT
 EXPORT
-gethostname(
-    OUT CHAR FAR* name,
-    IN  INT namelen)
+gethostname(OUT CHAR FAR* name,
+            IN  INT namelen)
 {
-  DWORD size = namelen;
-  
-  int ret = GetComputerNameExA(ComputerNameDnsHostname, name, &size);
-  if(ret == 0) {
-    WSASetLastError(WSAEFAULT);
-    return SOCKET_ERROR;
-  } else {
-    name[namelen-1] = '\0';
-    return 0;
-  }
+    DWORD size = namelen;
+
+    int ret = GetComputerNameExA(ComputerNameDnsHostname,
+                                 name,
+                                 &size);
+    if(ret == 0)
+    {
+        WSASetLastError(WSAEFAULT);
+        return SOCKET_ERROR;
+    }
+    else
+    {
+        name[namelen-1] = '\0';
+        return 0;
+    }
 }
 
 
@@ -715,22 +1064,27 @@ gethostname(
  *
  * @unimplemented
  */
+static CHAR *no_aliases = 0;
+static PROTOENT protocols[] =
+{
+    {"icmp",&no_aliases, IPPROTO_ICMP},
+    {"tcp", &no_aliases, IPPROTO_TCP},
+    {"udp", &no_aliases, IPPROTO_UDP},
+    {NULL, NULL, 0}
+};
 LPPROTOENT
 EXPORT
-getprotobyname(
-    IN  CONST CHAR FAR* name)
+getprotobyname(IN  CONST CHAR FAR* name)
 {
-    static CHAR *udp_aliases = 0;
-    static PROTOENT udp = { "udp", &udp_aliases, 17 };
-    static CHAR *tcp_aliases = 0;
-    static PROTOENT tcp = { "tcp", &tcp_aliases, 6 };
-    if( !_stricmp( name, "udp" ) ) {
-       return &udp;
-    } else if( !_stricmp( name, "tcp" ) ) {
-       return &tcp;
+    UINT i;
+    for (i = 0; protocols[i].p_name; i++)
+    {
+       if (_stricmp(protocols[i].p_name, name) == 0)
+         return &protocols[i];
     }
-    
-    return 0;
+    return NULL;
 }
 
 /*
@@ -738,12 +1092,15 @@ getprotobyname(
  */
 LPPROTOENT
 EXPORT
-getprotobynumber(
-    IN  INT number)
+getprotobynumber(IN  INT number)
 {
-    UNIMPLEMENTED
-
-    return (LPPROTOENT)NULL;
+    UINT i;
+    for (i = 0; protocols[i].p_name; i++)
+    {
+       if (protocols[i].p_proto == number)
+         return &protocols[i];
+    }
+    return NULL;
 }
 
 #define SKIPWS(ptr,act) \
@@ -751,14 +1108,16 @@ getprotobynumber(
 #define SKIPANDMARKSTR(ptr,act) \
 {while(*ptr && !isspace(*ptr)) ptr++; \
  if(!*ptr) {act;} else { *ptr = 0; ptr++; }}
 
-static BOOL DecodeServEntFromString( IN  PCHAR ServiceString,
-                                    OUT PCHAR *ServiceName,
-                                    OUT PCHAR *PortNumberStr,
-                                    OUT PCHAR *ProtocolStr,
-                                    IN  PCHAR *Aliases,
-                                    IN  DWORD MaxAlias ) {
+
+static BOOL
+DecodeServEntFromString(IN  PCHAR ServiceString,
+                        OUT PCHAR *ServiceName,
+                        OUT PCHAR *PortNumberStr,
+                        OUT PCHAR *ProtocolStr,
+                        IN  PCHAR *Aliases,
+                        IN  DWORD MaxAlias)
+{
     UINT NAliases = 0;
 
     WS_DbgPrint(MAX_TRACE, ("Parsing service ent [%s]\n", ServiceString));
@@ -770,16 +1129,19 @@ static BOOL DecodeServEntFromString( IN  PCHAR ServiceString,
     *PortNumberStr = ServiceString;
     SKIPANDMARKSTR(ServiceString, ;);
 
-    while( *ServiceString && NAliases < MaxAlias - 1 ) {
-       SKIPWS(ServiceString, break);
-       if( *ServiceString ) {
-           SKIPANDMARKSTR(ServiceString, ;);
-           if( strlen(ServiceString) ) {
-               WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString));
-               *Aliases++ = ServiceString;
-               NAliases++;
-           }
-       }
+    while( *ServiceString && NAliases < MaxAlias - 1 )
+    {
+        SKIPWS(ServiceString, break);
+        if( *ServiceString )
+        {
+            SKIPANDMARKSTR(ServiceString, ;);
+            if( strlen(ServiceString) )
+            {
+                WS_DbgPrint(MAX_TRACE, ("Alias: %s\n", ServiceString));
+                *Aliases++ = ServiceString;
+                NAliases++;
+            }
+        }
     }
     *Aliases = NULL;
 
@@ -788,8 +1150,8 @@ static BOOL DecodeServEntFromString( IN  PCHAR ServiceString,
     **ProtocolStr = 0; (*ProtocolStr)++;
 
     WS_DbgPrint(MAX_TRACE, ("Parsing done: %s %s %s %d\n",
-                           *ServiceName, *ProtocolStr, *PortNumberStr,
-                           NAliases));
+                *ServiceName, *ProtocolStr, *PortNumberStr,
+                NAliases));
 
     return TRUE;
 }
@@ -801,57 +1163,60 @@ static BOOL DecodeServEntFromString( IN  PCHAR ServiceString,
  */
 LPSERVENT
 EXPORT
-getservbyname(
-
-    IN  CONST CHAR FAR* name, 
-    IN  CONST CHAR FAR* proto)
+getservbyname(IN  CONST CHAR FAR* name,
+              IN  CONST CHAR FAR* proto)
 {
     BOOL  Found = FALSE;
     HANDLE ServicesFile;
     CHAR ServiceDBData[BUFSIZ] = { 0 };
     PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */
     PCHAR ServicesFileLocation = "\\drivers\\etc\\services";
-    PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0, 
-       ProtocolStr = 0, Comment = 0;
+    PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
+    ProtocolStr = 0, Comment = 0;
     PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
-    UINT i,SizeNeeded = 0, 
-       SystemDirSize = sizeof(ServiceDBData) - 1;
+    UINT i,SizeNeeded = 0,
+    SystemDirSize = sizeof(ServiceDBData) - 1;
     DWORD ReadSize = 0, ValidData = 0;
     PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
-    
-    if( !p ) {
-       WSASetLastError( WSANOTINITIALISED );
-       return NULL;
+
+    if( !p )
+    {
+        WSASetLastError( WSANOTINITIALISED );
+        return NULL;
     }
 
-    if( !name ) {
-       WSASetLastError( WSANO_RECOVERY );
-       return NULL;
+    if( !name )
+    {
+        WSASetLastError( WSANO_RECOVERY );
+        return NULL;
     }
-    
-    if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) ) {
-       WSASetLastError( WSANO_RECOVERY );
-       WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
-       return NULL; /* Can't get system directory */
+
+    if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) )
+    {
+        WSASetLastError( WSANO_RECOVERY );
+        WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
+        return NULL; /* Can't get system directory */
     }
-    
-    strncat( SystemDirectory, ServicesFileLocation, SystemDirSize );
-
-    ServicesFile = CreateFileA( SystemDirectory,
-                               GENERIC_READ,
-                               FILE_SHARE_READ,
-                               NULL,
-                               OPEN_EXISTING,
-                               FILE_ATTRIBUTE_NORMAL | 
-                               FILE_FLAG_SEQUENTIAL_SCAN,
-                               NULL );
-
-    if( ServicesFile == INVALID_HANDLE_VALUE ) {
-       WSASetLastError( WSANO_RECOVERY );
-       return NULL;
+
+    strncat(SystemDirectory,
+            ServicesFileLocation,
+            SystemDirSize );
+
+    ServicesFile = CreateFileA(SystemDirectory,
+                               GENERIC_READ,
+                               FILE_SHARE_READ,
+                               NULL,
+                               OPEN_EXISTING,
+                               FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+                               NULL );
+
+    if( ServicesFile == INVALID_HANDLE_VALUE )
+    {
+        WSASetLastError( WSANO_RECOVERY );
+        return NULL;
     }
 
-    /* Scan the services file ... 
+    /* Scan the services file ...
      *
      * We will read up to BUFSIZ bytes per pass, until the buffer does not
      * contain a full line, then we will try to read more.
@@ -860,95 +1225,113 @@ getservbyname(
      */
 
     /* Initial Read */
-    while( !Found &&
-          ReadFile( ServicesFile, ServiceDBData + ValidData,
-                    sizeof( ServiceDBData ) - ValidData,
-                    &ReadSize, NULL ) ) {
-       ValidData += ReadSize;
-       ReadSize = 0;
-       NextLine = ThisLine = ServiceDBData;
-
-       /* Find the beginning of the next line */
-       while( NextLine < ServiceDBData + ValidData &&
-              *NextLine != '\r' && *NextLine != '\n' ) NextLine++;
-       
-       /* Zero and skip, so we can treat what we have as a string */
-       if( NextLine >= ServiceDBData + ValidData ) 
-           break;
-
-       *NextLine = 0; NextLine++;
-
-       Comment = strchr( ThisLine, '#' );
-       if( Comment ) *Comment = 0; /* Terminate at comment start */
-
-       if( DecodeServEntFromString( ThisLine, 
-                                    &ServiceName, 
-                                    &PortNumberStr,
-                                    &ProtocolStr,
-                                    Aliases,
-                                    WS2_INTERNAL_MAX_ALIAS ) &&
-           !strcmp( ServiceName, name ) &&
-           (proto ? !strcmp( ProtocolStr, proto ) : TRUE) ) {
-
-           WS_DbgPrint(MAX_TRACE,("Found the service entry.\n"));
-           Found = TRUE;
-           SizeNeeded = sizeof(WINSOCK_GETSERVBYNAME_CACHE) + 
-               (NextLine - ThisLine);
-           break;
-       }
-
-       /* Get rid of everything we read so far */
-       while( NextLine <= ServiceDBData + ValidData &&
-              isspace( *NextLine ) ) NextLine++;
-
-       WS_DbgPrint(MAX_TRACE,("About to move %d chars\n", 
-                              ServiceDBData + ValidData - NextLine));
-
-       memmove( ServiceDBData, NextLine, 
-                ServiceDBData + ValidData - NextLine );
-       ValidData -= NextLine - ServiceDBData;
-       WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
+    while(!Found &&
+          ReadFile(ServicesFile,
+                   ServiceDBData + ValidData,
+                   sizeof( ServiceDBData ) - ValidData,
+                   &ReadSize,
+                   NULL))
+    {
+        ValidData += ReadSize;
+        ReadSize = 0;
+        NextLine = ThisLine = ServiceDBData;
+
+        /* Find the beginning of the next line */
+        while(NextLine < ServiceDBData + ValidData &&
+              *NextLine != '\r' && *NextLine != '\n' )
+        {
+            NextLine++;
+        }
+
+        /* Zero and skip, so we can treat what we have as a string */
+        if( NextLine > ServiceDBData + ValidData )
+            break;
+
+        *NextLine = 0; NextLine++;
+
+        Comment = strchr( ThisLine, '#' );
+        if( Comment ) *Comment = 0; /* Terminate at comment start */
+
+        if(DecodeServEntFromString(ThisLine,
+                                   &ServiceName,
+                                   &PortNumberStr,
+                                   &ProtocolStr,
+                                   Aliases,
+                                   WS2_INTERNAL_MAX_ALIAS) &&
+           !strcmp( ServiceName, name ) &&
+           (proto ? !strcmp( ProtocolStr, proto ) : TRUE) )
+        {
+
+            WS_DbgPrint(MAX_TRACE,("Found the service entry.\n"));
+            Found = TRUE;
+            SizeNeeded = sizeof(WINSOCK_GETSERVBYNAME_CACHE) +
+                (NextLine - ThisLine);
+            break;
+        }
+
+        /* Get rid of everything we read so far */
+        while( NextLine <= ServiceDBData + ValidData &&
+               isspace( *NextLine ) )
+        {
+            NextLine++;
+        }
+
+        WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
+                    ServiceDBData + ValidData - NextLine));
+
+        memmove(ServiceDBData,
+                NextLine,
+                ServiceDBData + ValidData - NextLine );
+        ValidData -= NextLine - ServiceDBData;
+        WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
     }
 
     /* This we'll do no matter what */
     CloseHandle( ServicesFile );
-    
-    if( !Found ) {
-       WS_DbgPrint(MAX_TRACE,("Not found\n"));
-       WSASetLastError( WSANO_DATA );
-       return NULL;
+
+    if( !Found )
+    {
+        WS_DbgPrint(MAX_TRACE,("Not found\n"));
+        WSASetLastError( WSANO_DATA );
+        return NULL;
     }
-    
-    if( !p->Getservbyname || p->Getservbyname->Size < SizeNeeded ) {
-       /* Free previous getservbyname buffer, allocate bigger */
-       if( p->Getservbyname ) 
-           HeapFree(GlobalHeap, 0, p->Getservbyname);
-       p->Getservbyname = HeapAlloc(GlobalHeap, 0, SizeNeeded);
-       if( !p->Getservbyname ) {
-           WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n", 
-                                  SizeNeeded));
-           WSASetLastError( WSATRY_AGAIN );
-           return NULL;
-       }
-       p->Getservbyname->Size = SizeNeeded;
+
+    if( !p->Getservbyname || p->Getservbyname->Size < SizeNeeded )
+    {
+        /* Free previous getservbyname buffer, allocate bigger */
+        if( p->Getservbyname )
+            HeapFree(GlobalHeap, 0, p->Getservbyname);
+        p->Getservbyname = HeapAlloc(GlobalHeap, 0, SizeNeeded);
+        if( !p->Getservbyname )
+        {
+            WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n",
+                        SizeNeeded));
+            WSASetLastError( WSATRY_AGAIN );
+            return NULL;
+        }
+        p->Getservbyname->Size = SizeNeeded;
     }
 
     /* Copy the data */
-    memmove( p->Getservbyname->Data, 
-            ThisLine,
-            NextLine - ThisLine );
+    memmove(p->Getservbyname->Data,
+            ThisLine,
+            NextLine - ThisLine );
 
     ADJ_PTR(ServiceName,ThisLine,p->Getservbyname->Data);
     ADJ_PTR(ProtocolStr,ThisLine,p->Getservbyname->Data);
-    WS_DbgPrint(MAX_TRACE,
-               ("ServiceName: %s, Protocol: %s\n", ServiceName, ProtocolStr));
-               
-    for( i = 0; Aliases[i]; i++ ) {
-       ADJ_PTR(Aliases[i],ThisLine,p->Getservbyname->Data);
-       WS_DbgPrint(MAX_TRACE,("Aliase %d: %s\n", i, Aliases[i]));
+    WS_DbgPrint(MAX_TRACE, ("ServiceName: %s, Protocol: %s\n",
+                ServiceName,
+                ProtocolStr));
+
+    for( i = 0; Aliases[i]; i++ )
+    {
+        ADJ_PTR(Aliases[i],ThisLine,p->Getservbyname->Data);
+        WS_DbgPrint(MAX_TRACE,("Aliase %d: %s\n", i, Aliases[i]));
     }
 
-    memcpy(p->Getservbyname,Aliases,sizeof(Aliases));
+    memcpy(p->Getservbyname,
+           Aliases,
+           sizeof(Aliases));
 
     /* Create the struct proper */
     p->Getservbyname->ServerEntry.s_name = ServiceName;
@@ -965,56 +1348,60 @@ getservbyname(
  */
 LPSERVENT
 EXPORT
-getservbyport(
-    IN  INT port, 
-    IN  CONST CHAR FAR* proto)
+getservbyport(IN  INT port,
+              IN  CONST CHAR FAR* proto)
 {
     BOOL  Found = FALSE;
     HANDLE ServicesFile;
     CHAR ServiceDBData[BUFSIZ] = { 0 };
     PCHAR SystemDirectory = ServiceDBData; /* Reuse this stack space */
     PCHAR ServicesFileLocation = "\\drivers\\etc\\services";
-    PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0, 
-       ProtocolStr = 0, Comment = 0;
+    PCHAR ThisLine = 0, NextLine = 0, ServiceName = 0, PortNumberStr = 0,
+    ProtocolStr = 0, Comment = 0;
     PCHAR Aliases[WS2_INTERNAL_MAX_ALIAS] = { 0 };
-    UINT i,SizeNeeded = 0, 
-       SystemDirSize = sizeof(ServiceDBData) - 1;
+    UINT i,SizeNeeded = 0,
+    SystemDirSize = sizeof(ServiceDBData) - 1;
     DWORD ReadSize = 0, ValidData = 0;
     PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
-    
-    if( !p ) {
-       WSASetLastError( WSANOTINITIALISED );
-       return NULL;
+
+    if( !p )
+    {
+        WSASetLastError( WSANOTINITIALISED );
+        return NULL;
     }
 
-    if ( !port ) {
+    if ( !port )
+    {
         WSASetLastError( WSANO_RECOVERY );
         return NULL;
     }
-    if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) ) {
-       WSASetLastError( WSANO_RECOVERY );
-       WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
-       return NULL; /* Can't get system directory */
+
+    if( !GetSystemDirectoryA( SystemDirectory, SystemDirSize ) )
+    {
+        WSASetLastError( WSANO_RECOVERY );
+        WS_DbgPrint(MIN_TRACE, ("Could not get windows system directory.\n"));
+        return NULL; /* Can't get system directory */
     }
-    
-    strncat( SystemDirectory, ServicesFileLocation, SystemDirSize );
-
-    ServicesFile = CreateFileA( SystemDirectory,
-                               GENERIC_READ,
-                               FILE_SHARE_READ,
-                               NULL,
-                               OPEN_EXISTING,
-                               FILE_ATTRIBUTE_NORMAL | 
-                               FILE_FLAG_SEQUENTIAL_SCAN,
-                               NULL );
-
-    if( ServicesFile == INVALID_HANDLE_VALUE ) {
-       WSASetLastError( WSANO_RECOVERY );
-       return NULL;
+
+    strncat(SystemDirectory,
+            ServicesFileLocation,
+            SystemDirSize );
+
+    ServicesFile = CreateFileA(SystemDirectory,
+                               GENERIC_READ,
+                               FILE_SHARE_READ,
+                               NULL,
+                               OPEN_EXISTING,
+                               FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+                               NULL );
+
+    if( ServicesFile == INVALID_HANDLE_VALUE )
+    {
+        WSASetLastError( WSANO_RECOVERY );
+        return NULL;
     }
 
-    /* Scan the services file ... 
+    /* Scan the services file ...
      *
      * We will read up to BUFSIZ bytes per pass, until the buffer does not
      * contain a full line, then we will try to read more.
@@ -1023,92 +1410,105 @@ getservbyport(
      */
 
     /* Initial Read */
-    while( !Found &&
-          ReadFile( ServicesFile, ServiceDBData + ValidData,
-                    sizeof( ServiceDBData ) - ValidData,
-                    &ReadSize, NULL ) ) {
-       ValidData += ReadSize;
-       ReadSize = 0;
-       NextLine = ThisLine = ServiceDBData;
-
-       /* Find the beginning of the next line */
-       while( NextLine < ServiceDBData + ValidData &&
-              *NextLine != '\r' && *NextLine != '\n' ) NextLine++;
-       
-       /* Zero and skip, so we can treat what we have as a string */
-       if( NextLine >= ServiceDBData + ValidData ) 
-           break;
-
-       *NextLine = 0; NextLine++;
-
-       Comment = strchr( ThisLine, '#' );
-       if( Comment ) *Comment = 0; /* Terminate at comment start */
-
-       if( DecodeServEntFromString( ThisLine, 
-                                    &ServiceName, 
-                                    &PortNumberStr,
-                                    &ProtocolStr,
-                                    Aliases,
-                                    WS2_INTERNAL_MAX_ALIAS ) &&
-           (htons(atoi( PortNumberStr )) == port ) &&
-           (proto ? !strcmp( ProtocolStr, proto ) : TRUE) ) {
+    while(!Found &&
+          ReadFile(ServicesFile,
+                   ServiceDBData + ValidData,
+                   sizeof( ServiceDBData ) - ValidData,
+                   &ReadSize, NULL ) )
+    {
+        ValidData += ReadSize;
+        ReadSize = 0;
+        NextLine = ThisLine = ServiceDBData;
+
+        /* Find the beginning of the next line */
+        while( NextLine < ServiceDBData + ValidData &&
+               *NextLine != '\r' && *NextLine != '\n' ) NextLine++;
+
+        /* Zero and skip, so we can treat what we have as a string */
+        if( NextLine > ServiceDBData + ValidData )
+            break;
+
+        *NextLine = 0; NextLine++;
+
+        Comment = strchr( ThisLine, '#' );
+        if( Comment ) *Comment = 0; /* Terminate at comment start */
+
+        if(DecodeServEntFromString(ThisLine,
+                                   &ServiceName,
+                                   &PortNumberStr,
+                                   &ProtocolStr,
+                                   Aliases,
+                                   WS2_INTERNAL_MAX_ALIAS ) &&
+           (htons(atoi( PortNumberStr )) == port ) &&
+           (proto ? !strcmp( ProtocolStr, proto ) : TRUE) )
+        {
 
             WS_DbgPrint(MAX_TRACE,("Found the port entry.\n"));
 
-           Found = TRUE;
-           SizeNeeded = sizeof(WINSOCK_GETSERVBYPORT_CACHE) + 
-               (NextLine - ThisLine);
-           break;
-       }
-
-       /* Get rid of everything we read so far */
-       while( NextLine <= ServiceDBData + ValidData &&
-              isspace( *NextLine ) ) NextLine++;
-
-       WS_DbgPrint(MAX_TRACE,("About to move %d chars\n", 
-                              ServiceDBData + ValidData - NextLine));
-
-       memmove( ServiceDBData, NextLine, 
-                ServiceDBData + ValidData - NextLine );
-       ValidData -= NextLine - ServiceDBData;
-       WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
+            Found = TRUE;
+            SizeNeeded = sizeof(WINSOCK_GETSERVBYPORT_CACHE) +
+            (NextLine - ThisLine);
+            break;
+        }
+
+        /* Get rid of everything we read so far */
+        while( NextLine <= ServiceDBData + ValidData &&
+               isspace( *NextLine ) )
+        {
+            NextLine++;
+        }
+
+        WS_DbgPrint(MAX_TRACE,("About to move %d chars\n",
+                    ServiceDBData + ValidData - NextLine));
+
+        memmove(ServiceDBData,
+                NextLine,
+                ServiceDBData + ValidData - NextLine );
+        ValidData -= NextLine - ServiceDBData;
+        WS_DbgPrint(MAX_TRACE,("Valid bytes: %d\n", ValidData));
     }
 
     /* This we'll do no matter what */
     CloseHandle( ServicesFile );
-    
-    if( !Found ) {
-       WS_DbgPrint(MAX_TRACE,("Not found\n"));
-       WSASetLastError( WSANO_DATA );
-       return NULL;
+
+    if( !Found )
+    {
+        WS_DbgPrint(MAX_TRACE,("Not found\n"));
+        WSASetLastError( WSANO_DATA );
+        return NULL;
     }
-    
-    if( !p->Getservbyport || p->Getservbyport->Size < SizeNeeded ) {
-       /* Free previous getservbyport buffer, allocate bigger */
-       if( p->Getservbyport ) 
-           HeapFree(GlobalHeap, 0, p->Getservbyport);
-       p->Getservbyport = HeapAlloc(GlobalHeap, 0, SizeNeeded);
-       if( !p->Getservbyport ) {
-           WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n", 
-                                  SizeNeeded));
-           WSASetLastError( WSATRY_AGAIN );
-           return NULL;
-       }
+
+    if( !p->Getservbyport || p->Getservbyport->Size < SizeNeeded )
+    {
+        /* Free previous getservbyport buffer, allocate bigger */
+        if( p->Getservbyport )
+            HeapFree(GlobalHeap, 0, p->Getservbyport);
+        p->Getservbyport = HeapAlloc(GlobalHeap,
+                                     0,
+                                     SizeNeeded);
+        if( !p->Getservbyport )
+        {
+            WS_DbgPrint(MIN_TRACE,("Couldn't allocate %d bytes\n",
+                        SizeNeeded));
+            WSASetLastError( WSATRY_AGAIN );
+            return NULL;
+        }
         p->Getservbyport->Size = SizeNeeded;
     }
     /* Copy the data */
-    memmove( p->Getservbyport->Data, 
-            ThisLine,
-            NextLine - ThisLine );
+    memmove(p->Getservbyport->Data,
+            ThisLine,
+            NextLine - ThisLine );
 
     ADJ_PTR(PortNumberStr,ThisLine,p->Getservbyport->Data);
     ADJ_PTR(ProtocolStr,ThisLine,p->Getservbyport->Data);
-    WS_DbgPrint(MAX_TRACE,
-               ("Port Number: %s, Protocol: %s\n", PortNumberStr, ProtocolStr));
-               
-    for( i = 0; Aliases[i]; i++ ) {
-       ADJ_PTR(Aliases[i],ThisLine,p->Getservbyport->Data);
-       WS_DbgPrint(MAX_TRACE,("Aliases %d: %s\n", i, Aliases[i]));
+    WS_DbgPrint(MAX_TRACE, ("Port Number: %s, Protocol: %s\n",
+                PortNumberStr, ProtocolStr));
+
+    for( i = 0; Aliases[i]; i++ )
+    {
+        ADJ_PTR(Aliases[i],ThisLine,p->Getservbyport->Data);
+        WS_DbgPrint(MAX_TRACE,("Aliases %d: %s\n", i, Aliases[i]));
     }
 
     memcpy(p->Getservbyport,Aliases,sizeof(Aliases));
@@ -1131,8 +1531,7 @@ getservbyport(
  */
 ULONG
 EXPORT
-inet_addr(
-    IN  CONST CHAR FAR* cp)
+inet_addr(IN  CONST CHAR FAR* cp)
 /*
  * FUNCTION: Converts a string containing an IPv4 address to an unsigned long
  * ARGUMENTS:
@@ -1147,13 +1546,20 @@ inet_addr(
 
     p = (PCHAR)cp;
 
+    if (!p)
+    {
+        WSASetLastError(WSAEFAULT);
+        return INADDR_NONE;
+    }
+
     if (strlen(p) == 0)
         return INADDR_NONE;
 
     if (strcmp(p, " ") == 0)
         return 0;
 
-    for (i = 0; i <= 3; i++) {
+    for (i = 0; i <= 3; i++)
+    {
         u += (strtoul(p, &p, 0) << (i * 8));
 
         if (strlen(p) == 0)
@@ -1174,8 +1580,7 @@ inet_addr(
  */
 CHAR FAR*
 EXPORT
-inet_ntoa(
-    IN  IN_ADDR in)
+inet_ntoa(IN  IN_ADDR in)
 {
     CHAR b[10];
     PCHAR p;
@@ -1192,119 +1597,202 @@ inet_ntoa(
     _itoa((in.S_un.S_addr >> 24) & 0xFF, b, 10);
     strcat(p, ".");
     strcat(p, b);
-    return (CHAR FAR*)p;
-}
 
-
-/*
- * @unimplemented
- */
-HANDLE
-EXPORT
-WSAAsyncGetHostByAddr(
-    IN  HWND hWnd,
-    IN  UINT wMsg,
-    IN  CONST CHAR FAR* addr, 
-    IN  INT len,
-    IN  INT type, 
-    OUT CHAR FAR* buf, 
-    IN  INT buflen)
-{
-    UNIMPLEMENTED
-
-    return (HANDLE)0;
-}
-
-
-/*
- * @unimplemented
- */
-HANDLE
-EXPORT
-WSAAsyncGetHostByName(
-    IN  HWND hWnd, 
-    IN  UINT wMsg,  
-    IN  CONST CHAR FAR* name, 
-    OUT CHAR FAR* buf, 
-    IN  INT buflen)
-{
-    UNIMPLEMENTED
-
-    return (HANDLE)0;
+    return (CHAR FAR*)p;
 }
 
 
 /*
- * @unimplemented
+ * @implemented
  */
-HANDLE
+VOID
 EXPORT
-WSAAsyncGetProtoByName(
-    IN  HWND hWnd,
-    IN  UINT wMsg,
-    IN  CONST CHAR FAR* name,
-    OUT CHAR FAR* buf,
-    IN  INT buflen)
+freeaddrinfo(struct addrinfo *pAddrInfo)
 {
-    UNIMPLEMENTED
-
-    return (HANDLE)0;
+    struct addrinfo *next, *cur;
+    cur = pAddrInfo;
+    while (cur)
+    {
+        next = cur->ai_next;
+        if (cur->ai_addr)
+          HeapFree(GetProcessHeap(), 0, cur->ai_addr);
+        if (cur->ai_canonname)
+          HeapFree(GetProcessHeap(), 0, cur->ai_canonname);
+        HeapFree(GetProcessHeap(), 0, cur);
+        cur = next;
+    }
 }
 
 
-/*
- * @unimplemented
- */
-HANDLE
-EXPORT
-WSAAsyncGetProtoByNumber(
-    IN  HWND hWnd,
-    IN  UINT wMsg,
-    IN  INT number,
-    OUT CHAR FAR* buf,
-    IN  INT buflen)
+struct addrinfo *
+new_addrinfo(struct addrinfo *prev)
 {
-    UNIMPLEMENTED
-
-    return (HANDLE)0;
+    struct addrinfo *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct addrinfo));
+    if (prev)
+      prev->ai_next = ret;
+    return ret;
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
-HANDLE
+INT
 EXPORT
-WSAAsyncGetServByName(
-    IN  HWND hWnd,
-    IN  UINT wMsg,
-    IN  CONST CHAR FAR* name,
-    IN  CONST CHAR FAR* proto,
-    OUT CHAR FAR* buf,
-    IN  INT buflen)
+getaddrinfo(const char FAR * nodename,
+            const char FAR * servname,
+            const struct addrinfo FAR * hints,
+            struct addrinfo FAR * FAR * res)
 {
-    UNIMPLEMENTED
-
-    return (HANDLE)0;
-}
-
+    struct addrinfo *ret = NULL, *ai;
+    ULONG addr;
+    USHORT port;
+    struct servent *se;
+    char *proto;
+    LPPROTOENT pent;
+    DNS_STATUS dns_status;
+    PDNS_RECORD dp, currdns;
+    struct sockaddr_in *sin;
+
+    if (res == NULL)
+        return WSAEINVAL;
+    if (nodename == NULL && servname == NULL)
+        return WSAHOST_NOT_FOUND;
+        
+    if (!WSAINITIALIZED)
+        return WSANOTINITIALISED;
+
+    if (servname)
+    {
+        /* converting port number */
+        port = strtoul(servname, NULL, 10);
+        /* service name was specified? */
+        if (port == 0)
+        {
+            /* protocol was specified? */
+            if (hints && hints->ai_protocol)
+            {
+                pent = getprotobynumber(hints->ai_protocol);
+                if (pent == NULL)
+                  return WSAEINVAL;
+                proto = pent->p_name;
+            }
+            else
+                proto = NULL;
+            se = getservbyname(servname, proto);
+            if (se == NULL)
+                return WSATYPE_NOT_FOUND;
+            port = se->s_port;
+        }
+        else
+            port = htons(port);
+    }
+    else
+        port = 0;
+
+    if (nodename)
+    {
+        /* Is it an IPv6 address? */
+        if (strstr(nodename, ":"))
+            return WSAHOST_NOT_FOUND;
+            
+        /* Is it an IPv4 address? */
+        addr = inet_addr(nodename);
+        if (addr != INADDR_NONE)
+        {
+            ai = new_addrinfo(NULL);
+            ai->ai_family = PF_INET;
+            ai->ai_addrlen = sizeof(struct sockaddr_in);
+            ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen);
+            sin = (struct sockaddr_in *)ai->ai_addr;
+            sin->sin_family = AF_INET;
+            sin->sin_port = port;
+            RtlCopyMemory(&sin->sin_addr, &addr, sizeof(sin->sin_addr));
+            if (hints)
+            {
+                if (ai->ai_socktype == 0)
+                    ai->ai_socktype = hints->ai_socktype;
+                if (ai->ai_protocol == 0)
+                    ai->ai_protocol = hints->ai_protocol;
+            }
+            ret = ai;
+        }
+        else
+        {
+           /* resolving host name */
+            dns_status = DnsQuery_A(nodename,
+                                    DNS_TYPE_A,
+                                    DNS_QUERY_STANDARD,
+                                    0,
+                                    /* extra dns servers */ &dp,
+                                    0);
+
+            if (dns_status == 0)
+            {
+                ai = NULL;
+                for (currdns = dp; currdns; currdns = currdns->pNext )
+                {
+                    /* accept only A records */
+                    if (currdns->wType != DNS_TYPE_A) continue;
+                    
+                    ai = new_addrinfo(ai);
+                    if (ret == NULL)
+                      ret = ai;
+                    ai->ai_family = PF_INET;
+                    ai->ai_addrlen = sizeof(struct sockaddr_in);
+                    ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen);
+                    sin = (struct sockaddr_in *)ret->ai_addr;
+                    sin->sin_family = AF_INET;
+                    sin->sin_port = port;
+                    RtlCopyMemory(&sin->sin_addr, &currdns->Data.A.IpAddress, sizeof(sin->sin_addr));
+                    if (hints)
+                    {
+                        if (ai->ai_socktype == 0)
+                            ai->ai_socktype = hints->ai_socktype;
+                        if (ai->ai_protocol == 0)
+                            ai->ai_protocol = hints->ai_protocol;
+                    }
+                }
+                DnsRecordListFree(dp, DnsFreeRecordList);
+            }
+        }
+    }
+    else
+    {
+        ai = new_addrinfo(NULL);
+        ai->ai_family = PF_INET;
+        ai->ai_addrlen = sizeof(struct sockaddr_in);
+        ai->ai_addr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ai->ai_addrlen);
+        sin = (struct sockaddr_in *)ai->ai_addr;
+        sin->sin_family = AF_INET;
+        sin->sin_port = port;
+        if (hints)
+        {
+            if (!(hints->ai_flags & AI_PASSIVE))
+            {
+                sin->sin_addr.S_un.S_un_b.s_b1 = 127;
+                sin->sin_addr.S_un.S_un_b.s_b2 = 0;
+                sin->sin_addr.S_un.S_un_b.s_b3 = 0;
+                sin->sin_addr.S_un.S_un_b.s_b4 = 1;
+            }
+            if (ai->ai_socktype == 0)
+                ai->ai_socktype = hints->ai_socktype;
+            if (ai->ai_protocol == 0)
+                ai->ai_protocol = hints->ai_protocol;
+        }
+        ret = ai;
+    }
 
-/*
- * @unimplemented
- */
-HANDLE
-EXPORT
-WSAAsyncGetServByPort(
-    IN  HWND hWnd,
-    IN  UINT wMsg,
-    IN  INT port,
-    IN  CONST CHAR FAR* proto,
-    OUT CHAR FAR* buf,
-    IN  INT buflen)
-{
-    UNIMPLEMENTED
+    if (ret == NULL)
+        return WSAHOST_NOT_FOUND;
+        
+    if (hints && hints->ai_family != PF_UNSPEC && hints->ai_family != PF_INET)
+    {
+        freeaddrinfo(ret);
+        return WSAEAFNOSUPPORT;
+    }
 
-    return (HANDLE)0;
+    *res = ret;
+    return 0;
 }
 
 /* EOF */
-