ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

addrinfo.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS WinSock 2 API
00004  * FILE:        addrinfo.c
00005  * PURPOSE:     Protocol-Independent Address Resolution
00006  * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 #include "ws2_32.h"
00011 
00012 //#define NDEBUG
00013 #include <debug.h>
00014 
00015 /* DEFINES *******************************************************************/
00016 
00017 #define Swap(a, b, c)       { (c) = (a); (a) = (b); (b) = (c); }
00018 #define FreeAddrInfoW(a)    freeaddrinfo((LPADDRINFO)a)
00019 
00020 /* FUNCTIONS *****************************************************************/
00021 
00022 /* FIXME: put into dnslib */
00023 VOID
00024 WSAAPI
00025 Dns_Ip4AddressToReverseName_W(IN LPWSTR AddressBuffer,
00026                               IN IN_ADDR Address)
00027 {
00028     /* Convert the address into IPv4 format */
00029     wsprintfW(AddressBuffer, L"%u.%u.%u.%u.in-addr.arpa.",
00030               Address.S_un.S_un_b.s_b4,
00031               Address.S_un.S_un_b.s_b3,
00032               Address.S_un.S_un_b.s_b2,
00033               Address.S_un.S_un_b.s_b1);
00034 }
00035 
00036 VOID
00037 WINAPI
00038 Dns_SplitHostFromDomainNameW(IN LPWSTR DomainName)
00039 {
00040     /* FIXME */
00041 }
00042 
00043 static
00044 INT
00045 WINAPI
00046 ConvertAddrinfoFromUnicodeToAnsi(IN PADDRINFOW Addrinfo)
00047 {
00048     LPSTR AnsiName;
00049     LPWSTR *UnicodeName;
00050 
00051     /* Make sure we have a valid pointer */
00052     if (Addrinfo)
00053     {
00054         do
00055         {
00056             /* Get the name */
00057             UnicodeName = &Addrinfo->ai_canonname;
00058             
00059             /* Check if it exists */
00060             if (*UnicodeName)
00061             {
00062                 /* Convert it */
00063                 AnsiName = AnsiDupFromUnicode(*UnicodeName);
00064                 if (AnsiName)
00065                 {
00066                     /* Free the old one */
00067                     HeapFree(WsSockHeap, 0, *UnicodeName);
00068             
00069                     /* Set the new one */
00070                     *UnicodeName = (LPWSTR)AnsiName;
00071                 }
00072                 else
00073                 {
00074                     return GetLastError();
00075                 }
00076             }
00077         } while ((Addrinfo = Addrinfo->ai_next));
00078     }
00079 
00080     /* All done */
00081     return ERROR_SUCCESS;
00082 }
00083 
00084 static
00085 BOOL
00086 WINAPI
00087 ParseV4Address(IN PCWSTR AddressString,
00088                OUT PDWORD pAddress)
00089 {
00090     DWORD Address;
00091     LPWSTR Ip = 0;
00092 
00093     /* Do the conversion, don't accept wildcard */
00094     RtlIpv4StringToAddressW((LPWSTR)AddressString, 0, &Ip, (IN_ADDR *)&Address);
00095 
00096     /* Return the address and success */
00097     *pAddress = Address;
00098     return FALSE;
00099 }
00100 
00101 static
00102 PADDRINFOW
00103 WINAPI
00104 NewAddrInfo(IN INT SocketType,
00105             IN INT Protocol,
00106             IN WORD Port,
00107             IN DWORD Address)
00108 {
00109     PADDRINFOW AddrInfo;
00110     PSOCKADDR_IN SockAddress;
00111 
00112     /* Allocate a structure */
00113     AddrInfo = HeapAlloc(WsSockHeap, 0, sizeof(ADDRINFOW));
00114     if (!AddrInfo) return NULL;
00115 
00116     /* Allocate a sockaddr */
00117     SockAddress = HeapAlloc(WsSockHeap, 0, sizeof(SOCKADDR_IN));
00118     if (!SockAddress)
00119     {
00120         /* Free the addrinfo and fail */
00121         HeapFree(WsSockHeap, 0, AddrInfo);
00122         return NULL;
00123     }
00124 
00125     /* Write data for socket address */
00126     SockAddress->sin_family = AF_INET;
00127     SockAddress->sin_port = Port;
00128     SockAddress->sin_addr.s_addr = Address;
00129     
00130     /* Fill out the addrinfo */
00131     AddrInfo->ai_family = PF_INET;
00132     AddrInfo->ai_socktype = SocketType;
00133     AddrInfo->ai_protocol = Protocol;
00134     AddrInfo->ai_flags = 0;
00135     AddrInfo->ai_next = 0;
00136     AddrInfo->ai_canonname = NULL;
00137     AddrInfo->ai_addrlen = sizeof(SOCKADDR_IN);
00138     AddrInfo->ai_addr = (PSOCKADDR)SockAddress;
00139 
00140     /* Return it */
00141     return AddrInfo;
00142 }
00143 
00144 static
00145 INT
00146 WINAPI
00147 CloneAddrInfo(IN WORD Port,
00148               IN PADDRINFOW ptResult)
00149 {
00150     PADDRINFOW Next = NULL;
00151     PADDRINFOW New  = NULL;
00152 
00153     /* Loop the chain */
00154     for (Next = ptResult; Next;)
00155     {
00156         /* Create a new structure */
00157         New = NewAddrInfo(SOCK_DGRAM,
00158                           Next->ai_protocol,
00159                           Port,
00160                           ((PSOCKADDR_IN)Next->ai_addr)->sin_addr.s_addr);
00161         if (!New) break;
00162 
00163         /* Link them */
00164         New->ai_next = Next->ai_next;
00165         Next->ai_next = New;
00166         Next = New->ai_next;
00167     }
00168 
00169     /* Check if we ran out of memory */
00170     if (Next) return EAI_MEMORY;
00171     
00172     /* Return success */
00173     return 0;
00174 }
00175 
00176 static
00177 INT
00178 WINAPI
00179 QueryDNS(IN LPCSTR NodeName,
00180          IN INT SocketType,
00181          IN INT Protocol,
00182          IN WORD Port,
00183          OUT CHAR Alias[NI_MAXHOST],
00184          OUT PADDRINFOW *pptResult)
00185 {
00186     PADDRINFOW *Next = pptResult;
00187     PHOSTENT Hostent = NULL;
00188     PCHAR *Addresses;
00189 
00190     /* Assume nothing found */
00191     *Next = NULL;
00192     Alias[0] = '\0';
00193 
00194     /* Get the hostent */
00195     Hostent = gethostbyname(NodeName);
00196     if (Hostent)
00197     {
00198         /* Check for valid addresses */
00199         if ((Hostent->h_addrtype == AF_INET) &&
00200             (Hostent->h_length == sizeof(IN_ADDR)))
00201         {
00202             /* Loop every address in it */
00203             for (Addresses = Hostent->h_addr_list; *Addresses; Addresses++)
00204             {
00205                 /* Create an addrinfo structure for it*/
00206                 *Next = NewAddrInfo(SocketType,
00207                                     Protocol,
00208                                     Port,
00209                                     ((PIN_ADDR)*Addresses)->s_addr);
00210                 if (!*Next) return EAI_MEMORY;
00211 
00212                 /* Move to the next entry */
00213                 Next = &((*Next)->ai_next);
00214             }
00215         }
00216 
00217         /* Copy the canonical name */
00218         strcpy(Alias, Hostent->h_name);
00219         
00220         /* Return success */
00221         return 0;
00222     }
00223     
00224     /* Find out what the error was */
00225     switch (GetLastError())
00226     {
00227         /* Convert the Winsock Error to an EAI error */
00228         case WSAHOST_NOT_FOUND: return EAI_NONAME;
00229         case WSATRY_AGAIN: return EAI_AGAIN;
00230         case WSANO_RECOVERY: return EAI_FAIL;
00231         case WSANO_DATA: return EAI_NODATA;
00232         default: return EAI_NONAME;
00233     }
00234 }
00235 
00236 static
00237 INT
00238 WINAPI
00239 LookupNodeByAddr(IN LPWSTR pNodeBuffer,
00240                  IN DWORD NodeBufferSize,
00241                  IN BOOLEAN OnlyNodeName,
00242                  IN PVOID Addr,
00243                  IN DWORD AddrSize,
00244                  IN INT AddressFamily)
00245 {
00246     GUID LookupGuid = SVCID_DNS_TYPE_PTR;
00247     PIN_ADDR Ip4Addr = Addr;
00248     WCHAR ReverseBuffer[76];
00249     WSAQUERYSETW Restrictions, Reply;
00250     DWORD BufferLength;
00251     INT ErrorCode;
00252     HANDLE LookupHandle;
00253 
00254     /* Validate the address */
00255     if (!Addr) return WSAEFAULT;
00256 
00257     /* Make sure the family and address size match */
00258     if (AddressFamily == AF_INET6)
00259     {
00260         /* Check the address size for this type */
00261         if (AddrSize != sizeof(IN6_ADDR)) return WSAEFAULT;
00262         Ip4Addr = (PIN_ADDR)&((PIN6_ADDR)Addr)->u.Byte[12];
00263     }
00264     else if (AddressFamily == AF_INET)
00265     {
00266         /* Check the address size for this type */
00267         if (AddrSize != sizeof(IN_ADDR)) return WSAEFAULT;
00268     }
00269     else
00270     {
00271         /* Address family not supported */
00272         return WSAEAFNOSUPPORT;
00273     }
00274 
00275     /* Check if this is a mapped V4 IPv6 or pure IPv4 */
00276     if (((AddressFamily == AF_INET6) && (IN6_IS_ADDR_V4MAPPED(Addr))) ||
00277         (AddressFamily == AF_INET))
00278     {
00279         /* Get the reverse name */
00280         Dns_Ip4AddressToReverseName_W(ReverseBuffer, *Ip4Addr);
00281     }
00282     /* FIXME: Not implemented for now 
00283     else if ( */
00284 
00285     /* By this point we have the Reverse Name, so prepare for lookup */
00286     RtlZeroMemory(&Restrictions, sizeof(Restrictions));
00287     Restrictions.dwSize = sizeof(Restrictions);
00288     Restrictions.lpszServiceInstanceName = ReverseBuffer;
00289     Restrictions.lpServiceClassId = &LookupGuid;
00290     Restrictions.dwNameSpace = NS_DNS;
00291 
00292     /* Now do the lookup */
00293     ErrorCode = WSALookupServiceBeginW(&Restrictions,
00294                                        LUP_RETURN_NAME,
00295                                        &LookupHandle);
00296     if (ErrorCode == ERROR_SUCCESS)
00297     {
00298         /* Lookup succesfull, now get the data */
00299         BufferLength = (NI_MAXHOST - 1) * sizeof(WCHAR) + sizeof(Restrictions);
00300         ErrorCode = WSALookupServiceNextW(LookupHandle,
00301                                           0,
00302                                           &BufferLength,
00303                                           &Restrictions);
00304         if (ErrorCode == ERROR_SUCCESS)
00305         {
00306             /* Now check if we have a name back */
00307             Reply = Restrictions;
00308             if (!Reply.lpszServiceInstanceName)
00309             {
00310                 /* Fail */
00311                 ErrorCode = WSAHOST_NOT_FOUND;
00312             }
00313             else
00314             {
00315                 /* Check if the caller only wants the node name */
00316                 if (OnlyNodeName)
00317                 {
00318                     /* Split it and get only the partial host name */
00319                     Dns_SplitHostFromDomainNameW(Reply.lpszServiceInstanceName);
00320                 }
00321 
00322                 /* Check the length and see if it's within our limit */
00323                 if (wcslen(Reply.lpszServiceInstanceName) + 1 >
00324                     NodeBufferSize)
00325                 {
00326                     /* It's not, so fail */
00327                     ErrorCode = WSAEFAULT;
00328                 }
00329                 else
00330                 {
00331                     /* It will fit, let's copy it*/
00332                     wcscpy(pNodeBuffer, Reply.lpszServiceInstanceName);
00333                 }
00334             }
00335         }
00336     }
00337     else if (ErrorCode == WSASERVICE_NOT_FOUND)
00338     {
00339         /* Normalize the error code */
00340         ErrorCode = WSAHOST_NOT_FOUND;
00341     }
00342 
00343     /* Finish the lookup if one was in progress */
00344     if (LookupHandle) WSALookupServiceEnd(LookupHandle);
00345 
00346     /* Return the error code */
00347     return ErrorCode;
00348 }
00349 
00350 static
00351 INT
00352 WINAPI
00353 GetServiceNameForPort(IN LPWSTR pServiceBuffer,
00354                       IN DWORD ServiceBufferSize,
00355                       IN WORD Port,
00356                       IN DWORD Flags)
00357 {
00358     return ERROR_SUCCESS;
00359 }
00360 
00361 static
00362 INT
00363 WINAPI
00364 LookupAddressForName(IN LPCSTR NodeName,
00365                      IN INT SocketType,
00366                      IN INT Protocol,
00367                      IN WORD Port,
00368                      IN BOOL bAI_CANONNAME,
00369                      OUT PADDRINFOW *pptResult)
00370 {
00371     INT iError = 0;
00372     INT AliasCount = 0;
00373     CHAR szFQDN1[NI_MAXHOST] = "";
00374     CHAR szFQDN2[NI_MAXHOST] = "";
00375     PCHAR Name = szFQDN1;
00376     PCHAR Alias = szFQDN2;
00377     PCHAR Scratch = NULL;
00378 
00379     /* Make a copy of the name */
00380     strcpy(Name, NodeName);
00381     
00382     /* Loop */
00383     while (TRUE)
00384     {
00385         /* Do a DNS Query for the name */
00386         iError = QueryDNS(NodeName,
00387                           SocketType,
00388                           Protocol,
00389                           Port,
00390                           Alias,
00391                           pptResult);
00392         if (iError) break;
00393 
00394         /* Exit if we have a result */
00395         if (*pptResult) break;
00396 
00397         /* Don't loop continously if this is a DNS misconfiguration */
00398         if ((!strlen(Alias)) || (!strcmp(Name, Alias)) || (++AliasCount == 16))
00399         {
00400             /* Exit the loop with a failure */
00401             iError = EAI_FAIL;
00402             break;
00403         }
00404 
00405         /* Restart loopup if we got a CNAME */
00406         Swap(Name, Alias, Scratch);
00407     }
00408 
00409     /* Check if we suceeded and the canonical name is requested */
00410     if (!iError && bAI_CANONNAME)
00411     {
00412         /* Allocate memory for a copy */
00413         (*pptResult)->ai_canonname = HeapAlloc(WsSockHeap, 0, 512);
00414         
00415         /* Check if we had enough memory */
00416         if (!(*pptResult)->ai_canonname)
00417         {
00418             /* Set failure code */
00419             iError = EAI_MEMORY;
00420         }
00421         else
00422         {
00423             /* Convert the alias to UNICODE */
00424             MultiByteToWideChar(CP_ACP, 
00425                                 0, 
00426                                 Alias, 
00427                                 -1, 
00428                                 (*pptResult)->ai_canonname, 
00429                                 256);
00430         }
00431     }
00432 
00433     /* Return to caller */
00434     return iError;
00435 }
00436 
00437 /*
00438  * @implemented
00439  */
00440 INT
00441 WSAAPI
00442 GetAddrInfoW(IN PCWSTR pszNodeName,
00443              IN PCWSTR pszServiceName,
00444              IN const ADDRINFOW *ptHints,
00445              OUT PADDRINFOW *pptResult)
00446 {
00447     INT iError = 0;
00448     INT iFlags = 0;
00449     INT iFamily = PF_UNSPEC;
00450     INT iSocketType = 0;
00451     INT iProtocol = 0;
00452     WORD wPort = 0;
00453     DWORD dwAddress = 0;
00454     PSERVENT ptService = NULL;
00455     PCHAR pc = NULL;
00456     BOOL bClone = FALSE;
00457     WORD wTcpPort = 0;
00458     WORD wUdpPort = 0;
00459     WCHAR CanonicalName[0x42];
00460     CHAR AnsiServiceName[256];
00461     CHAR AnsiNodeName[256];
00462     DPRINT("GetAddrInfoW: %S, %S, %p, %p\n", pszNodeName, pszServiceName, ptHints, pptResult);
00463 
00464     /* Assume error */
00465     *pptResult  = NULL;
00466 
00467     /* We must have at least one name to work with */
00468     if (!(pszNodeName) && !(pszServiceName))
00469     {
00470         /* Fail */
00471         SetLastError(EAI_NONAME);
00472         return EAI_NONAME;
00473     }
00474 
00475     /* Check if we got hints */
00476     if (ptHints)
00477     {
00478         /* Make sure these are empty */
00479         if ((ptHints->ai_addrlen) ||
00480             (ptHints->ai_canonname) ||
00481             (ptHints->ai_addr) ||
00482             (ptHints->ai_next))
00483         {
00484             /* Fail if they aren't */
00485             SetLastError(EAI_FAIL);
00486             return EAI_FAIL;
00487         }
00488         
00489         /* Save the flags and validate them */
00490         iFlags = ptHints->ai_flags;
00491         if ((iFlags & AI_CANONNAME) && !pszNodeName)
00492         {
00493             return EAI_BADFLAGS;
00494         }
00495 
00496         /* Save family and validate it */
00497         iFamily = ptHints->ai_family;
00498         if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET))
00499         {
00500             return EAI_FAMILY;
00501         }
00502 
00503         /* Save socket type and validate it */
00504         iSocketType = ptHints->ai_socktype;
00505         if ((iSocketType != 0) &&
00506             (iSocketType != SOCK_STREAM) &&
00507             (iSocketType != SOCK_DGRAM) &&
00508             (iSocketType != SOCK_RAW))
00509         {
00510             return EAI_SOCKTYPE;
00511         }
00512 
00513         /* Save the protocol */
00514         iProtocol = ptHints->ai_protocol;
00515     }
00516 
00517     /* Check if we have a service name */
00518     if (pszServiceName)
00519     {
00520         /* We need to convert it to ANSI */
00521         WideCharToMultiByte(CP_ACP,
00522                             0,
00523                             pszServiceName, 
00524                             -1, 
00525                             AnsiServiceName, 
00526                             256,
00527                             NULL,
00528                             0);
00529 
00530         /* Get the port */
00531         wPort = (WORD)strtoul(AnsiServiceName, &pc, 10);
00532 
00533         /* Check if the port string is numeric */
00534         if (*pc == '\0')
00535         {
00536             /* Get the port directly */
00537             wPort = wTcpPort = wUdpPort = htons(wPort);
00538 
00539             /* Check if this is both TCP and UDP */
00540             if (iSocketType == 0)
00541             {
00542                 /* Set it to TCP for now, but remember to clone */
00543                 bClone = TRUE;
00544                 iSocketType = SOCK_STREAM;
00545             }
00546         }
00547         else
00548         {
00549             /* The port name was a string. Check if this is a UDP socket */
00550             if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM))
00551             {
00552                 /* It's UDP, do a getservbyname */
00553                 ptService = getservbyname(AnsiServiceName, "udp");
00554 
00555                 /* If we got a servent, return the port from it */
00556                 if (ptService) wPort = wUdpPort = ptService->s_port;
00557             }
00558 
00559             /* Check if this is a TCP socket */
00560             if ((iSocketType == 0) || (iSocketType == SOCK_STREAM))
00561             {
00562                 /* It's TCP, do a getserbyname */
00563                 ptService = getservbyname(AnsiServiceName, "tcp");
00564 
00565                 /* Return the port from the servent */
00566                 if (ptService) wPort = wTcpPort = ptService->s_port;
00567             }
00568             
00569             /* If we got 0, then fail */
00570             if (wPort == 0)
00571             {
00572                 return iSocketType ? EAI_SERVICE : EAI_NONAME;
00573             }
00574 
00575             /* Check if this was for both */
00576             if (iSocketType == 0)
00577             {
00578                 /* Do the TCP case right now */
00579                 iSocketType = (wTcpPort) ? SOCK_STREAM : SOCK_DGRAM;
00580                 bClone = (wTcpPort && wUdpPort); 
00581             }
00582         }
00583     }
00584 
00585     /* Check if no node was given or if this is is a valid IPv4 address */
00586     if ((!pszNodeName) || (ParseV4Address(pszNodeName, &dwAddress)))
00587     {
00588         /* Check if we don't have a node name */
00589         if (!pszNodeName)
00590         {
00591             /* Make one up based on the flags */
00592             dwAddress = htonl((iFlags & AI_PASSIVE) ?
00593                               INADDR_ANY : INADDR_LOOPBACK);
00594         }
00595         
00596         /* Create the Addr Info */
00597         *pptResult = NewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);
00598 
00599         /* If we didn't get one back, assume out of memory */
00600         if (!(*pptResult)) iError = EAI_MEMORY;
00601         
00602         /* Check if we have success and a nodename */
00603         if (!iError && pszNodeName)
00604         {
00605             /* Set AI_NUMERICHOST since this is a numeric string */
00606             (*pptResult)->ai_flags |= AI_NUMERICHOST;
00607             
00608             /* Check if the canonical name was requestd */
00609             if (iFlags & AI_CANONNAME)
00610             {
00611                 /* Get the canonical name */
00612                 GetNameInfoW((*pptResult)->ai_addr,
00613                              (socklen_t)(*pptResult)->ai_addrlen,
00614                              CanonicalName,
00615                              0x41,
00616                              NULL,
00617                              0,
00618                              2);
00619 
00620                 /* Allocate memory for a copy */
00621                 (*pptResult)->ai_canonname = HeapAlloc(WsSockHeap,
00622                                                        0,
00623                                                        wcslen(CanonicalName));
00624                 
00625                 if (!(*pptResult)->ai_canonname)
00626                 {
00627                     /* No memory for the copy */
00628                     iError = EAI_MEMORY;
00629                 }
00630                 else
00631                 {
00632                     /* Duplicate the string */
00633                     RtlMoveMemory((*pptResult)->ai_canonname,
00634                                   CanonicalName,
00635                                   wcslen(CanonicalName));
00636                 }
00637             }
00638         }
00639     }
00640     else if (iFlags & AI_NUMERICHOST)
00641     {
00642         /* No name for this request (we have a non-numeric name) */
00643         iError = EAI_NONAME;
00644     }
00645     else
00646     {
00647         /* We need to convert it to ANSI */
00648         WideCharToMultiByte(CP_ACP,
00649                             0,
00650                             pszNodeName, 
00651                             -1, 
00652                             AnsiNodeName, 
00653                             256,
00654                             NULL,
00655                             0);
00656 
00657         /* Non-numeric name, do DNS lookup */
00658         iError = LookupAddressForName(AnsiNodeName,
00659                                       iSocketType,
00660                                       iProtocol,
00661                                       wPort,
00662                                       (iFlags & AI_CANONNAME),
00663                                       pptResult);
00664     }
00665 
00666     /* If all was good and the caller requested UDP and TCP */
00667     if (!iError && bClone)
00668     {
00669         /* Process UDP now, we already did TCP */
00670         iError = CloneAddrInfo(wUdpPort, *pptResult);
00671     }
00672 
00673     /* If we've hit an error till here */
00674     if (iError)
00675     {
00676         /* Free the address info and return nothing */
00677         FreeAddrInfoW(*pptResult);
00678         *pptResult = NULL;        
00679     }
00680 
00681     /* Return to caller */
00682     return iError;
00683 }
00684 
00685 #undef freeaddrinfo
00686 /*
00687  * @implemented
00688  */
00689 VOID
00690 WINAPI
00691 freeaddrinfo(PADDRINFOA AddrInfo)
00692 {
00693     PADDRINFOA NextInfo;
00694 
00695     /* Loop the chain of structures */
00696     for (NextInfo = AddrInfo; NextInfo; NextInfo = AddrInfo)
00697     {
00698         /* Check if there is a canonical name */
00699         if (NextInfo->ai_canonname)
00700         {
00701             /* Free it */
00702             HeapFree(WsSockHeap, 0, NextInfo->ai_canonname);
00703         }
00704         
00705         /* Check if there is an address */
00706         if (NextInfo->ai_addr)
00707         {
00708             /* Free it */
00709             HeapFree(WsSockHeap, 0, NextInfo->ai_addr);
00710         }
00711 
00712         /* Move to the next entry */
00713         AddrInfo = NextInfo->ai_next;
00714 
00715         /* Free this entry */
00716         HeapFree(WsSockHeap, 0, NextInfo);
00717     }
00718 }
00719 
00720 #undef getaddrinfo
00721 /*
00722  * @implemented
00723  */
00724 INT
00725 WINAPI
00726 getaddrinfo(const char FAR *nodename,
00727             const char FAR *servname,
00728             const struct addrinfo FAR *hints,
00729             struct addrinfo FAR * FAR *res)
00730 {
00731     INT ErrorCode;
00732     LPWSTR UnicodeNodeName;
00733     LPWSTR UnicodeServName = NULL; 
00734     DPRINT("getaddrinfo: %s, %s, %p, %p\n", nodename, servname, hints, res);
00735 
00736     /* Check for WSAStartup */
00737     if ((ErrorCode = WsQuickProlog()) != ERROR_SUCCESS) return ErrorCode;
00738 
00739     /* Assume NULL */
00740     *res = NULL;
00741 
00742     /* Convert the node name */
00743     UnicodeNodeName = UnicodeDupFromAnsi((LPSTR)nodename);
00744     if (!UnicodeNodeName)
00745     {
00746         /* Prepare to fail */
00747         ErrorCode = GetLastError();
00748         goto Quickie;
00749     }
00750 
00751     /* Convert the servname too, if we have one */
00752     if (servname)
00753     {
00754         UnicodeServName = UnicodeDupFromAnsi((LPSTR)servname);
00755         if (!UnicodeServName)
00756         {
00757             /* Prepare to fail */
00758             ErrorCode = GetLastError();
00759             goto Quickie;
00760         }
00761     }
00762   
00763     /* Now call the unicode function */
00764     ErrorCode = GetAddrInfoW(UnicodeNodeName,
00765                              UnicodeServName,
00766                              (PADDRINFOW)hints,
00767                              (PADDRINFOW*)res);
00768 
00769     /* Convert it to ANSI if we suceeded */
00770     if (ErrorCode == ERROR_SUCCESS) ConvertAddrinfoFromUnicodeToAnsi((PADDRINFOW)*res);
00771 
00772 Quickie:
00773     /* Check if we have a unicode node name and serv name */
00774     if (UnicodeNodeName) HeapFree(WsSockHeap, 0, UnicodeNodeName);
00775     if (UnicodeServName) HeapFree(WsSockHeap, 0, UnicodeServName);
00776 
00777     /* Check if we are in error */
00778     if (ErrorCode != ERROR_SUCCESS)
00779     {
00780         /* Free the structure and return nothing */
00781         freeaddrinfo(*res);
00782         *res = NULL;
00783     }
00784 
00785     /* Set the last error and return */
00786     SetLastError(ErrorCode);
00787     return ErrorCode;
00788 }
00789 
00790 /*
00791  * @implemented
00792  */
00793 INT
00794 WSAAPI
00795 GetNameInfoW(IN CONST SOCKADDR *pSockaddr,
00796              IN socklen_t SockaddrLength,
00797              OUT PWCHAR pNodeBuffer,
00798              IN DWORD NodeBufferSize,
00799              OUT PWCHAR pServiceBuffer,
00800              IN DWORD ServiceBufferSize,
00801              IN INT Flags)
00802 {
00803     DWORD AddressLength, AddrSize;
00804     PVOID Addr;
00805     SOCKADDR_IN Address;
00806     INT ErrorCode = ERROR_SUCCESS;
00807 
00808     /* Check for valid socket */
00809     if (!pSockaddr) return EAI_FAIL;
00810     
00811     /* Check which family this is */
00812     if (pSockaddr->sa_family == AF_INET)
00813     {
00814         /* IPv4 */
00815         AddressLength = sizeof(SOCKADDR_IN);
00816         Addr = &((PSOCKADDR_IN)pSockaddr)->sin_addr;
00817         AddrSize = sizeof(IN_ADDR);
00818     }
00819     else if (pSockaddr->sa_family == AF_INET6)
00820     {
00821         /* IPv6 */
00822         AddressLength = sizeof(SOCKADDR_IN6);
00823         Addr = &((PSOCKADDR_IN6)pSockaddr)->sin6_addr;
00824         AddrSize = sizeof(IN6_ADDR);
00825     }
00826     else
00827     {
00828         /* Unsupported family */
00829         return EAI_FAMILY;
00830     } 
00831 
00832     /* Check for valid socket adress length */
00833     if ((DWORD)SockaddrLength < AddressLength) return EAI_FAIL;
00834     
00835     /* Check if we have a node name */
00836     if (pNodeBuffer)
00837     {    
00838         /* Check if only the numeric host is wanted */
00839         if (!(Flags & NI_NUMERICHOST))
00840         {
00841             /* Do the lookup by addr */
00842             ErrorCode = LookupNodeByAddr(pNodeBuffer,
00843                                          NodeBufferSize,
00844                                          Flags & NI_NOFQDN,
00845                                          Addr,
00846                                          AddrSize,
00847                                          pSockaddr->sa_family);
00848             /* Check if we failed */
00849             if (ErrorCode != ERROR_SUCCESS)
00850             {
00851                 /* Fail if the caller REALLY wants the NAME itself? */
00852                 if (Flags & NI_NAMEREQD) goto quickie;
00853             }
00854             else
00855             {
00856                 /* We suceeded, no need to get the numeric address */
00857                 goto SkipNumeric;
00858             }
00859         }
00860 
00861         /* Copy the address */
00862         RtlMoveMemory(&Address, pSockaddr, AddressLength);
00863 
00864         /* Get the numeric address */
00865         Address.sin_port = 0;
00866         ErrorCode = WSAAddressToStringW((LPSOCKADDR)&Address,
00867                                         AddressLength,
00868                                         NULL,
00869                                         pNodeBuffer,
00870                                         &NodeBufferSize);
00871         if (ErrorCode == SOCKET_ERROR)
00872         {
00873             /* Get the error code and exit with it */
00874             ErrorCode = GetLastError();
00875             goto quickie;
00876         }
00877     }
00878 
00879 SkipNumeric:
00880     /* Check if we got a service name */
00881     if (pServiceBuffer)
00882     {
00883         /* Handle this request */
00884         ErrorCode = GetServiceNameForPort(pServiceBuffer,
00885                                           ServiceBufferSize,
00886                                           ((PSOCKADDR_IN)pSockaddr)->sin_port,
00887                                           Flags);
00888     }
00889 
00890     /* Set the error and return it (or success) */
00891 quickie:
00892     SetLastError(ErrorCode);
00893     return ErrorCode;
00894 }
00895 
00896 #undef getnameinfo
00897 /*
00898  * @implemented
00899  */
00900 INT
00901 WINAPI
00902 getnameinfo(const struct sockaddr FAR *sa,
00903             socklen_t salen,
00904             char FAR *host,
00905             DWORD hostlen,
00906             char FAR *serv,
00907             DWORD servlen,
00908             INT flags)
00909 {
00910     INT ErrorCode;
00911     WCHAR Buffer[256];
00912     WCHAR ServiceBuffer[17];
00913     DWORD HostLength = 0, ServLength = 0;
00914     PWCHAR ServiceString = NULL, HostString = NULL;
00915     DPRINT("getaddrinfo: %p, %p, %p, %lx\n", host, serv, sa, salen);
00916 
00917     /* Check for WSAStartup */
00918     if ((ErrorCode = WsQuickProlog()) != ERROR_SUCCESS) return ErrorCode;
00919 
00920     /* Check if we have a host pointer */
00921     if (host)
00922     {
00923         /* Setup the data for it */
00924         HostString = Buffer;
00925         HostLength = sizeof(Buffer) / sizeof(WCHAR);
00926     }
00927 
00928     /* Check if we have a service pointer */
00929     if (serv)
00930     {
00931         /* Setup the data for it */
00932         ServiceString = ServiceBuffer;
00933         ServLength = sizeof(ServiceBuffer) - 1;
00934     }
00935   
00936     /* Now call the unicode function */
00937     ErrorCode = GetNameInfoW(sa,
00938                              salen,
00939                              HostString,
00940                              HostLength,
00941                              ServiceString,
00942                              ServLength,
00943                              flags);
00944 
00945     /* Check for success */
00946     if (ErrorCode == ERROR_SUCCESS)
00947     {
00948         /* Check if we had a host pointer */
00949         if (HostString)
00950         {
00951             /* Convert it back to ANSI */
00952             ErrorCode = WideCharToMultiByte(CP_ACP,
00953                                             0,
00954                                             HostString,
00955                                             -1,
00956                                             host,
00957                                             hostlen,
00958                                             NULL,
00959                                             NULL);
00960             if (!ErrorCode) goto Quickie;
00961         }
00962 
00963         /* Check if we have a service pointer */
00964         if (ServiceString)
00965         {
00966             /* Convert it back to ANSI */
00967             ErrorCode = WideCharToMultiByte(CP_ACP,
00968                                             0,
00969                                             ServiceString,
00970                                             -1,
00971                                             serv,
00972                                             servlen,
00973                                             NULL,
00974                                             NULL);
00975             if (!ErrorCode) goto Quickie;
00976         }
00977 
00978         /* Return success */
00979         return ERROR_SUCCESS;
00980     }
00981 
00982     /* Set the last error and return */
00983 Quickie:
00984     SetLastError(ErrorCode);
00985     return ErrorCode;
00986 }

Generated on Fri May 25 2012 04:25:10 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.