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