]> git.xonotic.org Git - xonotic/xonotic.git/blobdiff - misc/builddeps/dp.win32/include/wspiapi.h
add DX3 headers
[xonotic/xonotic.git] / misc / builddeps / dp.win32 / include / wspiapi.h
diff --git a/misc/builddeps/dp.win32/include/wspiapi.h b/misc/builddeps/dp.win32/include/wspiapi.h
new file mode 100644 (file)
index 0000000..ba5e7c2
--- /dev/null
@@ -0,0 +1,1061 @@
+/*++\r
+\r
+Copyright (c) Microsoft Corporation. All rights reserved.\r
+\r
+Module Name:\r
+    wspiapi.h\r
+\r
+Abstract:\r
+    The file contains protocol independent API functions.\r
+\r
+Revision History:\r
+    Wed Jul 12 10:50:31 2000, Created\r
+\r
+--*/\r
+\r
+#ifndef _WSPIAPI_H_\r
+#define _WSPIAPI_H_\r
+\r
+#pragma once\r
+\r
+#if (NTDDI_VERSION >= NTDDI_WIN2K)\r
+\r
+#include <stdio.h>              // sprintf()\r
+#include <stdlib.h>             // calloc(), strtoul()\r
+#include <malloc.h>             // calloc()\r
+#include <string.h>             // strlen(), strcmp(), strstr()\r
+\r
+#if defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L\r
+\r
+#define _WSPIAPI_STRCPY_S strcpy_s\r
+#define _WSPIAPI_STRCAT_S strcat_s\r
+#define _WSPIAPI_STRNCPY_S strncpy_s\r
+#define _WSPIAPI_SPRINTF_S_1 sprintf_s\r
+\r
+#else\r
+\r
+#define _WSPIAPI_STRCPY_S(_Dst, _Size, _Src) strcpy((_Dst), (_Src))\r
+#define _WSPIAPI_STRCAT_S(_Dst, _Size, _Src) strcat((_Dst), (_Src))\r
+#define _WSPIAPI_STRNCPY_S(_Dst, _Size, _Src, _Count) strncpy((_Dst), (_Src), (_Count)); (_Dst)[(_Size) - 1] = 0\r
+#define _WSPIAPI_SPRINTF_S_1(_Dst, _Size, _Format, _Arg1) sprintf((_Dst), (_Format), (_Arg1))\r
+\r
+#endif // defined(__GOT_SECURE_LIB__) && __GOT_SECURE_LIB__ >= 200402L\r
+\r
+#if !defined(_WSPIAPI_COUNTOF)\r
+#if !defined(__cplusplus)\r
+#define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0]))\r
+#else\r
+template <typename __CountofType, size_t _N>\r
+char (&__wspiapi_countof_helper(__CountofType (&_Array)[_N]))[_N];\r
+#define _WSPIAPI_COUNTOF(_Array) sizeof(__wspiapi_countof_helper(_Array))\r
+#endif\r
+#endif\r
+\r
+#define WspiapiMalloc(tSize)    calloc(1, (tSize))\r
+#define WspiapiFree(p)          free(p)\r
+#define WspiapiSwap(a, b, c)    { (c) = (a); (a) = (b); (b) = (c); }\r
+#define getaddrinfo             WspiapiGetAddrInfo\r
+#define getnameinfo             WspiapiGetNameInfo\r
+#define freeaddrinfo            WspiapiFreeAddrInfo\r
+\r
+//\r
+// These function pointers are also within the #if (NTDDI_VERSION >= WIN2K)\r
+// because they are used by the other functions defined in this file available\r
+// only on win2k and above.\r
+//\r
+typedef int (WINAPI *WSPIAPI_PGETADDRINFO) (\r
+    IN  const char                      *nodename,\r
+    IN  const char                      *servname,\r
+    IN  const struct addrinfo           *hints,\r
+    OUT struct addrinfo                 **res);\r
+\r
+typedef int (WINAPI *WSPIAPI_PGETNAMEINFO) (\r
+    IN  const struct sockaddr           *sa,\r
+    IN  socklen_t                       salen,\r
+    OUT char                            *host,\r
+    IN  size_t                          hostlen,\r
+    OUT char                            *serv,\r
+    IN  size_t                          servlen,\r
+    IN  int                             flags);\r
+\r
+typedef void (WINAPI *WSPIAPI_PFREEADDRINFO) (\r
+    IN  struct addrinfo                 *ai);\r
+\r
+\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+    \r
+////////////////////////////////////////////////////////////\r
+// v4 only versions of getaddrinfo and friends.\r
+// NOTE: gai_strerror is inlined in ws2tcpip.h\r
+////////////////////////////////////////////////////////////\r
+\r
+__inline    \r
+char *\r
+WINAPI\r
+WspiapiStrdup (\r
+        IN  const char *                    pszString)\r
+/*++\r
+\r
+Routine Description\r
+    allocates enough storage via calloc() for a copy of the string,\r
+    copies the string into the new memory, and returns a pointer to it.\r
+\r
+Arguments\r
+    pszString       string to copy into new memory\r
+\r
+Return Value\r
+    a pointer to the newly allocated storage with the string in it.\r
+    NULL if enough memory could not be allocated, or string was NULL.\r
+\r
+--*/    \r
+{\r
+    char    *pszMemory;\r
+    size_t  cchMemory;\r
+\r
+    if (!pszString)\r
+        return(NULL);\r
+\r
+    cchMemory = strlen(pszString) + 1;\r
+    pszMemory = (char *) WspiapiMalloc(cchMemory);\r
+    if (!pszMemory)\r
+        return(NULL);\r
+\r
+    _WSPIAPI_STRCPY_S(pszMemory, cchMemory, pszString);\r
+    return pszMemory;\r
+}\r
+\r
+    \r
+    \r
+__inline\r
+BOOL\r
+WINAPI\r
+WspiapiParseV4Address (\r
+    IN  const char *                    pszAddress,\r
+    OUT PDWORD                          pdwAddress)\r
+/*++\r
+\r
+Routine Description\r
+    get the IPv4 address (in network byte order) from its string\r
+    representation.  the syntax should be a.b.c.d.\r
+    \r
+Arguments\r
+    pszArgument         string representation of the IPv4 address\r
+    ptAddress           pointer to the resulting IPv4 address\r
+\r
+Return Value\r
+    Returns FALSE if there is an error, TRUE for success.\r
+    \r
+--*/\r
+{\r
+    DWORD       dwAddress   = 0;\r
+    const char  *pcNext     = NULL;\r
+    int         iCount      = 0;\r
+\r
+    // ensure there are 3 '.' (periods)\r
+    for (pcNext = pszAddress; *pcNext != '\0'; pcNext++)\r
+        if (*pcNext == '.')\r
+            iCount++;\r
+    if (iCount != 3)\r
+        return FALSE;\r
+\r
+    // return an error if dwAddress is INADDR_NONE (255.255.255.255)\r
+    // since this is never a valid argument to getaddrinfo.\r
+    dwAddress = inet_addr(pszAddress);\r
+    if (dwAddress == INADDR_NONE)\r
+        return FALSE;\r
+\r
+    *pdwAddress = dwAddress;\r
+    return TRUE;\r
+}\r
+\r
+\r
+\r
+__inline\r
+struct addrinfo *\r
+WINAPI\r
+WspiapiNewAddrInfo (\r
+    IN  int                             iSocketType,\r
+    IN  int                             iProtocol,\r
+    IN  WORD                            wPort,\r
+    IN  DWORD                           dwAddress)\r
+/*++\r
+\r
+Routine Description\r
+    allocate an addrinfo structure and populate fields.\r
+    IPv4 specific internal function, not exported.\r
+    \r
+Arguments\r
+    iSocketType         SOCK_*.  can be wildcarded (zero).\r
+    iProtocol           IPPROTO_*.  can be wildcarded (zero).\r
+    wPort               port number of service (in network order).\r
+    dwAddress           IPv4 address (in network order).\r
+    \r
+Return Value\r
+    returns an addrinfo struct, or NULL if out of memory.\r
+\r
+--*/    \r
+{\r
+    struct addrinfo     *ptNew;\r
+    struct sockaddr_in  *ptAddress;\r
+\r
+    // allocate a new addrinfo structure.\r
+    ptNew       =\r
+        (struct addrinfo *) WspiapiMalloc(sizeof(struct addrinfo));\r
+    if (!ptNew)\r
+        return NULL;\r
+\r
+    ptAddress   =\r
+        (struct sockaddr_in *) WspiapiMalloc(sizeof(struct sockaddr_in));\r
+    if (!ptAddress)\r
+    {\r
+        WspiapiFree(ptNew);\r
+        return NULL;\r
+    }\r
+    ptAddress->sin_family       = AF_INET;\r
+    ptAddress->sin_port         = wPort;\r
+    ptAddress->sin_addr.s_addr  = dwAddress;\r
+    \r
+    // fill in the fields...\r
+    ptNew->ai_family            = PF_INET;\r
+    ptNew->ai_socktype          = iSocketType;\r
+    ptNew->ai_protocol          = iProtocol;\r
+    ptNew->ai_addrlen           = sizeof(struct sockaddr_in);\r
+    ptNew->ai_addr              = (struct sockaddr *) ptAddress;\r
+\r
+    return ptNew;\r
+}\r
+\r
+\r
+\r
+__inline\r
+int\r
+WINAPI\r
+WspiapiQueryDNS(\r
+    IN  const char                      *pszNodeName,\r
+    IN  int                             iSocketType,\r
+    IN  int                             iProtocol,  \r
+    IN  WORD                            wPort,      \r
+    OUT char                            pszAlias[NI_MAXHOST],\r
+    OUT struct addrinfo                 **pptResult)\r
+/*++\r
+\r
+Routine Description\r
+    helper routine for WspiapiLookupNode.\r
+    performs name resolution by querying the DNS for A records.\r
+    *pptResult would need to be freed if an error is returned.\r
+    \r
+Arguments\r
+    pszNodeName         name of node to resolve.\r
+    iSocketType         SOCK_*.  can be wildcarded (zero).\r
+    iProtocol           IPPROTO_*.  can be wildcarded (zero).\r
+    wPort               port number of service (in network order).\r
+    pszAlias            where to return the alias.  must be of size NI_MAXHOST.\r
+    pptResult           where to return the result.\r
+    \r
+Return Value\r
+    Returns 0 on success, an EAI_* style error value otherwise.\r
+\r
+--*/    \r
+{\r
+    struct addrinfo **pptNext   = pptResult;\r
+    struct hostent  *ptHost     = NULL;\r
+    char            **ppAddresses;\r
+\r
+    *pptNext    = NULL;\r
+    pszAlias[0] = '\0';\r
+\r
+    ptHost = gethostbyname(pszNodeName);\r
+    if (ptHost)\r
+    {\r
+        if ((ptHost->h_addrtype == AF_INET)     &&\r
+            (ptHost->h_length   == sizeof(struct in_addr)))\r
+        {\r
+            for (ppAddresses    = ptHost->h_addr_list;\r
+                 *ppAddresses   != NULL;\r
+                 ppAddresses++)\r
+            {\r
+                // create an addrinfo structure...\r
+                *pptNext = WspiapiNewAddrInfo(\r
+                    iSocketType,\r
+                    iProtocol,\r
+                    wPort,\r
+                    ((struct in_addr *) *ppAddresses)->s_addr);\r
+                if (!*pptNext)\r
+                    return EAI_MEMORY;\r
+\r
+                pptNext = &((*pptNext)->ai_next);\r
+            }\r
+        }\r
+\r
+        // pick up the canonical name.\r
+        _WSPIAPI_STRNCPY_S(pszAlias, NI_MAXHOST, ptHost->h_name, NI_MAXHOST - 1);\r
+        \r
+        return 0;\r
+    }\r
+    \r
+    switch (WSAGetLastError())\r
+    {\r
+        case WSAHOST_NOT_FOUND: return EAI_NONAME;\r
+        case WSATRY_AGAIN:      return EAI_AGAIN;\r
+        case WSANO_RECOVERY:    return EAI_FAIL;\r
+        case WSANO_DATA:        return EAI_NODATA;\r
+        default:                return EAI_NONAME;\r
+    }\r
+}\r
+\r
+\r
+\r
+__inline\r
+int\r
+WINAPI\r
+WspiapiLookupNode(\r
+    IN  const char                      *pszNodeName,\r
+    IN  int                             iSocketType,\r
+    IN  int                             iProtocol,  \r
+    IN  WORD                            wPort,      \r
+    IN  BOOL                            bAI_CANONNAME,\r
+    OUT struct addrinfo                 **pptResult)\r
+/*++\r
+\r
+Routine Description\r
+    resolve a nodename and return a list of addrinfo structures.\r
+    IPv4 specific internal function, not exported.\r
+    *pptResult would need to be freed if an error is returned.\r
+    \r
+    NOTE: if bAI_CANONNAME is true, the canonical name should be\r
+          returned in the first addrinfo structure.\r
+    \r
+Arguments\r
+    pszNodeName         name of node to resolve.\r
+    iSocketType         SOCK_*.  can be wildcarded (zero).\r
+    iProtocol           IPPROTO_*.  can be wildcarded (zero).\r
+    wPort               port number of service (in network order).\r
+    bAI_CANONNAME       whether the AI_CANONNAME flag is set.\r
+    pptResult           where to return result.\r
+    \r
+Return Value\r
+    Returns 0 on success, an EAI_* style error value otherwise.\r
+\r
+--*/\r
+{\r
+    int     iError              = 0;\r
+    int     iAliasCount         = 0;\r
+\r
+    char    szFQDN1[NI_MAXHOST] = "";\r
+    char    szFQDN2[NI_MAXHOST] = "";\r
+    char    *pszName            = szFQDN1;\r
+    char    *pszAlias           = szFQDN2;\r
+    char    *pszScratch         = NULL;\r
+    _WSPIAPI_STRNCPY_S(pszName, NI_MAXHOST, pszNodeName, NI_MAXHOST - 1);\r
+    \r
+    for (;;)\r
+    {\r
+        iError = WspiapiQueryDNS(pszNodeName,\r
+                                 iSocketType,\r
+                                 iProtocol,\r
+                                 wPort,\r
+                                 pszAlias,\r
+                                 pptResult);\r
+        if (iError)\r
+            break;\r
+\r
+        // if we found addresses, then we are done.\r
+        if (*pptResult)\r
+            break;\r
+\r
+        // stop infinite loops due to DNS misconfiguration.  there appears\r
+        // to be no particular recommended limit in RFCs 1034 and 1035.\r
+        if ((!strlen(pszAlias))             ||\r
+            (!strcmp(pszName, pszAlias))    ||\r
+            (++iAliasCount == 16))\r
+        {\r
+            iError = EAI_FAIL;\r
+            break;\r
+        }\r
+\r
+        // there was a new CNAME, look again.\r
+        WspiapiSwap(pszName, pszAlias, pszScratch);\r
+    }\r
+\r
+    if (!iError && bAI_CANONNAME)\r
+    {\r
+        (*pptResult)->ai_canonname = WspiapiStrdup(pszAlias);\r
+        if (!(*pptResult)->ai_canonname)\r
+            iError = EAI_MEMORY;\r
+    }\r
+\r
+    return iError;\r
+}\r
+\r
+\r
+\r
+__inline\r
+int\r
+WINAPI\r
+WspiapiClone (\r
+    IN  WORD                            wPort,      \r
+    IN  struct addrinfo                 *ptResult)\r
+/*++\r
+\r
+Routine Description\r
+    clone every addrinfo structure in ptResult for the UDP service.\r
+    ptResult would need to be freed if an error is returned.\r
+    \r
+Arguments\r
+    wPort               port number of UDP service.\r
+    ptResult            list of addrinfo structures, each\r
+                        of whose node needs to be cloned.\r
+\r
+Return Value\r
+    Returns 0 on success, an EAI_MEMORY on allocation failure.\r
+\r
+--*/\r
+{\r
+    struct addrinfo *ptNext = NULL;\r
+    struct addrinfo *ptNew  = NULL;\r
+\r
+    for (ptNext = ptResult; ptNext != NULL; )\r
+    {\r
+        // create an addrinfo structure...\r
+        ptNew = WspiapiNewAddrInfo(\r
+            SOCK_DGRAM,\r
+            ptNext->ai_protocol,\r
+            wPort,\r
+            ((struct sockaddr_in *) ptNext->ai_addr)->sin_addr.s_addr);\r
+        if (!ptNew)\r
+            break;\r
+\r
+        // link the cloned addrinfo\r
+        ptNew->ai_next  = ptNext->ai_next;\r
+        ptNext->ai_next = ptNew;\r
+        ptNext          = ptNew->ai_next;\r
+    }\r
+\r
+    if (ptNext != NULL)\r
+        return EAI_MEMORY;\r
+    \r
+    return 0;\r
+}\r
+\r
+\r
+\r
+__inline\r
+void\r
+WINAPI\r
+WspiapiLegacyFreeAddrInfo (\r
+    IN  struct addrinfo                 *ptHead)\r
+/*++\r
+\r
+Routine Description\r
+    Free an addrinfo structure (or chain of structures).\r
+    As specified in RFC 2553, Section 6.4.\r
+    \r
+Arguments\r
+    ptHead              structure (chain) to free\r
+    \r
+--*/    \r
+{\r
+    struct addrinfo *ptNext;    // next strcture to free\r
+\r
+    for (ptNext = ptHead; ptNext != NULL; ptNext = ptHead)\r
+    {\r
+        if (ptNext->ai_canonname)\r
+            WspiapiFree(ptNext->ai_canonname);\r
+        \r
+        if (ptNext->ai_addr)\r
+            WspiapiFree(ptNext->ai_addr);\r
+\r
+        ptHead = ptNext->ai_next;\r
+        WspiapiFree(ptNext);\r
+    }\r
+}\r
+\r
+\r
+\r
+__inline\r
+int\r
+WINAPI\r
+WspiapiLegacyGetAddrInfo(\r
+    IN const char                       *pszNodeName,\r
+    IN const char                       *pszServiceName,\r
+    IN const struct addrinfo            *ptHints,\r
+    OUT struct addrinfo                 **pptResult)\r
+/*++\r
+\r
+Routine Description\r
+    Protocol-independent name-to-address translation.\r
+    As specified in RFC 2553, Section 6.4.\r
+    This is the hacked version that only supports IPv4.\r
+    \r
+Arguments\r
+    pszNodeName         node name to lookup.\r
+    pszServiceName      service name to lookup.\r
+    ptHints             hints about how to process request.\r
+    pptResult           where to return result.\r
+    \r
+Return Value\r
+    returns zero if successful, an EAI_* error code if not.\r
+\r
+--*/    \r
+{\r
+    int                 iError      = 0;\r
+    int                 iFlags      = 0;\r
+    int                 iFamily     = PF_UNSPEC;\r
+    int                 iSocketType = 0;\r
+    int                 iProtocol   = 0;\r
+    WORD                wPort       = 0;\r
+    DWORD               dwAddress   = 0;\r
+\r
+    struct servent      *ptService  = NULL;\r
+    char                *pc         = NULL;\r
+    BOOL                bClone      = FALSE;\r
+    WORD                wTcpPort    = 0;\r
+    WORD                wUdpPort    = 0;\r
+    \r
+    \r
+    // initialize pptResult with default return value.\r
+    *pptResult  = NULL;\r
+\r
+\r
+    ////////////////////////////////////////\r
+    // validate arguments...\r
+    //\r
+    \r
+    // both the node name and the service name can't be NULL.\r
+    if ((!pszNodeName) && (!pszServiceName))\r
+        return EAI_NONAME;\r
+\r
+    // validate hints.\r
+    if (ptHints)\r
+    {\r
+        // all members other than ai_flags, ai_family, ai_socktype\r
+        // and ai_protocol must be zero or a null pointer.\r
+        if ((ptHints->ai_addrlen    != 0)       ||\r
+            (ptHints->ai_canonname  != NULL)    ||\r
+            (ptHints->ai_addr       != NULL)    ||\r
+            (ptHints->ai_next       != NULL))\r
+        {\r
+            return EAI_FAIL;\r
+        }\r
+        \r
+        // the spec has the "bad flags" error code, so presumably we\r
+        // should check something here.  insisting that there aren't\r
+        // any unspecified flags set would break forward compatibility,\r
+        // however.  so we just check for non-sensical combinations.\r
+        //\r
+        // we cannot come up with a canonical name given a null node name.\r
+        iFlags      = ptHints->ai_flags;\r
+        if ((iFlags & AI_CANONNAME) && !pszNodeName)\r
+            return EAI_BADFLAGS;\r
+\r
+        // we only support a limited number of protocol families.\r
+        iFamily     = ptHints->ai_family;\r
+        if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET))\r
+            return EAI_FAMILY;\r
+\r
+        // we only support only these socket types.\r
+        iSocketType = ptHints->ai_socktype;\r
+        if ((iSocketType != 0)                  &&\r
+            (iSocketType != SOCK_STREAM)        &&\r
+            (iSocketType != SOCK_DGRAM)         &&\r
+            (iSocketType != SOCK_RAW))\r
+            return EAI_SOCKTYPE;\r
+\r
+        // REVIEW: What if ai_socktype and ai_protocol are at odds?\r
+        iProtocol   = ptHints->ai_protocol;\r
+    }\r
+\r
+\r
+    ////////////////////////////////////////\r
+    // do service lookup...\r
+\r
+    if (pszServiceName)\r
+    {\r
+        wPort = (WORD) strtoul(pszServiceName, &pc, 10);\r
+        if (*pc == '\0')        // numeric port string\r
+        {\r
+            wPort = wTcpPort = wUdpPort = htons(wPort);\r
+            if (iSocketType == 0)\r
+            {\r
+                bClone      = TRUE;\r
+                iSocketType = SOCK_STREAM;\r
+            }\r
+        }\r
+        else                    // non numeric port string\r
+        {\r
+            if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM))\r
+            {\r
+                ptService = getservbyname(pszServiceName, "udp");\r
+                if (ptService)\r
+                    wPort = wUdpPort = ptService->s_port;\r
+            }\r
+\r
+            if ((iSocketType == 0) || (iSocketType == SOCK_STREAM))\r
+            {\r
+                ptService = getservbyname(pszServiceName, "tcp");\r
+                if (ptService)\r
+                    wPort = wTcpPort = ptService->s_port;\r
+            }\r
+            \r
+            // assumes 0 is an invalid service port...\r
+            if (wPort == 0)     // no service exists\r
+                return (iSocketType ? EAI_SERVICE : EAI_NONAME);\r
+\r
+            if (iSocketType == 0)\r
+            {\r
+                // if both tcp and udp, process tcp now & clone udp later.\r
+                iSocketType = (wTcpPort) ? SOCK_STREAM : SOCK_DGRAM;\r
+                bClone      = (wTcpPort && wUdpPort); \r
+            }\r
+        }\r
+    }\r
+    \r
+\r
+\r
+    ////////////////////////////////////////\r
+    // do node name lookup...\r
+\r
+    // if we weren't given a node name,\r
+    // return the wildcard or loopback address (depending on AI_PASSIVE).\r
+    //\r
+    // if we have a numeric host address string,\r
+    // return the binary address.\r
+    //\r
+    if ((!pszNodeName) || (WspiapiParseV4Address(pszNodeName, &dwAddress)))\r
+    {\r
+        if (!pszNodeName)\r
+        {\r
+            dwAddress = htonl((iFlags & AI_PASSIVE)\r
+                              ? INADDR_ANY\r
+                              : INADDR_LOOPBACK);\r
+        }\r
+        \r
+        // create an addrinfo structure...\r
+        *pptResult =\r
+            WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);\r
+        if (!(*pptResult))\r
+            iError = EAI_MEMORY;\r
+        \r
+        if (!iError && pszNodeName)\r
+        {\r
+            // implementation specific behavior: set AI_NUMERICHOST\r
+            // to indicate that we got a numeric host address string.\r
+            (*pptResult)->ai_flags |= AI_NUMERICHOST;\r
+            \r
+            // return the numeric address string as the canonical name\r
+            if (iFlags & AI_CANONNAME)\r
+            {\r
+                (*pptResult)->ai_canonname =\r
+                    WspiapiStrdup(inet_ntoa(*((struct in_addr *) &dwAddress)));\r
+                if (!(*pptResult)->ai_canonname)        \r
+                    iError = EAI_MEMORY;\r
+            }\r
+        }\r
+    }\r
+\r
+\r
+    // if we do not have a numeric host address string and\r
+    // AI_NUMERICHOST flag is set, return an error!\r
+    else if (iFlags & AI_NUMERICHOST)\r
+    {\r
+        iError = EAI_NONAME;\r
+    }\r
+    \r
+\r
+    // since we have a non-numeric node name,\r
+    // we have to do a regular node name lookup.\r
+    else\r
+    {\r
+        iError = WspiapiLookupNode(pszNodeName,\r
+                                   iSocketType,\r
+                                   iProtocol,\r
+                                   wPort,\r
+                                   (iFlags & AI_CANONNAME),\r
+                                   pptResult);\r
+    }\r
+\r
+    if (!iError && bClone)\r
+    {\r
+        iError = WspiapiClone(wUdpPort, *pptResult);\r
+    }\r
+\r
+    if (iError)\r
+    {\r
+        WspiapiLegacyFreeAddrInfo(*pptResult);\r
+        *pptResult  = NULL;        \r
+    }\r
+\r
+    return (iError);\r
+}\r
+\r
+\r
+\r
+__inline\r
+int\r
+WINAPI\r
+WspiapiLegacyGetNameInfo(\r
+    IN  const struct sockaddr           *ptSocketAddress,\r
+    IN  socklen_t                       tSocketLength,\r
+    OUT char                            *pszNodeName,\r
+    IN  size_t                          tNodeLength,\r
+    OUT char                            *pszServiceName,\r
+    IN  size_t                          tServiceLength,\r
+    IN  int                             iFlags)\r
+/*++\r
+\r
+Routine Description\r
+    protocol-independent address-to-name translation.\r
+    as specified in RFC 2553, Section 6.5.\r
+    this is the hacked version that only supports IPv4.\r
+    \r
+Arguments\r
+    ptSocketAddress     socket address to translate.\r
+    tSocketLength       length of above socket address.\r
+    pszNodeName         where to return the node name.\r
+    tNodeLength         size of above buffer.\r
+    pszServiceName      where to return the service name.\r
+    tServiceLength      size of above buffer.\r
+    iFlags              flags of type NI_*.\r
+    \r
+Return Value\r
+    returns zero if successful, an EAI_* error code if not.\r
+\r
+--*/    \r
+{\r
+    struct servent  *ptService;\r
+    WORD            wPort;    \r
+    char            szBuffer[]  = "65535";\r
+    char            *pszService = szBuffer;\r
+\r
+    struct hostent  *ptHost;\r
+    struct in_addr  tAddress;\r
+    char            *pszNode    = NULL;\r
+    char            *pc         = NULL;\r
+    \r
+\r
+    // sanity check ptSocketAddress and tSocketLength.\r
+    if ((!ptSocketAddress) || (tSocketLength < sizeof(struct sockaddr)))\r
+        return EAI_FAIL;\r
+    \r
+    if (ptSocketAddress->sa_family != AF_INET)\r
+        return EAI_FAMILY;\r
+\r
+    if (tSocketLength < sizeof(struct sockaddr_in))\r
+        return EAI_FAIL;\r
+    \r
+    if (!(pszNodeName && tNodeLength) &&\r
+        !(pszServiceName && tServiceLength))\r
+    {\r
+        return EAI_NONAME;    \r
+    }\r
+\r
+    // the draft has the "bad flags" error code, so presumably we\r
+    // should check something here.  insisting that there aren't\r
+    // any unspecified flags set would break forward compatibility,\r
+    // however.  so we just check for non-sensical combinations.\r
+    if ((iFlags & NI_NUMERICHOST) && (iFlags & NI_NAMEREQD))\r
+    {                                                                       \r
+        return EAI_BADFLAGS;\r
+    }\r
+        \r
+    // translate the port to a service name (if requested).\r
+    if (pszServiceName && tServiceLength)\r
+    {\r
+        wPort = ((struct sockaddr_in *) ptSocketAddress)->sin_port;\r
+        \r
+        if (iFlags & NI_NUMERICSERV)\r
+        {\r
+            // return numeric form of the address.\r
+            _WSPIAPI_SPRINTF_S_1(szBuffer, _WSPIAPI_COUNTOF(szBuffer), "%u", ntohs(wPort));\r
+        }\r
+        else\r
+        {\r
+            // return service name corresponding to port.\r
+            ptService = getservbyport(wPort,\r
+                                      (iFlags & NI_DGRAM) ? "udp" : NULL);\r
+            if (ptService && ptService->s_name)\r
+            {\r
+                // lookup successful.\r
+                pszService = ptService->s_name;\r
+            }\r
+            else\r
+            {\r
+                // DRAFT: return numeric form of the port!\r
+                _WSPIAPI_SPRINTF_S_1(szBuffer, _WSPIAPI_COUNTOF(szBuffer), "%u", ntohs(wPort));\r
+            }\r
+        }\r
+        \r
+        \r
+        if (tServiceLength > strlen(pszService))\r
+            _WSPIAPI_STRCPY_S(pszServiceName, tServiceLength, pszService);\r
+        else\r
+            return EAI_FAIL;\r
+    }\r
+\r
+    \r
+    // translate the address to a node name (if requested).\r
+    if (pszNodeName && tNodeLength)\r
+    {    \r
+        // this is the IPv4-only version, so we have an IPv4 address.\r
+        tAddress = ((struct sockaddr_in *) ptSocketAddress)->sin_addr;\r
+\r
+        if (iFlags & NI_NUMERICHOST)\r
+        {\r
+            // return numeric form of the address.\r
+            pszNode  = inet_ntoa(tAddress);\r
+        }\r
+        else\r
+        {\r
+            // return node name corresponding to address.\r
+            ptHost = gethostbyaddr((char *) &tAddress,\r
+                                   sizeof(struct in_addr),\r
+                                   AF_INET);\r
+            if (ptHost && ptHost->h_name)\r
+            {\r
+                // DNS lookup successful.\r
+                // stop copying at a "." if NI_NOFQDN is specified.\r
+                pszNode = ptHost->h_name;\r
+                if ((iFlags & NI_NOFQDN) &&\r
+                    ((pc = strchr(pszNode, '.')) != NULL))\r
+                    *pc = '\0';\r
+            }\r
+            else\r
+            {\r
+                // DNS lookup failed.  return numeric form of the address.\r
+                if (iFlags & NI_NAMEREQD)\r
+                {\r
+                    switch (WSAGetLastError())\r
+                    {\r
+                        case WSAHOST_NOT_FOUND: return EAI_NONAME;\r
+                        case WSATRY_AGAIN:      return EAI_AGAIN;\r
+                        case WSANO_RECOVERY:    return EAI_FAIL;\r
+                        default:                return EAI_NONAME;\r
+                    }\r
+                }\r
+                else\r
+                    pszNode  = inet_ntoa(tAddress);\r
+            }\r
+        }\r
+\r
+        if (tNodeLength > strlen(pszNode))\r
+            _WSPIAPI_STRCPY_S(pszNodeName, tNodeLength, pszNode);\r
+        else\r
+            return EAI_FAIL;\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+\r
+\r
+typedef struct \r
+{\r
+    char const          *pszName;\r
+    FARPROC             pfAddress;\r
+} WSPIAPI_FUNCTION;\r
+\r
+#define WSPIAPI_FUNCTION_ARRAY                                  \\r
+{                                                               \\r
+    "getaddrinfo",      (FARPROC) WspiapiLegacyGetAddrInfo,     \\r
+    "getnameinfo",      (FARPROC) WspiapiLegacyGetNameInfo,     \\r
+    "freeaddrinfo",     (FARPROC) WspiapiLegacyFreeAddrInfo,    \\r
+}\r
+\r
+\r
+\r
+__inline\r
+FARPROC\r
+WINAPI\r
+WspiapiLoad(\r
+    IN  WORD                            wFunction)\r
+/*++\r
+\r
+Routine Description\r
+    try to locate the address family independent name resolution routines\r
+    (i.e. getaddrinfo, getnameinfo, freeaddrinfo, gai_strerror).\r
+    \r
+Locks\r
+    this function call is not synchronized.  hence the library containing\r
+    the routines might be loaded multiple times.  another option is to\r
+    synchronize through a spin lock using a static local variable and the\r
+    InterlockedExchange operation.  \r
+\r
+    \r
+Arguments\r
+    wFunction           ordinal # of the function to get the pointer to\r
+                        0   getaddrinfo\r
+                        1   getnameinfo\r
+                        2   freeaddrinfo\r
+    \r
+Return Value\r
+    address of the library/legacy routine\r
+\r
+--*/\r
+{\r
+    HMODULE                 hLibrary        = NULL;\r
+\r
+    // these static variables store state across calls, across threads.\r
+    static BOOL             bInitialized    = FALSE;\r
+    static WSPIAPI_FUNCTION rgtGlobal[]     = WSPIAPI_FUNCTION_ARRAY;\r
+    static const int        iNumGlobal      = (sizeof(rgtGlobal) /\r
+                                               sizeof(WSPIAPI_FUNCTION));\r
+    \r
+    // we overwrite rgtGlobal only if all routines exist in library.\r
+    WSPIAPI_FUNCTION        rgtLocal[]      = WSPIAPI_FUNCTION_ARRAY;\r
+    FARPROC                 fScratch        = NULL;\r
+    int                     i               = 0;\r
+    \r
+    \r
+    if (bInitialized)           // WspiapiLoad has already been called once\r
+        return (rgtGlobal[wFunction].pfAddress);\r
+\r
+    for (;;)                    // breakout loop\r
+    {\r
+        CHAR SystemDir[MAX_PATH + 1];\r
+        CHAR Path[MAX_PATH + 8];\r
+\r
+        if (GetSystemDirectoryA(SystemDir, MAX_PATH) == 0) \r
+        {\r
+            break;\r
+        }\r
+\r
+        // in Whistler and beyond...\r
+        // the routines are present in the WinSock 2 library (ws2_32.dll).\r
+        // printf("Looking in ws2_32 for getaddrinfo...\n");\r
+        _WSPIAPI_STRCPY_S(Path, _WSPIAPI_COUNTOF(Path), SystemDir);\r
+        _WSPIAPI_STRCAT_S(Path, _WSPIAPI_COUNTOF(Path), "\\ws2_32");\r
+        hLibrary = LoadLibraryA(Path);\r
+        if (hLibrary != NULL)\r
+        {\r
+            fScratch = GetProcAddress(hLibrary, "getaddrinfo");\r
+            if (fScratch == NULL)\r
+            {\r
+                FreeLibrary(hLibrary);\r
+                hLibrary = NULL;\r
+            }\r
+        }\r
+        if (hLibrary != NULL)\r
+            break;\r
+        \r
+\r
+        // in the IPv6 Technology Preview...        \r
+        // the routines are present in the IPv6 WinSock library (wship6.dll).\r
+        // printf("Looking in wship6 for getaddrinfo...\n");\r
+        _WSPIAPI_STRCPY_S(Path, _WSPIAPI_COUNTOF(Path), SystemDir);\r
+        _WSPIAPI_STRCAT_S(Path, _WSPIAPI_COUNTOF(Path), "\\wship6");\r
+        hLibrary = LoadLibraryA(Path);\r
+        if (hLibrary != NULL)\r
+        {\r
+            fScratch = GetProcAddress(hLibrary, "getaddrinfo");\r
+            if (fScratch == NULL)\r
+            {\r
+                FreeLibrary(hLibrary);\r
+                hLibrary = NULL;\r
+            }\r
+        }\r
+\r
+        break;\r
+    }\r
+\r
+\r
+    if (hLibrary != NULL)\r
+    {\r
+        // use routines from this library...\r
+        // since getaddrinfo is here, we expect all routines to be here,\r
+        // but will fall back to IPv4-only if any of them is missing.\r
+        for (i = 0; i < iNumGlobal; i++)\r
+        {\r
+            rgtLocal[i].pfAddress\r
+                = GetProcAddress(hLibrary, rgtLocal[i].pszName);\r
+            if (rgtLocal[i].pfAddress == NULL)\r
+            {\r
+                FreeLibrary(hLibrary);\r
+                hLibrary = NULL;\r
+                break;\r
+            }\r
+        }\r
+\r
+        if (hLibrary != NULL)\r
+        {\r
+            // printf("found!\n");\r
+            for (i = 0; i < iNumGlobal; i++)\r
+                rgtGlobal[i].pfAddress = rgtLocal[i].pfAddress;\r
+        }\r
+    }\r
+    \r
+    bInitialized = TRUE;\r
+    return (rgtGlobal[wFunction].pfAddress);\r
+}\r
+\r
+\r
+\r
+__inline\r
+int\r
+WINAPI\r
+WspiapiGetAddrInfo(\r
+    IN const char                       *nodename,\r
+    IN const char                       *servname,\r
+    IN const struct addrinfo            *hints,\r
+    OUT struct addrinfo                 **res)\r
+{\r
+    int                             iError;\r
+    static WSPIAPI_PGETADDRINFO     pfGetAddrInfo   = NULL;\r
+    \r
+    if (!pfGetAddrInfo)\r
+        pfGetAddrInfo   = (WSPIAPI_PGETADDRINFO) WspiapiLoad(0);\r
+\r
+    iError = (*pfGetAddrInfo)(nodename, servname, hints, res);\r
+    WSASetLastError(iError);\r
+    return iError;\r
+}\r
+\r
+\r
+\r
+__inline\r
+int\r
+WINAPI\r
+WspiapiGetNameInfo (\r
+    IN  const struct sockaddr           *sa,\r
+    IN  socklen_t                       salen,\r
+    OUT char                            *host,\r
+    IN  size_t                          hostlen,\r
+    OUT char                            *serv,\r
+    IN  size_t                          servlen,\r
+    IN  int                             flags)\r
+{\r
+    int                             iError;\r
+    static WSPIAPI_PGETNAMEINFO     pfGetNameInfo   = NULL;\r
+    \r
+    if (!pfGetNameInfo)\r
+        pfGetNameInfo   = (WSPIAPI_PGETNAMEINFO) WspiapiLoad(1);\r
+\r
+    iError = (*pfGetNameInfo)(sa, salen, host, hostlen, serv, servlen, flags);\r
+    WSASetLastError(iError);\r
+    return iError;\r
+}\r
+\r
+\r
+\r
+__inline\r
+void\r
+WINAPI\r
+WspiapiFreeAddrInfo (\r
+    IN  struct addrinfo                 *ai)\r
+{\r
+    static WSPIAPI_PFREEADDRINFO    pfFreeAddrInfo   = NULL;\r
+\r
+    if (!pfFreeAddrInfo)\r
+        pfFreeAddrInfo  = (WSPIAPI_PFREEADDRINFO) WspiapiLoad(2);\r
+    (*pfFreeAddrInfo)(ai);\r
+}\r
+\r
+#ifdef  __cplusplus\r
+}\r
+#endif\r
+\r
+#endif // if (NTDDI_VERSION >= WIN2K)\r
+#endif // _WSPIAPI_H_\r
+\r