- Remove the remaining __USE_W32API, deprecated for ages.
[reactos.git] / reactos / dll / win32 / ws2_32 / misc / ns.c
index c9b29ea..bb89ead 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>
@@ -35,7 +34,8 @@ WSAAddressToStringA(IN      LPSOCKADDR lpsaAddress,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -52,7 +52,8 @@ WSAAddressToStringW(IN      LPSOCKADDR lpsaAddress,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -66,7 +67,8 @@ WSAEnumNameSpaceProvidersA(IN OUT  LPDWORD lpdwBufferLength,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -80,7 +82,8 @@ WSAEnumNameSpaceProvidersW(IN OUT  LPDWORD lpdwBufferLength,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -96,7 +99,8 @@ WSAGetServiceClassInfoA(IN      LPGUID lpProviderId,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -112,7 +116,8 @@ WSAGetServiceClassInfoW(IN      LPGUID lpProviderId,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -127,7 +132,8 @@ WSAGetServiceClassNameByClassIdA(IN      LPGUID lpServiceClassId,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -142,7 +148,8 @@ WSAGetServiceClassNameByClassIdW(IN      LPGUID lpServiceClassId,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -155,7 +162,8 @@ WSAInstallServiceClassA(IN  LPWSASERVICECLASSINFOA lpServiceClassInfo)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -168,7 +176,8 @@ WSAInstallServiceClassW(IN  LPWSASERVICECLASSINFOW lpServiceClassInfo)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -183,7 +192,8 @@ WSALookupServiceBeginA(IN  LPWSAQUERYSETA lpqsRestrictions,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -198,7 +208,8 @@ WSALookupServiceBeginW(IN  LPWSAQUERYSETW lpqsRestrictions,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -211,7 +222,8 @@ WSALookupServiceEnd(IN  HANDLE hLookup)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -227,7 +239,8 @@ WSALookupServiceNextA(IN      HANDLE hLookup,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -243,7 +256,8 @@ WSALookupServiceNextW(IN      HANDLE hLookup,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -256,7 +270,8 @@ WSARemoveServiceClass(IN  LPGUID lpServiceClassId)
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -271,7 +286,8 @@ WSASetServiceA(IN  LPWSAQUERYSETA lpqsRegInfo,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -286,7 +302,8 @@ WSASetServiceW(IN  LPWSAQUERYSETW lpqsRegInfo,
 {
     UNIMPLEMENTED
 
-    return 0;
+    WSASetLastError(WSASYSCALLFAILURE);
+    return SOCKET_ERROR;
 }
 
 
@@ -364,7 +381,7 @@ WSAStringToAddressA(IN     LPSTR AddressString,
 
 
 /*
- * @implement
+ * @implemented
  */
 INT
 EXPORT
@@ -378,14 +395,15 @@ WSAStringToAddressW(IN      LPWSTR AddressString,
     int res=0;
     LONG inetaddr = 0;
     LPWSTR *bp=NULL;
+    SOCKADDR_IN *sockaddr;
 
-    SOCKADDR_IN *sockaddr = (SOCKADDR_IN *) lpAddress;
-
-    if (!lpAddressLength || !lpAddress)
+    if (!lpAddressLength || !lpAddress || !AddressString)
+    {
+        WSASetLastError(WSAEINVAL);
         return SOCKET_ERROR;
+    }
 
-    if (AddressString==NULL)
-        return WSAEINVAL;
+    sockaddr = (SOCKADDR_IN *) lpAddress;
 
     /* Set right adress family */
     if (lpProtocolInfo!=NULL)
@@ -403,46 +421,41 @@ WSAStringToAddressW(IN      LPWSTR AddressString,
         }
         else
         {
-            if (!lpAddress)
-                res = WSAEINVAL;
-            else
-            {
-                // translate now ip string to ip
+            // translate ip string to ip
 
-                /* rest sockaddr.sin_addr.s_addr
+            /* 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));
+            memset(lpAddress,0,sizeof(SOCKADDR_IN));
 
-                /* Set right adress family */
-                sockaddr->sin_family = AF_INET;
+            /* Set right adress family */
+            sockaddr->sin_family = AF_INET;
 
-                /* Get port number */
-                pos = wcscspn(AddressString,L":") + 1;
+            /* Get port number */
+            pos = wcscspn(AddressString,L":") + 1;
 
-                if (pos < (int)wcslen(AddressString))
-                    sockaddr->sin_port = wcstol(&AddressString[pos],
-                                                bp,
-                                                10);
+            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;
+            else
+                sockaddr->sin_port = 0;
 
-                while (pos < (int)wcslen(AddressString))
-                {
-                    inetaddr = (inetaddr<<8) + ((UCHAR)wcstol(&AddressString[pos],
-                                                              bp,
-                                                              10));
-                    pos += wcscspn( &AddressString[pos],L".") +1 ;
-                }
+            /* Get ip number */
+            pos=0;
+            inetaddr=0;
 
-                res = 0;
-                sockaddr->sin_addr.s_addr = inetaddr;
+            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;
+
         }
     }
 
@@ -618,8 +631,9 @@ struct hostent defined in w32api/include/winsock2.h
 
 void free_servent(struct servent* s)
 {
+    char* next;
     HFREE(s->s_name);
-    char* next = s->s_aliases[0];
+    next = s->s_aliases[0];
     while(next) { HFREE(next); next++; }
     s->s_port = 0;
     HFREE(s->s_proto);
@@ -646,10 +660,11 @@ gethostbyname(IN  CONST CHAR FAR* name)
     DNS_STATUS dns_status = {0};
     /* include/WinDNS.h -- look up DNS_RECORD on MSDN */
     PDNS_RECORD dp = 0;
+    PWINSOCK_THREAD_BLOCK p;
 
     addr = GH_INVALID;
 
-    PWINSOCK_THREAD_BLOCK p = NtCurrentTeb()->WinSockData;
+    p = NtCurrentTeb()->WinSockData;
 
     if( !p )
     {
@@ -798,25 +813,27 @@ gethostname(OUT CHAR FAR* name,
  *
  * @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)
 {
-    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"))
+    UINT i;
+    for (i = 0; protocols[i].p_name; i++)
     {
-        return &tcp;
+       if (_stricmp(protocols[i].p_name, name) == 0)
+         return &protocols[i];
     }
-
-    return 0;
+    return NULL;
 }
 
 /*
@@ -826,9 +843,13 @@ LPPROTOENT
 EXPORT
 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) \
@@ -1274,6 +1295,12 @@ inet_addr(IN  CONST CHAR FAR* cp)
 
     p = (PCHAR)cp;
 
+    if (!p)
+    {
+        WSASetLastError(WSAEFAULT);
+        return INADDR_NONE;
+    }
+
     if (strlen(p) == 0)
         return INADDR_NONE;
 
@@ -1324,5 +1351,197 @@ inet_ntoa(IN  IN_ADDR in)
 }
 
 
-/* EOF */
+/*
+ * @implemented
+ */
+VOID
+EXPORT
+freeaddrinfo(struct addrinfo *pAddrInfo)
+{
+    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;
+    }
+}
+
+
+struct addrinfo *
+new_addrinfo(struct addrinfo *prev)
+{
+    struct addrinfo *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct addrinfo));
+    if (prev)
+      prev->ai_next = ret;
+    return ret;
+}
+
+/*
+ * @implemented
+ */
+INT
+EXPORT
+getaddrinfo(const char FAR * nodename,
+            const char FAR * servname,
+            const struct addrinfo FAR * hints,
+            struct addrinfo FAR * FAR * res)
+{
+    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;
+    }
 
+    if (ret == NULL)
+        return WSAHOST_NOT_FOUND;
+        
+    if (hints && hints->ai_family != PF_UNSPEC && hints->ai_family != PF_INET)
+    {
+        freeaddrinfo(ret);
+        return WSAEAFNOSUPPORT;
+    }
+
+    *res = ret;
+    return 0;
+}
+
+/* EOF */