ReactOS  0.4.12-dev-914-g71f84a3
addrinfo.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS WinSock 2 API
4  * FILE: dll/win32/ws2_32_new/src/addrinfo.c
5  * PURPOSE: Protocol-Independent Address Resolution
6  * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ws2_32.h>
12 
13 #include <ws2tcpip.h>
14 
15 #define NDEBUG
16 #include <debug.h>
17 
18 /* DEFINES *******************************************************************/
19 
20 #define Swap(a, b, c) { (c) = (a); (a) = (b); (b) = (c); }
21 #define FreeAddrInfoW(a) freeaddrinfo((LPADDRINFO)a)
22 
23 /* FUNCTIONS *****************************************************************/
24 
25 /* FIXME: put into dnslib */
26 VOID
27 WSAAPI
30 {
31  /* Convert the address into IPv4 format */
32  wsprintfW(AddressBuffer, L"%u.%u.%u.%u.in-addr.arpa.",
33  Address.S_un.S_un_b.s_b4,
34  Address.S_un.S_un_b.s_b3,
35  Address.S_un.S_un_b.s_b2,
36  Address.S_un.S_un_b.s_b1);
37 }
38 
39 VOID
40 WINAPI
42 {
43  /* FIXME */
44 }
45 
46 static
47 INT
48 WINAPI
50 {
51  LPSTR AnsiName;
53 
54  /* Make sure we have a valid pointer */
55  if (Addrinfo)
56  {
57  do
58  {
59  /* Get the name */
60  UnicodeName = &Addrinfo->ai_canonname;
61 
62  /* Check if it exists */
63  if (*UnicodeName)
64  {
65  /* Convert it */
66  AnsiName = AnsiDupFromUnicode(*UnicodeName);
67  if (AnsiName)
68  {
69  /* Free the old one */
71 
72  /* Set the new one */
73  *UnicodeName = (LPWSTR)AnsiName;
74  }
75  else
76  {
77  return GetLastError();
78  }
79  }
80  } while ((Addrinfo = Addrinfo->ai_next));
81  }
82 
83  /* All done */
84  return ERROR_SUCCESS;
85 }
86 
87 static
88 BOOL
89 WINAPI
90 ParseV4Address(IN PCWSTR AddressString,
91  OUT PDWORD pAddress)
92 {
93  CHAR AnsiAddressString[MAX_HOSTNAME_LEN];
94  CHAR * cp = AnsiAddressString;
95  DWORD val, base;
96  unsigned char c;
97  DWORD parts[4], *pp = parts;
98  if (!AddressString)
99  return FALSE;
101  0,
102  AddressString,
103  -1,
104  AnsiAddressString,
105  sizeof(AnsiAddressString),
106  NULL,
107  0);
108  if (!isdigit(*cp)) return FALSE;
109 
110 again:
111  /*
112  * Collect number up to ``.''.
113  * Values are specified as for C:
114  * 0x=hex, 0=octal, other=decimal.
115  */
116  val = 0; base = 10;
117  if (*cp == '0') {
118  if (*++cp == 'x' || *cp == 'X')
119  base = 16, cp++;
120  else
121  base = 8;
122  }
123  while ((c = *cp)) {
124  if (isdigit(c)) {
125  val = (val * base) + (c - '0');
126  cp++;
127  continue;
128  }
129  if (base == 16 && isxdigit(c)) {
130  val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
131  cp++;
132  continue;
133  }
134  break;
135  }
136  if (*cp == '.') {
137  /*
138  * Internet format:
139  * a.b.c.d
140  */
141  if (pp >= parts + 4) return FALSE;
142  *pp++ = val;
143  cp++;
144  goto again;
145  }
146  /*
147  * Check for trailing characters.
148  */
149  if (*cp) return FALSE;
150 
151  if (pp >= parts + 4) return FALSE;
152  *pp++ = val;
153  /*
154  * Concoct the address according to
155  * the number of parts specified.
156  */
157  if ((DWORD)(pp - parts) != 4) return FALSE;
158  if (parts[0] > 0xff || parts[1] > 0xff || parts[2] > 0xff || parts[3] > 0xff) return FALSE;
159  val = (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3];
160 
161  if (pAddress)
162  *pAddress = htonl(val);
163 
164  return TRUE;
165 }
166 
167 static
169 WINAPI
171  IN INT Protocol,
172  IN WORD Port,
173  IN DWORD Address)
174 {
176  PSOCKADDR_IN SockAddress;
177 
178  /* Allocate a structure */
179  AddrInfo = HeapAlloc(WsSockHeap, 0, sizeof(ADDRINFOW));
180  if (!AddrInfo) return NULL;
181 
182  /* Allocate a sockaddr */
183  SockAddress = HeapAlloc(WsSockHeap, 0, sizeof(SOCKADDR_IN));
184  if (!SockAddress)
185  {
186  /* Free the addrinfo and fail */
188  return NULL;
189  }
190 
191  /* Write data for socket address */
192  SockAddress->sin_family = AF_INET;
193  SockAddress->sin_port = Port;
194  SockAddress->sin_addr.s_addr = Address;
195  ZeroMemory(SockAddress->sin_zero, sizeof(SockAddress->sin_zero));
196 
197  /* Fill out the addrinfo */
198  AddrInfo->ai_family = PF_INET;
199  AddrInfo->ai_socktype = SocketType;
200  AddrInfo->ai_protocol = Protocol;
201  AddrInfo->ai_flags = 0;
202  AddrInfo->ai_next = 0;
203  AddrInfo->ai_canonname = NULL;
204  AddrInfo->ai_addrlen = sizeof(SOCKADDR_IN);
205  AddrInfo->ai_addr = (PSOCKADDR)SockAddress;
206 
207  /* Return it */
208  return AddrInfo;
209 }
210 
211 static
212 INT
213 WINAPI
215  IN PADDRINFOW ptResult)
216 {
217  PADDRINFOW Next = NULL;
218  PADDRINFOW New = NULL;
219 
220  /* Loop the chain */
221  for (Next = ptResult; Next;)
222  {
223  /* Create a new structure */
225  Next->ai_protocol,
226  Port,
227  ((PSOCKADDR_IN)Next->ai_addr)->sin_addr.s_addr);
228  if (!New) break;
229 
230  /* Link them */
231  New->ai_next = Next->ai_next;
232  Next->ai_next = New;
233  Next = New->ai_next;
234  }
235 
236  /* Check if we ran out of memory */
237  if (Next) return EAI_MEMORY;
238 
239  /* Return success */
240  return 0;
241 }
242 
243 static
244 INT
245 WINAPI
247  IN INT SocketType,
248  IN INT Protocol,
249  IN WORD Port,
251  OUT PADDRINFOW *pptResult)
252 {
253  PADDRINFOW *Next = pptResult;
254  PHOSTENT Hostent = NULL;
255  PCHAR *Addresses;
256 
257  /* Assume nothing found */
258  *Next = NULL;
259  Alias[0] = '\0';
260 
261  /* Get the hostent */
262  Hostent = gethostbyname(NodeName);
263  if (Hostent)
264  {
265  /* Check for valid addresses */
266  if ((Hostent->h_addrtype == AF_INET) &&
267  (Hostent->h_length == sizeof(IN_ADDR)))
268  {
269  /* Loop every address in it */
270  for (Addresses = Hostent->h_addr_list; *Addresses; Addresses++)
271  {
272  /* Create an addrinfo structure for it*/
273  *Next = NewAddrInfo(SocketType,
274  Protocol,
275  Port,
276  ((PIN_ADDR)*Addresses)->s_addr);
277  if (!*Next) return EAI_MEMORY;
278 
279  /* Move to the next entry */
280  Next = &((*Next)->ai_next);
281  }
282  }
283 
284  /* Copy the canonical name */
285  strcpy(Alias, Hostent->h_name);
286 
287  /* Return success */
288  return 0;
289  }
290 
291  /* Find out what the error was */
292  switch (GetLastError())
293  {
294  /* Convert the Winsock Error to an EAI error */
295  case WSAHOST_NOT_FOUND: return EAI_NONAME;
296  case WSATRY_AGAIN: return EAI_AGAIN;
297  case WSANO_RECOVERY: return EAI_FAIL;
298  case WSANO_DATA: return EAI_NODATA;
299  default: return EAI_NONAME;
300  }
301 }
302 
303 static
304 INT
305 WINAPI
307  IN DWORD NodeBufferSize,
308  IN BOOLEAN OnlyNodeName,
309  IN PVOID Addr,
310  IN DWORD AddrSize,
312 {
313  GUID LookupGuid = SVCID_DNS_TYPE_PTR;
314  PIN_ADDR Ip4Addr = Addr;
315  WCHAR ReverseBuffer[76];
316  WSAQUERYSETW Restrictions, Reply;
318  INT ErrorCode;
319  HANDLE LookupHandle;
320 
321  /* Validate the address */
322  if (!Addr) return WSAEFAULT;
323 
324  /* Make sure the family and address size match */
325  if (AddressFamily == AF_INET6)
326  {
327  /* Check the address size for this type */
328  if (AddrSize != sizeof(IN6_ADDR)) return WSAEFAULT;
329  Ip4Addr = (PIN_ADDR)&((PIN6_ADDR)Addr)->u.Byte[12];
330  }
331  else if (AddressFamily == AF_INET)
332  {
333  /* Check the address size for this type */
334  if (AddrSize != sizeof(IN_ADDR)) return WSAEFAULT;
335  }
336  else
337  {
338  /* Address family not supported */
339  return WSAEAFNOSUPPORT;
340  }
341 
342  /* Check if this is a mapped V4 IPv6 or pure IPv4 */
343  if (((AddressFamily == AF_INET6) && (IN6_IS_ADDR_V4MAPPED(Addr))) ||
344  (AddressFamily == AF_INET))
345  {
346  /* Get the reverse name */
347  Dns_Ip4AddressToReverseName_W(ReverseBuffer, *Ip4Addr);
348  }
349  /* FIXME: Not implemented for now
350  else if ( */
351 
352  /* By this point we have the Reverse Name, so prepare for lookup */
353  RtlZeroMemory(&Restrictions, sizeof(Restrictions));
354  Restrictions.dwSize = sizeof(Restrictions);
355  Restrictions.lpszServiceInstanceName = ReverseBuffer;
356  Restrictions.lpServiceClassId = &LookupGuid;
357  Restrictions.dwNameSpace = NS_DNS;
358 
359  /* Now do the lookup */
360  ErrorCode = WSALookupServiceBeginW(&Restrictions,
362  &LookupHandle);
363  if (ErrorCode == ERROR_SUCCESS)
364  {
365  /* Lookup successful, now get the data */
366  BufferLength = (NI_MAXHOST - 1) * sizeof(WCHAR) + sizeof(Restrictions);
367  ErrorCode = WSALookupServiceNextW(LookupHandle,
368  0,
369  &BufferLength,
370  &Restrictions);
371  if (ErrorCode == ERROR_SUCCESS)
372  {
373  /* Now check if we have a name back */
374  Reply = Restrictions;
375  if (!Reply.lpszServiceInstanceName)
376  {
377  /* Fail */
379  }
380  else
381  {
382  /* Check if the caller only wants the node name */
383  if (OnlyNodeName)
384  {
385  /* Split it and get only the partial host name */
386  Dns_SplitHostFromDomainNameW(Reply.lpszServiceInstanceName);
387  }
388 
389  /* Check the length and see if it's within our limit */
390  if (wcslen(Reply.lpszServiceInstanceName) + 1 >
391  NodeBufferSize)
392  {
393  /* It's not, so fail */
395  }
396  else
397  {
398  /* It will fit, let's copy it*/
399  wcscpy(pNodeBuffer, Reply.lpszServiceInstanceName);
400  }
401  }
402  }
403  }
404  else if (ErrorCode == WSASERVICE_NOT_FOUND)
405  {
406  /* Normalize the error code */
408  }
409 
410  /* Finish the lookup if one was in progress */
411  if (LookupHandle) WSALookupServiceEnd(LookupHandle);
412 
413  /* Return the error code */
414  return ErrorCode;
415 }
416 
417 static
418 INT
419 WINAPI
421  IN DWORD ServiceBufferSize,
422  IN WORD Port,
423  IN DWORD Flags)
424 {
425  return ERROR_SUCCESS;
426 }
427 
428 static
429 INT
430 WINAPI
432  IN INT SocketType,
433  IN INT Protocol,
434  IN WORD Port,
435  IN BOOL bAI_CANONNAME,
436  OUT PADDRINFOW *pptResult)
437 {
438  INT iError = 0;
439  INT AliasCount = 0;
440  CHAR szFQDN1[NI_MAXHOST] = "";
441  CHAR szFQDN2[NI_MAXHOST] = "";
442  PCHAR Name = szFQDN1;
443  PCHAR Alias = szFQDN2;
444  PCHAR Scratch = NULL;
445 
446  /* Make a copy of the name */
447  strcpy(Name, NodeName);
448 
449  /* Loop */
450  while (TRUE)
451  {
452  /* Do a DNS Query for the name */
453  iError = QueryDNS(NodeName,
454  SocketType,
455  Protocol,
456  Port,
457  Alias,
458  pptResult);
459  if (iError) break;
460 
461  /* Exit if we have a result */
462  if (*pptResult) break;
463 
464  /* Don't loop continuously if this is a DNS misconfiguration */
465  if ((!strlen(Alias)) || (!strcmp(Name, Alias)) || (++AliasCount == 16))
466  {
467  /* Exit the loop with a failure */
468  iError = EAI_FAIL;
469  break;
470  }
471 
472  /* Restart loopup if we got a CNAME */
473  Swap(Name, Alias, Scratch);
474  }
475 
476  /* Check if we succeeded and the canonical name is requested */
477  if (!iError && bAI_CANONNAME)
478  {
479  /* Allocate memory for a copy */
480  (*pptResult)->ai_canonname = HeapAlloc(WsSockHeap, 0, 512);
481 
482  /* Check if we had enough memory */
483  if (!(*pptResult)->ai_canonname)
484  {
485  /* Set failure code */
486  iError = EAI_MEMORY;
487  }
488  else
489  {
490  /* Convert the alias to UNICODE */
492  0,
493  Alias,
494  -1,
495  (*pptResult)->ai_canonname,
496  256);
497  }
498  }
499 
500  /* Return to caller */
501  return iError;
502 }
503 
504 /*
505  * @implemented
506  */
507 INT
508 WSAAPI
509 GetAddrInfoW(IN PCWSTR pszNodeName,
510  IN PCWSTR pszServiceName,
511  IN const ADDRINFOW *ptHints,
512  OUT PADDRINFOW *pptResult)
513 {
514  INT iError = 0;
515  INT iFlags = 0;
516  INT iFamily = PF_UNSPEC;
517  INT iSocketType = 0;
518  INT iProtocol = 0;
519  WORD wPort = 0;
520  DWORD dwAddress = 0;
521  PSERVENT ptService = NULL;
522  PCHAR pc = NULL;
523  BOOL bClone = FALSE;
524  WORD wTcpPort = 0;
525  WORD wUdpPort = 0;
526  WCHAR CanonicalName[0x42];
527  CHAR AnsiServiceName[256];
528  CHAR AnsiNodeName[256];
529  DPRINT("GetAddrInfoW: %S, %S, %p, %p\n", pszNodeName, pszServiceName, ptHints, pptResult);
530 
531  /* Assume error */
532  *pptResult = NULL;
533 
534  /* We must have at least one name to work with */
535  if (!(pszNodeName) && !(pszServiceName))
536  {
537  /* Fail */
539  return EAI_NONAME;
540  }
541 
542  /* Check if we got hints */
543  if (ptHints)
544  {
545  /* Make sure these are empty */
546  if ((ptHints->ai_addrlen) ||
547  (ptHints->ai_canonname) ||
548  (ptHints->ai_addr) ||
549  (ptHints->ai_next))
550  {
551  /* Fail if they aren't */
553  return EAI_FAIL;
554  }
555 
556  /* Save the flags and validate them */
557  iFlags = ptHints->ai_flags;
558  if ((iFlags & AI_CANONNAME) && !pszNodeName)
559  {
561  return EAI_BADFLAGS;
562  }
563 
564  /* Save family and validate it */
565  iFamily = ptHints->ai_family;
566  if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET))
567  {
569  return EAI_FAMILY;
570  }
571 
572  /* Save socket type and validate it */
573  iSocketType = ptHints->ai_socktype;
574  if ((iSocketType != 0) &&
575  (iSocketType != SOCK_STREAM) &&
576  (iSocketType != SOCK_DGRAM) &&
577  (iSocketType != SOCK_RAW))
578  {
580  return EAI_SOCKTYPE;
581  }
582 
583  /* Save the protocol */
584  iProtocol = ptHints->ai_protocol;
585  }
586 
587  /* Check if we have a service name */
588  if (pszServiceName)
589  {
590  /* We need to convert it to ANSI */
592  0,
593  pszServiceName,
594  -1,
595  AnsiServiceName,
596  sizeof(AnsiServiceName),
597  NULL,
598  0);
599 
600  /* Get the port */
601  wPort = (WORD)strtoul(AnsiServiceName, &pc, 10);
602 
603  /* Check if the port string is numeric */
604  if (*pc == '\0')
605  {
606  /* Get the port directly */
607  wPort = wTcpPort = wUdpPort = htons(wPort);
608 
609 #if 0
610  /* Check if this is both TCP and UDP */
611  if (iSocketType == 0)
612  {
613  /* Set it to TCP for now, but remember to clone */
614  bClone = TRUE;
615  iSocketType = SOCK_STREAM;
616  }
617 #endif
618  }
619  else
620  {
621  wPort = 0;
622  /* The port name was a string. Check if this is a UDP socket */
623  if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM))
624  {
625  /* It's UDP, do a getservbyname */
626  ptService = getservbyname(AnsiServiceName, "udp");
627 
628  /* If we got a servent, return the port from it */
629  if (ptService) wPort = wUdpPort = ptService->s_port;
630  }
631 
632  /* Check if this is a TCP socket */
633  if ((iSocketType == 0) || (iSocketType == SOCK_STREAM))
634  {
635  /* It's TCP, do a getserbyname */
636  ptService = getservbyname(AnsiServiceName, "tcp");
637 
638  /* Return the port from the servent */
639  if (ptService) wPort = wTcpPort = ptService->s_port;
640  }
641 
642  /* If we got 0, then fail */
643  if (wPort == 0)
644  {
646  return EAI_SERVICE;
647  }
648 
649  /* Check if this was for both */
650  if (iSocketType == 0)
651  {
652  /* Do the TCP case right now */
653  if (wTcpPort && !wUdpPort)
654  iSocketType = SOCK_STREAM;
655  if (!wTcpPort && wUdpPort)
656  iSocketType = SOCK_DGRAM;
657  //bClone = (wTcpPort && wUdpPort);
658  }
659  }
660  }
661 
662  /* Check if no node was given or if this is is a valid IPv4 address */
663  if ((!pszNodeName) || (ParseV4Address(pszNodeName, &dwAddress)))
664  {
665  /* Check if we don't have a node name */
666  if (!pszNodeName)
667  {
668  /* Make one up based on the flags */
669  dwAddress = htonl((iFlags & AI_PASSIVE) ?
671  }
672 
673  /* Create the Addr Info */
674  *pptResult = NewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);
675 
676  /* If we didn't get one back, assume out of memory */
677  if (!(*pptResult)) iError = EAI_MEMORY;
678 
679  /* Check if we have success and a nodename */
680  if (!iError && pszNodeName)
681  {
682  /* Set AI_NUMERICHOST since this is a numeric string */
683  (*pptResult)->ai_flags |= AI_NUMERICHOST;
684 
685  /* Check if the canonical name was requested */
686  if (iFlags & AI_CANONNAME)
687  {
688  /* Get the canonical name */
689  GetNameInfoW((*pptResult)->ai_addr,
690  (socklen_t)(*pptResult)->ai_addrlen,
691  CanonicalName,
692  0x41,
693  NULL,
694  0,
695  2);
696 
697  /* Allocate memory for a copy */
698  (*pptResult)->ai_canonname = HeapAlloc(WsSockHeap,
699  0,
700  wcslen(CanonicalName));
701 
702  if (!(*pptResult)->ai_canonname)
703  {
704  /* No memory for the copy */
705  iError = EAI_MEMORY;
706  }
707  else
708  {
709  /* Duplicate the string */
710  RtlMoveMemory((*pptResult)->ai_canonname,
711  CanonicalName,
712  wcslen(CanonicalName));
713  }
714  }
715  }
716  }
717  else if (iFlags & AI_NUMERICHOST)
718  {
719  /* No name for this request (we have a non-numeric name) */
720  iError = EAI_NONAME;
721  }
722  else
723  {
724  /* We need to convert it to ANSI */
726  0,
727  pszNodeName,
728  -1,
729  AnsiNodeName,
730  sizeof(AnsiNodeName),
731  NULL,
732  0);
733 
734  /* Non-numeric name, do DNS lookup */
735  iError = LookupAddressForName(AnsiNodeName,
736  iSocketType,
737  iProtocol,
738  wPort,
739  (iFlags & AI_CANONNAME),
740  pptResult);
741  }
742 
743  /* If all was good and the caller requested UDP and TCP */
744  if (!iError && bClone)
745  {
746  /* Process UDP now, we already did TCP */
747  iError = CloneAddrInfo(wUdpPort, *pptResult);
748  }
749 
750  /* If we've hit an error till here */
751  if (iError)
752  {
753  /* Free the address info and return nothing */
754  FreeAddrInfoW(*pptResult);
755  *pptResult = NULL;
756  }
757 
758  /* Return to caller */
759  SetLastError(iError);
760  return iError;
761 }
762 
763 #undef freeaddrinfo
764 /*
765  * @implemented
766  */
767 VOID
768 WINAPI
770 {
771  PADDRINFOA NextInfo;
772 
773  /* Loop the chain of structures */
774  for (NextInfo = AddrInfo; NextInfo; NextInfo = AddrInfo)
775  {
776  /* Check if there is a canonical name */
777  if (NextInfo->ai_canonname)
778  {
779  /* Free it */
780  HeapFree(WsSockHeap, 0, NextInfo->ai_canonname);
781  }
782 
783  /* Check if there is an address */
784  if (NextInfo->ai_addr)
785  {
786  /* Free it */
787  HeapFree(WsSockHeap, 0, NextInfo->ai_addr);
788  }
789 
790  /* Move to the next entry */
791  AddrInfo = NextInfo->ai_next;
792 
793  /* Free this entry */
794  HeapFree(WsSockHeap, 0, NextInfo);
795  }
796 }
797 
798 #undef getaddrinfo
799 /*
800  * @implemented
801  */
802 INT
803 WINAPI
804 getaddrinfo(const char FAR *nodename,
805  const char FAR *servname,
806  const struct addrinfo FAR *hints,
807  struct addrinfo FAR * FAR *res)
808 {
809  INT ErrorCode;
810  LPWSTR UnicodeNodeName = NULL;
811  LPWSTR UnicodeServName = NULL;
812  DPRINT("getaddrinfo: %s, %s, %p, %p\n", nodename, servname, hints, res);
813 
814  /* Check for WSAStartup */
815  if ((ErrorCode = WsQuickProlog()) != ERROR_SUCCESS) return ErrorCode;
816 
817  /* Convert the node name */
818  if (nodename)
819  {
820  UnicodeNodeName = UnicodeDupFromAnsi(nodename);
821  if (!UnicodeNodeName)
822  {
823  /* Prepare to fail */
825  goto Quickie;
826  }
827  }
828 
829  /* Convert the servname too, if we have one */
830  if (servname)
831  {
832  UnicodeServName = UnicodeDupFromAnsi(servname);
833  if (!UnicodeServName)
834  {
835  /* Prepare to fail */
837  goto Quickie;
838  }
839  }
840 
841  /* Now call the unicode function */
842  ErrorCode = GetAddrInfoW(UnicodeNodeName,
843  UnicodeServName,
844  (PADDRINFOW)hints,
845  (PADDRINFOW*)res);
846 
847  /* Convert it to ANSI if we succeeded */
849 
850 Quickie:
851  /* Check if we have a unicode node name and serv name */
852  if (UnicodeNodeName) HeapFree(WsSockHeap, 0, UnicodeNodeName);
853  if (UnicodeServName) HeapFree(WsSockHeap, 0, UnicodeServName);
854 
855  /* Check if we are in error */
856  if (ErrorCode != ERROR_SUCCESS)
857  {
858  /* Free the structure and return nothing */
859  freeaddrinfo(*res);
860  *res = NULL;
861  }
862 
863  /* Set the last error and return */
865  return ErrorCode;
866 }
867 
868 /*
869  * @implemented
870  */
871 INT
872 WSAAPI
874  IN socklen_t SockaddrLength,
875  OUT PWCHAR pNodeBuffer,
876  IN DWORD NodeBufferSize,
877  OUT PWCHAR pServiceBuffer,
878  IN DWORD ServiceBufferSize,
879  IN INT Flags)
880 {
881  DWORD AddressLength, AddrSize;
882  PVOID Addr;
885 
886  DPRINT("GetNameInfoW: %p, %d, %p, %ld, %p, %ld, %d\n",
887  pSockaddr,
888  SockaddrLength,
889  pNodeBuffer,
890  NodeBufferSize,
891  pServiceBuffer,
892  ServiceBufferSize,
893  Flags);
894 
895  /* Check for valid socket */
896  if (!pSockaddr)
897  return WSAEFAULT;
898 
899  /* Check which family this is */
900  if (pSockaddr->sa_family == AF_INET)
901  {
902  /* IPv4 */
903  AddressLength = sizeof(SOCKADDR_IN);
904  Addr = &((PSOCKADDR_IN)pSockaddr)->sin_addr;
905  AddrSize = sizeof(IN_ADDR);
906  }
907  else if (pSockaddr->sa_family == AF_INET6)
908  {
909  /* IPv6 */
910  AddressLength = sizeof(SOCKADDR_IN6);
911  Addr = &((PSOCKADDR_IN6)pSockaddr)->sin6_addr;
912  AddrSize = sizeof(IN6_ADDR);
913  }
914  else
915  {
916  /* Unsupported family */
918  return EAI_FAMILY;
919  }
920 
921  /* Check for valid socket address length */
922  if ((DWORD)SockaddrLength < AddressLength)
923  return WSAEFAULT;
924 
925  /* Check if we have a node name */
926  if (pNodeBuffer)
927  {
928  /* Check if only the numeric host is wanted */
929  if (!(Flags & NI_NUMERICHOST))
930  {
931  /* Do the lookup by addr */
932  ErrorCode = LookupNodeByAddr(pNodeBuffer,
933  NodeBufferSize,
934  Flags & NI_NOFQDN,
935  Addr,
936  AddrSize,
937  pSockaddr->sa_family);
938  /* Check if we failed */
939  if (ErrorCode != ERROR_SUCCESS)
940  {
941  /* Fail if the caller REALLY wants the NAME itself? */
942  if (Flags & NI_NAMEREQD) goto quickie;
943  }
944  else
945  {
946  /* We succeeded, no need to get the numeric address */
947  goto SkipNumeric;
948  }
949  }
950 
951  /* Copy the address */
952  RtlMoveMemory(&Address, pSockaddr, AddressLength);
953 
954  /* Get the numeric address */
955  if (pSockaddr->sa_family == AF_INET)
956  {
957  /* IPv4 */
958  ((PSOCKADDR_IN)&Address)->sin_port = 0;
959  }
960  else if (pSockaddr->sa_family == AF_INET6)
961  {
962  /* IPv6 */
963  ((PSOCKADDR_IN6)&Address)->sin6_port = 0;
964  }
966  AddressLength,
967  NULL,
968  pNodeBuffer,
969  &NodeBufferSize);
970  if (ErrorCode == SOCKET_ERROR)
971  {
972  /* Get the error code and exit with it */
974  goto quickie;
975  }
976  }
977 
978 SkipNumeric:
979  /* Check if we got a service name */
980  if (pServiceBuffer)
981  {
982  /* Handle this request */
983  ErrorCode = GetServiceNameForPort(pServiceBuffer,
984  ServiceBufferSize,
985  ((PSOCKADDR_IN)pSockaddr)->sin_port,
986  Flags);
987  }
988 
989  /* Set the error and return it (or success) */
990 quickie:
992  return ErrorCode;
993 }
994 
995 #undef getnameinfo
996 /*
997  * @implemented
998  */
999 INT
1000 WINAPI
1001 getnameinfo(const struct sockaddr FAR *sa,
1002  socklen_t salen,
1003  char FAR *host,
1004  DWORD hostlen,
1005  char FAR *serv,
1006  DWORD servlen,
1007  INT flags)
1008 {
1009  INT ErrorCode;
1010  WCHAR Buffer[256];
1011  WCHAR ServiceBuffer[17];
1012  DWORD HostLength = 0, ServLength = 0;
1013  PWCHAR ServiceString = NULL, HostString = NULL;
1014  DPRINT("getnameinfo: %p, %p, %p, %lx\n", host, serv, sa, salen);
1015 
1016  /* Check for WSAStartup */
1017  if ((ErrorCode = WsQuickProlog()) != ERROR_SUCCESS) return ErrorCode;
1018 
1019  /* Check if we have a host pointer */
1020  if (host)
1021  {
1022  /* Setup the data for it */
1023  HostString = Buffer;
1024  HostLength = sizeof(Buffer) / sizeof(WCHAR);
1025  }
1026 
1027  /* Check if we have a service pointer */
1028  if (serv)
1029  {
1030  /* Setup the data for it */
1031  ServiceString = ServiceBuffer;
1032  ServLength = sizeof(ServiceBuffer) / sizeof(WCHAR);
1033  }
1034 
1035  /* Now call the unicode function */
1037  salen,
1038  HostString,
1039  HostLength,
1040  ServiceString,
1041  ServLength,
1042  flags);
1043 
1044  /* Check for success */
1045  if (ErrorCode == ERROR_SUCCESS)
1046  {
1047  /* Check if we had a host pointer */
1048  if (HostString)
1049  {
1050  /* Convert it back to ANSI */
1052  0,
1053  HostString,
1054  -1,
1055  host,
1056  hostlen,
1057  NULL,
1058  NULL);
1059  if (!ErrorCode) goto Quickie;
1060  }
1061 
1062  /* Check if we have a service pointer */
1063  if (ServiceString)
1064  {
1065  /* Convert it back to ANSI */
1067  0,
1068  ServiceString,
1069  -1,
1070  serv,
1071  servlen,
1072  NULL,
1073  NULL);
1074  if (!ErrorCode) goto Quickie;
1075  }
1076 
1077  /* Return success */
1078  return ERROR_SUCCESS;
1079  }
1080 
1081  /* Set the last error and return */
1082 Quickie:
1084  return ErrorCode;
1085 }
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
#define EAI_SOCKTYPE
Definition: ws2tcpip.h:40
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
signed char * PCHAR
Definition: retypes.h:7
#define NI_NOFQDN
Definition: ws2def.h:353
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
#define SOCKET_ERROR
Definition: winsock.h:333
CPPORT Port[4]
Definition: headless.c:34
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define IN
Definition: typedefs.h:38
char ** h_addr_list
Definition: winsock.h:138
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
struct in6_addr IN6_ADDR
#define NI_NAMEREQD
Definition: ws2def.h:355
IN PCO_ADDRESS_FAMILY AddressFamily
Definition: ndis.h:1888
#define TRUE
Definition: types.h:120
#define WSAEFAULT
Definition: winerror.h:1945
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4418
#define WSAHOST_NOT_FOUND
Definition: winerror.h:2000
u_short sin_port
Definition: winsock.h:511
#define AI_PASSIVE
Definition: ws2def.h:293
#define NI_NUMERICHOST
Definition: ws2def.h:354
#define ERROR_SUCCESS
Definition: deptool.c:10
#define WideCharToMultiByte
Definition: compat.h:101
INT WSAAPI WSAAddressToStringW(IN LPSOCKADDR lpsaAddress, IN DWORD dwAddressLength, IN LPWSAPROTOCOL_INFOW lpProtocolInfo, OUT LPWSTR lpszAddressString, IN OUT LPDWORD lpdwAddressStringLength)
Definition: rnr.c:128
#define WSASERVICE_NOT_FOUND
Definition: winerror.h:1995
#define LUP_RETURN_NAME
Definition: winsock2.h:514
static INT WINAPI CloneAddrInfo(IN WORD Port, IN PADDRINFOW ptResult)
Definition: addrinfo.c:214
#define AI_CANONNAME
Definition: ws2def.h:294
#define EAI_AGAIN
Definition: ws2tcpip.h:31
#define htonl(x)
Definition: module.h:212
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
LPWSTR WSAAPI UnicodeDupFromAnsi(IN LPCSTR AnsiString)
Definition: qshelpr.c:68
struct addrinfoW * ai_next
Definition: ws2def.h:683
static BOOL WINAPI ParseV4Address(IN PCWSTR AddressString, OUT PDWORD pAddress)
Definition: addrinfo.c:90
#define CP_ACP
Definition: compat.h:99
char * h_name
Definition: winsock.h:134
char CHAR
Definition: xmlstorage.h:175
#define WSAEAFNOSUPPORT
Definition: winerror.h:1960
VOID WINAPI freeaddrinfo(PADDRINFOA AddrInfo)
Definition: addrinfo.c:769
char * host
Definition: whois.c:55
IN PDCB IN POEM_STRING IN PUNICODE_STRING UnicodeName
Definition: fatprocs.h:1294
_In_ USHORT _In_ ULONG Protocol
Definition: wsk.h:182
#define New(t)
Definition: rtf.h:1086
#define s_addr
Definition: tcpip.h:133
#define INADDR_ANY
Definition: StrAddr.c:4
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
static INT WINAPI LookupNodeByAddr(IN LPWSTR pNodeBuffer, IN DWORD NodeBufferSize, IN BOOLEAN OnlyNodeName, IN PVOID Addr, IN DWORD AddrSize, IN INT AddressFamily)
Definition: addrinfo.c:306
struct sockaddr * PSOCKADDR
Definition: winsock.h:485
#define NS_DNS
Definition: nspapi.h:16
struct in_addr * PIN_ADDR
#define EAI_FAIL
Definition: ws2tcpip.h:33
uint16_t * PWCHAR
Definition: typedefs.h:54
char * LPSTR
Definition: xmlstorage.h:182
int32_t INT
Definition: typedefs.h:56
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define SOCK_RAW
Definition: winsock.h:337
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
INT WSAAPI WSALookupServiceEnd(IN HANDLE hLookup)
Definition: rnr.c:202
static const ADDRINFOW PADDRINFOW *static const WCHAR * servname
Definition: sock.c:80
static INT WINAPI GetServiceNameForPort(IN LPWSTR pServiceBuffer, IN DWORD ServiceBufferSize, IN WORD Port, IN DWORD Flags)
Definition: addrinfo.c:420
INT WSAAPI GetAddrInfoW(IN PCWSTR pszNodeName, IN PCWSTR pszServiceName, IN const ADDRINFOW *ptHints, OUT PADDRINFOW *pptResult)
Definition: addrinfo.c:509
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint base
Definition: 3dtext.c:35
_In_ ULONG BufferLength
Definition: usbdlib.h:225
#define FAR
Definition: guiddef.h:36
#define pp
Definition: hlsl.yy.c:978
short h_length
Definition: winsock.h:137
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
#define AF_INET6
Definition: winsock.h:369
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
int ai_protocol
Definition: ws2def.h:679
const char * LPCSTR
Definition: xmlstorage.h:183
#define PF_INET
Definition: winsock.h:373
#define isdigit(c)
Definition: acclib.h:68
#define WSATRY_AGAIN
Definition: winerror.h:2001
LPSTR WSAAPI AnsiDupFromUnicode(IN LPCWSTR UnicodeString)
Definition: qshelpr.c:20
char * ai_canonname
Definition: ws2def.h:670
GLuint GLfloat * val
Definition: glext.h:7180
#define Swap(a, b, c)
Definition: addrinfo.c:20
PHOSTENT WSAAPI gethostbyname(IN const char FAR *name)
Definition: getxbyxx.c:221
PSERVENT WSAAPI getservbyname(IN const char FAR *name, IN const char FAR *proto)
Definition: getxbyxx.c:500
#define WSANO_RECOVERY
Definition: winerror.h:2002
static INT WINAPI LookupAddressForName(IN LPCSTR NodeName, IN INT SocketType, IN INT Protocol, IN WORD Port, IN BOOL bAI_CANONNAME, OUT PADDRINFOW *pptResult)
Definition: addrinfo.c:431
#define MAX_HOSTNAME_LEN
Definition: iptypes.h:30
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
SOCKADDR_IN6_LH * PSOCKADDR_IN6
Definition: ws2ipdef.h:200
#define EAI_NODATA
Definition: ws2tcpip.h:36
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define EAI_SERVICE
Definition: ws2tcpip.h:39
#define PF_UNSPEC
Definition: winsock.h:371
Definition: tcpip.h:125
INT WINAPI WSALookupServiceNextW(IN HANDLE hLookup, IN DWORD dwControlFlags, IN OUT LPDWORD lpdwBufferLength, OUT LPWSAQUERYSETW lpqsResults)
Definition: rnr.c:386
#define WINAPI
Definition: msvc.h:8
const GLubyte * c
Definition: glext.h:8905
unsigned short WORD
Definition: ntddk_ex.h:93
#define WSANO_DATA
Definition: winerror.h:2003
unsigned long DWORD
Definition: ntddk_ex.h:95
int socklen_t
Definition: tcp.c:35
#define SetLastError(x)
Definition: compat.h:409
_In_ PADDRINFOEXW AddrInfo
Definition: wsk.h:458
GLbitfield flags
Definition: glext.h:7161
#define NI_MAXHOST
Definition: ws2def.h:359
INT WSAAPI GetNameInfoW(IN CONST SOCKADDR *pSockaddr, IN socklen_t SockaddrLength, OUT PWCHAR pNodeBuffer, IN DWORD NodeBufferSize, OUT PWCHAR pServiceBuffer, IN DWORD ServiceBufferSize, IN INT Flags)
Definition: addrinfo.c:873
char sin_zero[8]
Definition: winsock.h:513
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static const char * NodeName(const NOTIFICATIONLIST *item)
Definition: changenotify.c:145
static const WCHAR L[]
Definition: oid.c:1250
WSAQUERYSETW
Definition: winsock2.h:836
static PADDRINFOW WINAPI NewAddrInfo(IN INT SocketType, IN INT Protocol, IN WORD Port, IN DWORD Address)
Definition: addrinfo.c:170
struct in_addr IN_ADDR
#define islower(c)
Definition: acclib.h:72
_In_ USHORT SocketType
Definition: wsk.h:182
#define FreeAddrInfoW(a)
Definition: addrinfo.c:21
#define EAI_MEMORY
Definition: ws2tcpip.h:35
short h_addrtype
Definition: winsock.h:136
struct in_addr sin_addr
Definition: winsock.h:512
#define AI_NUMERICHOST
Definition: ws2def.h:295
#define SVCID_DNS_TYPE_PTR
Definition: svcguid.h:209
static INT WINAPI ConvertAddrinfoFromUnicodeToAnsi(IN PADDRINFOW Addrinfo)
Definition: addrinfo.c:49
#define WSAAPI
Definition: winsock2.h:584
short s_port
Definition: winsock.h:165
#define EAI_BADFLAGS
Definition: ws2tcpip.h:32
#define EAI_NONAME
Definition: ws2tcpip.h:38
struct sockaddr_in SOCKADDR_IN
Definition: winsock.h:487
struct sockaddr_in * PSOCKADDR_IN
Definition: winsock.h:488
DWORD * PDWORD
Definition: pedump.c:68
#define MultiByteToWideChar
Definition: compat.h:100
struct sockaddr * ai_addr
Definition: ws2def.h:682
INT WINAPI WSALookupServiceBeginW(IN LPWSAQUERYSETW lpqsRestrictions, IN DWORD dwControlFlags, OUT LPHANDLE lphLookup)
Definition: rnr.c:316
#define isxdigit(c)
Definition: acclib.h:70
INT WINAPI getnameinfo(const struct sockaddr FAR *sa, socklen_t salen, char FAR *host, DWORD hostlen, char FAR *serv, DWORD servlen, INT flags)
Definition: addrinfo.c:1001
struct addrinfo * ai_next
Definition: ws2def.h:672
SOCKADDR_IN6_LH SOCKADDR_IN6
Definition: ws2ipdef.h:199
POINT cp
Definition: magnifier.c:60
#define OUT
Definition: typedefs.h:39
GLuint res
Definition: glext.h:9613
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define c
Definition: ke_i.h:80
#define AF_INET
Definition: tcpip.h:117
#define INADDR_LOOPBACK
Definition: winsock.h:312
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
INT WINAPI getaddrinfo(const char FAR *nodename, const char FAR *servname, const struct addrinfo FAR *hints, struct addrinfo FAR *FAR *res)
Definition: addrinfo.c:804
#define SOCK_STREAM
Definition: tcpip.h:118
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define htons(x)
Definition: module.h:213
VOID WINAPI Dns_SplitHostFromDomainNameW(IN LPWSTR DomainName)
Definition: addrinfo.c:41
FORCEINLINE DWORD WsQuickProlog(VOID)
Definition: ws2_32p.h:892
static INT WINAPI QueryDNS(IN LPCSTR NodeName, IN INT SocketType, IN INT Protocol, IN WORD Port, OUT CHAR Alias[NI_MAXHOST], OUT PADDRINFOW *pptResult)
Definition: addrinfo.c:246
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define SOCK_DGRAM
Definition: winsock.h:336
#define EAI_FAMILY
Definition: ws2tcpip.h:34
HANDLE WsSockHeap
Definition: dllmain.c:21
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
short sin_family
Definition: winsock.h:510
#define HeapFree(x, y, z)
Definition: compat.h:394
#define CONST
Definition: pedump.c:81
struct sockaddr * ai_addr
Definition: ws2def.h:671
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
VOID WSAAPI Dns_Ip4AddressToReverseName_W(IN LPWSTR AddressBuffer, IN IN_ADDR Address)
Definition: addrinfo.c:28
WS2TCPIP_INLINE BOOLEAN IN6_IS_ADDR_V4MAPPED(CONST IN6_ADDR *a)
Definition: ws2ipdef.h:385