xinput1_3: Move HID data into struct xinput_controller.
[wine.git] / dlls / ws2_32 / protocol.c
blobe7fd3595fc6551c13dba4110f43ef1ae4f0f7cb0
1 /*
2 * Protocol-level socket functions
4 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
5 * Copyright (C) 2001 Stefan Leichter
6 * Copyright (C) 2004 Hans Leidekker
7 * Copyright (C) 2005 Marcus Meissner
8 * Copyright (C) 2006-2008 Kai Blin
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "ws2_32_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
28 WINE_DECLARE_DEBUG_CHANNEL(winediag);
30 static char *get_fqdn(void)
32 char *ret;
33 DWORD size = 0;
35 GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, NULL, &size );
36 if (GetLastError() != ERROR_MORE_DATA) return NULL;
37 if (!(ret = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
38 if (!GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, ret, &size ))
40 HeapFree( GetProcessHeap(), 0, ret );
41 return NULL;
43 return ret;
46 /* call Unix getaddrinfo, allocating a large enough buffer */
47 static int do_getaddrinfo( const char *node, const char *service,
48 const struct addrinfo *hints, struct addrinfo **info )
50 struct addrinfo *buffer, *new_buffer;
51 unsigned int size = 1024;
52 int ret;
54 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
55 return WSA_NOT_ENOUGH_MEMORY;
57 while ((ret = unix_funcs->getaddrinfo( node, service, hints, buffer, &size )) == ERROR_INSUFFICIENT_BUFFER)
59 if (!(new_buffer = HeapReAlloc( GetProcessHeap(), 0, buffer, size )))
61 HeapFree( GetProcessHeap(), 0, buffer );
62 return WSA_NOT_ENOUGH_MEMORY;
64 buffer = new_buffer;
67 if (!ret)
68 *info = buffer;
69 else
70 HeapFree( GetProcessHeap(), 0, buffer );
71 return ret;
75 /***********************************************************************
76 * getaddrinfo (ws2_32.@)
78 int WINAPI getaddrinfo( const char *node, const char *service,
79 const struct addrinfo *hints, struct addrinfo **info )
81 char *nodev6 = NULL, *fqdn = NULL;
82 int ret;
84 TRACE( "node %s, service %s, hints %p\n", debugstr_a(node), debugstr_a(service), hints );
86 *info = NULL;
88 if (!node && !service)
90 SetLastError( WSAHOST_NOT_FOUND );
91 return WSAHOST_NOT_FOUND;
94 if (node)
96 if (!node[0])
98 if (!(fqdn = get_fqdn())) return WSA_NOT_ENOUGH_MEMORY;
99 node = fqdn;
101 else if (!hints || hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET6)
103 /* [ipv6] or [ipv6]:portnumber are supported by Windows */
104 char *close_bracket;
106 if (node[0] == '[' && (close_bracket = strchr(node + 1, ']')))
108 nodev6 = HeapAlloc( GetProcessHeap(), 0, close_bracket - node );
109 if (!nodev6) return WSA_NOT_ENOUGH_MEMORY;
110 lstrcpynA( nodev6, node + 1, close_bracket - node );
111 node = nodev6;
116 ret = do_getaddrinfo( node, service, hints, info );
118 if (ret && (!hints || !(hints->ai_flags & AI_NUMERICHOST)) && node)
120 if (!fqdn && !(fqdn = get_fqdn()))
122 HeapFree( GetProcessHeap(), 0, nodev6 );
123 return WSA_NOT_ENOUGH_MEMORY;
125 if (!strcmp( fqdn, node ) || (!strncmp( fqdn, node, strlen( node ) ) && fqdn[strlen( node )] == '.'))
127 /* If it didn't work it means the host name IP is not in /etc/hosts, try again
128 * by sending a NULL host and avoid sending a NULL servname too because that
129 * is invalid */
130 ERR_(winediag)( "Failed to resolve your host name IP\n" );
131 ret = do_getaddrinfo( NULL, service, hints, info );
132 if (!ret && hints && (hints->ai_flags & AI_CANONNAME) && *info && !(*info)->ai_canonname)
134 freeaddrinfo( *info );
135 *info = NULL;
136 return EAI_NONAME;
141 HeapFree( GetProcessHeap(), 0, fqdn );
142 HeapFree( GetProcessHeap(), 0, nodev6 );
144 if (!ret && TRACE_ON(winsock))
146 struct addrinfo *ai;
148 for (ai = *info; ai != NULL; ai = ai->ai_next)
150 TRACE( "=> %p, flags %#x, family %d, type %d, protocol %d, len %ld, name %s, addr %s\n",
151 ai, ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol, ai->ai_addrlen,
152 ai->ai_canonname, debugstr_sockaddr(ai->ai_addr) );
156 SetLastError( ret );
157 return ret;
161 static ADDRINFOEXW *addrinfo_AtoW( const struct addrinfo *ai )
163 ADDRINFOEXW *ret;
165 if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(ADDRINFOEXW) ))) return NULL;
166 ret->ai_flags = ai->ai_flags;
167 ret->ai_family = ai->ai_family;
168 ret->ai_socktype = ai->ai_socktype;
169 ret->ai_protocol = ai->ai_protocol;
170 ret->ai_addrlen = ai->ai_addrlen;
171 ret->ai_canonname = NULL;
172 ret->ai_addr = NULL;
173 ret->ai_blob = NULL;
174 ret->ai_bloblen = 0;
175 ret->ai_provider = NULL;
176 ret->ai_next = NULL;
177 if (ai->ai_canonname)
179 int len = MultiByteToWideChar( CP_ACP, 0, ai->ai_canonname, -1, NULL, 0 );
180 if (!(ret->ai_canonname = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
182 HeapFree( GetProcessHeap(), 0, ret );
183 return NULL;
185 MultiByteToWideChar( CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len );
187 if (ai->ai_addr)
189 if (!(ret->ai_addr = HeapAlloc( GetProcessHeap(), 0, ai->ai_addrlen )))
191 HeapFree( GetProcessHeap(), 0, ret->ai_canonname );
192 HeapFree( GetProcessHeap(), 0, ret );
193 return NULL;
195 memcpy( ret->ai_addr, ai->ai_addr, ai->ai_addrlen );
197 return ret;
200 static ADDRINFOEXW *addrinfo_list_AtoW( const struct addrinfo *info )
202 ADDRINFOEXW *ret, *infoW;
204 if (!(ret = infoW = addrinfo_AtoW( info ))) return NULL;
205 while (info->ai_next)
207 if (!(infoW->ai_next = addrinfo_AtoW( info->ai_next )))
209 FreeAddrInfoExW( ret );
210 return NULL;
212 infoW = infoW->ai_next;
213 info = info->ai_next;
215 return ret;
218 static struct addrinfo *addrinfo_WtoA( const struct addrinfoW *ai )
220 struct addrinfo *ret;
222 if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(struct addrinfo) ))) return NULL;
223 ret->ai_flags = ai->ai_flags;
224 ret->ai_family = ai->ai_family;
225 ret->ai_socktype = ai->ai_socktype;
226 ret->ai_protocol = ai->ai_protocol;
227 ret->ai_addrlen = ai->ai_addrlen;
228 ret->ai_canonname = NULL;
229 ret->ai_addr = NULL;
230 ret->ai_next = NULL;
231 if (ai->ai_canonname)
233 int len = WideCharToMultiByte( CP_ACP, 0, ai->ai_canonname, -1, NULL, 0, NULL, NULL );
234 if (!(ret->ai_canonname = HeapAlloc( GetProcessHeap(), 0, len )))
236 HeapFree( GetProcessHeap(), 0, ret );
237 return NULL;
239 WideCharToMultiByte( CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len, NULL, NULL );
241 if (ai->ai_addr)
243 if (!(ret->ai_addr = HeapAlloc( GetProcessHeap(), 0, sizeof(struct sockaddr) )))
245 HeapFree( GetProcessHeap(), 0, ret->ai_canonname );
246 HeapFree( GetProcessHeap(), 0, ret );
247 return NULL;
249 memcpy( ret->ai_addr, ai->ai_addr, sizeof(struct sockaddr) );
251 return ret;
254 struct getaddrinfo_args
256 OVERLAPPED *overlapped;
257 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine;
258 ADDRINFOEXW **result;
259 char *nodename;
260 char *servname;
261 struct addrinfo *hints;
264 static void WINAPI getaddrinfo_callback(TP_CALLBACK_INSTANCE *instance, void *context)
266 struct getaddrinfo_args *args = context;
267 OVERLAPPED *overlapped = args->overlapped;
268 HANDLE event = overlapped->hEvent;
269 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine = args->completion_routine;
270 struct addrinfo *res;
271 int ret;
273 ret = getaddrinfo( args->nodename, args->servname, args->hints, &res );
274 if (res)
276 *args->result = addrinfo_list_AtoW(res);
277 overlapped->u.Pointer = args->result;
278 freeaddrinfo(res);
281 HeapFree( GetProcessHeap(), 0, args->nodename );
282 HeapFree( GetProcessHeap(), 0, args->servname );
283 HeapFree( GetProcessHeap(), 0, args );
285 overlapped->Internal = ret;
286 if (completion_routine) completion_routine( ret, 0, overlapped );
287 if (event) SetEvent( event );
290 static int getaddrinfoW( const WCHAR *nodename, const WCHAR *servname,
291 const struct addrinfo *hints, ADDRINFOEXW **res, OVERLAPPED *overlapped,
292 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine )
294 int ret = EAI_MEMORY, len, i;
295 char *nodenameA = NULL, *servnameA = NULL;
296 struct addrinfo *resA;
297 WCHAR *local_nodenameW = (WCHAR *)nodename;
299 *res = NULL;
300 if (nodename)
302 /* Is this an IDN? Most likely if any char is above the Ascii table, this
303 * is the simplest validation possible, further validation will be done by
304 * the native getaddrinfo() */
305 for (i = 0; nodename[i]; i++)
307 if (nodename[i] > 'z')
308 break;
310 if (nodename[i])
312 if (hints && (hints->ai_flags & AI_DISABLE_IDN_ENCODING))
314 /* Name requires conversion but it was disabled */
315 ret = WSAHOST_NOT_FOUND;
316 SetLastError( ret );
317 goto end;
320 len = IdnToAscii( 0, nodename, -1, NULL, 0 );
321 if (!len)
323 ERR("Failed to convert %s to punycode\n", debugstr_w(nodename));
324 ret = EAI_FAIL;
325 goto end;
327 if (!(local_nodenameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) goto end;
328 IdnToAscii( 0, nodename, -1, local_nodenameW, len );
331 if (local_nodenameW)
333 len = WideCharToMultiByte( CP_ACP, 0, local_nodenameW, -1, NULL, 0, NULL, NULL );
334 if (!(nodenameA = HeapAlloc( GetProcessHeap(), 0, len ))) goto end;
335 WideCharToMultiByte( CP_ACP, 0, local_nodenameW, -1, nodenameA, len, NULL, NULL );
337 if (servname)
339 len = WideCharToMultiByte( CP_ACP, 0, servname, -1, NULL, 0, NULL, NULL );
340 if (!(servnameA = HeapAlloc( GetProcessHeap(), 0, len ))) goto end;
341 WideCharToMultiByte( CP_ACP, 0, servname, -1, servnameA, len, NULL, NULL );
344 if (overlapped)
346 struct getaddrinfo_args *args;
348 if (overlapped->hEvent && completion_routine)
350 ret = WSAEINVAL;
351 goto end;
354 if (!(args = HeapAlloc( GetProcessHeap(), 0, sizeof(*args) + sizeof(*args->hints) ))) goto end;
355 args->overlapped = overlapped;
356 args->completion_routine = completion_routine;
357 args->result = res;
358 args->nodename = nodenameA;
359 args->servname = servnameA;
360 if (hints)
362 args->hints = (struct addrinfo *)(args + 1);
363 args->hints->ai_flags = hints->ai_flags;
364 args->hints->ai_family = hints->ai_family;
365 args->hints->ai_socktype = hints->ai_socktype;
366 args->hints->ai_protocol = hints->ai_protocol;
368 else args->hints = NULL;
370 overlapped->Internal = WSAEINPROGRESS;
371 if (!TrySubmitThreadpoolCallback( getaddrinfo_callback, args, NULL ))
373 HeapFree( GetProcessHeap(), 0, args );
374 ret = GetLastError();
375 goto end;
378 if (local_nodenameW != nodename)
379 HeapFree( GetProcessHeap(), 0, local_nodenameW );
380 SetLastError( ERROR_IO_PENDING );
381 return ERROR_IO_PENDING;
384 ret = getaddrinfo( nodenameA, servnameA, hints, &resA );
385 if (!ret)
387 *res = addrinfo_list_AtoW( resA );
388 freeaddrinfo( resA );
391 end:
392 if (local_nodenameW != nodename)
393 HeapFree( GetProcessHeap(), 0, local_nodenameW );
394 HeapFree( GetProcessHeap(), 0, nodenameA );
395 HeapFree( GetProcessHeap(), 0, servnameA );
396 return ret;
400 /***********************************************************************
401 * GetAddrInfoExW (ws2_32.@)
403 int WINAPI GetAddrInfoExW( const WCHAR *name, const WCHAR *servname, DWORD namespace,
404 GUID *namespace_id, const ADDRINFOEXW *hints, ADDRINFOEXW **result,
405 struct timeval *timeout, OVERLAPPED *overlapped,
406 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine, HANDLE *handle )
408 int ret;
410 TRACE( "name %s, servname %s, namespace %u, namespace_id %s)\n",
411 debugstr_w(name), debugstr_w(servname), namespace, debugstr_guid(namespace_id) );
413 if (namespace != NS_DNS)
414 FIXME( "Unsupported namespace %u\n", namespace );
415 if (namespace_id)
416 FIXME( "Unsupported namespace_id %s\n", debugstr_guid(namespace_id) );
417 if (timeout)
418 FIXME( "Unsupported timeout\n" );
419 if (handle)
420 FIXME( "Unsupported cancel handle\n" );
422 ret = getaddrinfoW( name, servname, (struct addrinfo *)hints, result, overlapped, completion_routine );
423 if (ret) return ret;
424 if (handle) *handle = (HANDLE)0xdeadbeef;
425 return 0;
429 /***********************************************************************
430 * GetAddrInfoExOverlappedResult (ws2_32.@)
432 int WINAPI GetAddrInfoExOverlappedResult( OVERLAPPED *overlapped )
434 TRACE( "(%p)\n", overlapped );
435 return overlapped->Internal;
439 /***********************************************************************
440 * GetAddrInfoExCancel (ws2_32.@)
442 int WINAPI GetAddrInfoExCancel( HANDLE *handle )
444 FIXME( "(%p)\n", handle );
445 return WSA_INVALID_HANDLE;
449 /***********************************************************************
450 * GetAddrInfoW (ws2_32.@)
452 int WINAPI GetAddrInfoW(const WCHAR *nodename, const WCHAR *servname, const ADDRINFOW *hints, ADDRINFOW **res)
454 struct addrinfo *hintsA = NULL;
455 ADDRINFOEXW *resex;
456 int ret = EAI_MEMORY;
458 TRACE( "nodename %s, servname %s, hints %p, result %p\n",
459 debugstr_w(nodename), debugstr_w(servname), hints, res );
461 *res = NULL;
462 if (hints) hintsA = addrinfo_WtoA( hints );
463 ret = getaddrinfoW( nodename, servname, hintsA, &resex, NULL, NULL );
464 freeaddrinfo( hintsA );
465 if (ret) return ret;
467 if (resex)
469 /* ADDRINFOEXW has a layout compatible with ADDRINFOW except for the
470 * ai_next field, so we may convert it in place */
471 *res = (ADDRINFOW *)resex;
474 ((ADDRINFOW *)resex)->ai_next = (ADDRINFOW *)resex->ai_next;
475 resex = resex->ai_next;
476 } while (resex);
478 return 0;
482 /***********************************************************************
483 * freeaddrinfo (ws2_32.@)
485 void WINAPI freeaddrinfo( struct addrinfo *info )
487 TRACE( "%p\n", info );
489 HeapFree( GetProcessHeap(), 0, info );
493 /***********************************************************************
494 * FreeAddrInfoW (ws2_32.@)
496 void WINAPI FreeAddrInfoW( ADDRINFOW *ai )
498 while (ai)
500 ADDRINFOW *next;
501 HeapFree( GetProcessHeap(), 0, ai->ai_canonname );
502 HeapFree( GetProcessHeap(), 0, ai->ai_addr );
503 next = ai->ai_next;
504 HeapFree( GetProcessHeap(), 0, ai );
505 ai = next;
510 /***********************************************************************
511 * FreeAddrInfoEx (ws2_32.@)
513 void WINAPI FreeAddrInfoEx( ADDRINFOEXA *ai )
515 TRACE( "(%p)\n", ai );
517 while (ai)
519 ADDRINFOEXA *next;
520 HeapFree( GetProcessHeap(), 0, ai->ai_canonname );
521 HeapFree( GetProcessHeap(), 0, ai->ai_addr );
522 next = ai->ai_next;
523 HeapFree( GetProcessHeap(), 0, ai );
524 ai = next;
529 /***********************************************************************
530 * FreeAddrInfoExW (ws2_32.@)
532 void WINAPI FreeAddrInfoExW( ADDRINFOEXW *ai )
534 TRACE( "(%p)\n", ai );
536 while (ai)
538 ADDRINFOEXW *next;
539 HeapFree( GetProcessHeap(), 0, ai->ai_canonname );
540 HeapFree( GetProcessHeap(), 0, ai->ai_addr );
541 next = ai->ai_next;
542 HeapFree( GetProcessHeap(), 0, ai );
543 ai = next;
548 /***********************************************************************
549 * getnameinfo (ws2_32.@)
551 int WINAPI getnameinfo( const SOCKADDR *addr, socklen_t addr_len, char *host,
552 DWORD host_len, char *serv, DWORD serv_len, int flags )
554 TRACE( "addr %s, addr_len %d, host %p, host_len %u, serv %p, serv_len %d, flags %#x\n",
555 debugstr_sockaddr(addr), addr_len, host, host_len, serv, serv_len, flags );
557 return unix_funcs->getnameinfo( addr, addr_len, host, host_len, serv, serv_len, flags );
561 /***********************************************************************
562 * GetNameInfoW (ws2_32.@)
564 int WINAPI GetNameInfoW( const SOCKADDR *addr, socklen_t addr_len, WCHAR *host,
565 DWORD host_len, WCHAR *serv, DWORD serv_len, int flags )
567 int ret;
568 char *hostA = NULL, *servA = NULL;
570 if (host && (!(hostA = HeapAlloc( GetProcessHeap(), 0, host_len ))))
571 return EAI_MEMORY;
572 if (serv && (!(servA = HeapAlloc( GetProcessHeap(), 0, serv_len ))))
574 HeapFree( GetProcessHeap(), 0, hostA );
575 return EAI_MEMORY;
578 ret = getnameinfo( addr, addr_len, hostA, host_len, servA, serv_len, flags );
579 if (!ret)
581 if (host) MultiByteToWideChar( CP_ACP, 0, hostA, -1, host, host_len );
582 if (serv) MultiByteToWideChar( CP_ACP, 0, servA, -1, serv, serv_len );
585 HeapFree( GetProcessHeap(), 0, hostA );
586 HeapFree( GetProcessHeap(), 0, servA );
587 return ret;
591 static struct hostent *get_hostent_buffer( unsigned int size )
593 struct per_thread_data *data = get_per_thread_data();
594 if (data->he_buffer)
596 if (data->he_len >= size) return data->he_buffer;
597 HeapFree( GetProcessHeap(), 0, data->he_buffer );
599 data->he_buffer = HeapAlloc( GetProcessHeap(), 0, (data->he_len = size) );
600 if (!data->he_buffer) SetLastError(WSAENOBUFS);
601 return data->he_buffer;
604 /* create a hostent entry
606 * Creates the entry with enough memory for the name, aliases
607 * addresses, and the address pointers. Also copies the name
608 * and sets up all the pointers.
610 * NOTE: The alias and address lists must be allocated with room
611 * for the NULL item terminating the list. This is true even if
612 * the list has no items ("aliases" and "addresses" must be
613 * at least "1", a truly empty list is invalid).
615 static struct hostent *create_hostent( char *name, int alias_count, int aliases_size,
616 int address_count, int address_length )
618 struct hostent *p_to;
619 char *p;
620 unsigned int size = sizeof(struct hostent), i;
622 size += strlen(name) + 1;
623 size += alias_count * sizeof(char *);
624 size += aliases_size;
625 size += address_count * sizeof(char *);
626 size += (address_count - 1) * address_length;
628 if (!(p_to = get_hostent_buffer( size ))) return NULL;
629 memset( p_to, 0, size );
631 /* Use the memory in the same way winsock does.
632 * First set the pointer for aliases, second set the pointers for addresses.
633 * Third fill the addresses indexes, fourth jump aliases names size.
634 * Fifth fill the hostname.
635 * NOTE: This method is valid for OS versions >= XP.
637 p = (char *)(p_to + 1);
638 p_to->h_aliases = (char **)p;
639 p += alias_count * sizeof(char *);
641 p_to->h_addr_list = (char **)p;
642 p += address_count * sizeof(char *);
644 for (i = 0, address_count--; i < address_count; i++, p += address_length)
645 p_to->h_addr_list[i] = p;
647 /* h_aliases must be filled in manually because we don't know each string
648 * size. Leave these pointers NULL (already set to NULL by memset earlier).
650 p += aliases_size;
652 p_to->h_name = p;
653 strcpy( p, name );
655 return p_to;
659 /***********************************************************************
660 * gethostbyaddr (ws2_32.51)
662 struct hostent * WINAPI gethostbyaddr( const char *addr, int len, int family )
664 unsigned int size = 1024;
665 struct hostent *host;
666 int ret;
668 if (!(host = get_hostent_buffer( size )))
669 return NULL;
671 while ((ret = unix_funcs->gethostbyaddr( addr, len, family, host, &size )) == ERROR_INSUFFICIENT_BUFFER)
673 if (!(host = get_hostent_buffer( size )))
674 return NULL;
677 SetLastError( ret );
678 return ret ? NULL : host;
682 struct route
684 struct in_addr addr;
685 IF_INDEX interface;
686 DWORD metric, default_route;
689 static int __cdecl compare_routes_by_metric_asc( const void *left, const void *right )
691 const struct route *a = left, *b = right;
692 if (a->default_route && b->default_route)
693 return a->default_route - b->default_route;
694 if (a->default_route && !b->default_route)
695 return -1;
696 if (b->default_route && !a->default_route)
697 return 1;
698 return a->metric - b->metric;
701 /* Returns the list of local IP addresses by going through the network
702 * adapters and using the local routing table to sort the addresses
703 * from highest routing priority to lowest routing priority. This
704 * functionality is inferred from the description for obtaining local
705 * IP addresses given in the Knowledge Base Article Q160215.
707 * Please note that the returned hostent is only freed when the thread
708 * closes and is replaced if another hostent is requested.
710 static struct hostent *get_local_ips( char *hostname )
712 int numroutes = 0, i, j, default_routes = 0;
713 IP_ADAPTER_INFO *adapters = NULL, *k;
714 struct hostent *hostlist = NULL;
715 MIB_IPFORWARDTABLE *routes = NULL;
716 struct route *route_addrs = NULL;
717 DWORD adap_size, route_size, n;
719 /* Obtain the size of the adapter list and routing table, also allocate memory */
720 if (GetAdaptersInfo( NULL, &adap_size ) != ERROR_BUFFER_OVERFLOW)
721 return NULL;
722 if (GetIpForwardTable( NULL, &route_size, FALSE ) != ERROR_INSUFFICIENT_BUFFER)
723 return NULL;
725 adapters = HeapAlloc( GetProcessHeap(), 0, adap_size );
726 routes = HeapAlloc( GetProcessHeap(), 0, route_size );
727 if (!adapters || !routes)
728 goto cleanup;
730 /* Obtain the adapter list and the full routing table */
731 if (GetAdaptersInfo( adapters, &adap_size ) != NO_ERROR)
732 goto cleanup;
733 if (GetIpForwardTable( routes, &route_size, FALSE ) != NO_ERROR)
734 goto cleanup;
736 /* Store the interface associated with each route */
737 for (n = 0; n < routes->dwNumEntries; n++)
739 IF_INDEX ifindex;
740 DWORD ifmetric, ifdefault = 0;
741 BOOL exists = FALSE;
743 /* Check if this is a default route (there may be more than one) */
744 if (!routes->table[n].dwForwardDest)
745 ifdefault = ++default_routes;
746 else if (routes->table[n].u1.ForwardType != MIB_IPROUTE_TYPE_DIRECT)
747 continue;
748 ifindex = routes->table[n].dwForwardIfIndex;
749 ifmetric = routes->table[n].dwForwardMetric1;
750 /* Only store the lowest valued metric for an interface */
751 for (j = 0; j < numroutes; j++)
753 if (route_addrs[j].interface == ifindex)
755 if (route_addrs[j].metric > ifmetric)
756 route_addrs[j].metric = ifmetric;
757 exists = TRUE;
760 if (exists)
761 continue;
762 route_addrs = heap_realloc( route_addrs, (numroutes + 1) * sizeof(struct route) );
763 if (!route_addrs)
764 goto cleanup;
765 route_addrs[numroutes].interface = ifindex;
766 route_addrs[numroutes].metric = ifmetric;
767 route_addrs[numroutes].default_route = ifdefault;
768 /* If no IP is found in the next step (for whatever reason)
769 * then fall back to the magic loopback address.
771 memcpy( &route_addrs[numroutes].addr.s_addr, magic_loopback_addr, 4 );
772 numroutes++;
774 if (numroutes == 0)
775 goto cleanup; /* No routes, fall back to the Magic IP */
777 /* Find the IP address associated with each found interface */
778 for (i = 0; i < numroutes; i++)
780 for (k = adapters; k != NULL; k = k->Next)
782 char *ip = k->IpAddressList.IpAddress.String;
784 if (route_addrs[i].interface == k->Index)
785 route_addrs[i].addr.s_addr = inet_addr(ip);
789 /* Allocate a hostent and enough memory for all the IPs,
790 * including the NULL at the end of the list.
792 hostlist = create_hostent( hostname, 1, 0, numroutes+1, sizeof(struct in_addr) );
793 if (hostlist == NULL)
794 goto cleanup;
795 hostlist->h_addr_list[numroutes] = NULL;
796 hostlist->h_aliases[0] = NULL;
797 hostlist->h_addrtype = AF_INET;
798 hostlist->h_length = sizeof(struct in_addr);
800 /* Reorder the entries before placing them in the host list. Windows expects
801 * the IP list in order from highest priority to lowest (the critical thing
802 * is that most applications expect the first IP to be the default route).
804 if (numroutes > 1)
805 qsort( route_addrs, numroutes, sizeof(struct route), compare_routes_by_metric_asc );
807 for (i = 0; i < numroutes; i++)
808 *(struct in_addr *)hostlist->h_addr_list[i] = route_addrs[i].addr;
810 cleanup:
811 HeapFree( GetProcessHeap(), 0, route_addrs );
812 HeapFree( GetProcessHeap(), 0, adapters );
813 HeapFree( GetProcessHeap(), 0, routes );
814 return hostlist;
818 /***********************************************************************
819 * gethostbyname (ws2_32.52)
821 struct hostent * WINAPI gethostbyname( const char *name )
823 struct hostent *host = NULL;
824 char hostname[100];
825 int ret;
827 TRACE( "%s\n", debugstr_a(name) );
829 if (!num_startup)
831 SetLastError( WSANOTINITIALISED );
832 return NULL;
835 if ((ret = unix_funcs->gethostname( hostname, 100 )))
837 SetLastError( ret );
838 return NULL;
841 if (!name || !name[0])
842 name = hostname;
844 /* If the hostname of the local machine is requested then return the
845 * complete list of local IP addresses */
846 if (!strcmp( name, hostname ))
847 host = get_local_ips( hostname );
849 /* If any other hostname was requested (or the routing table lookup failed)
850 * then return the IP found by the host OS */
851 if (!host)
853 unsigned int size = 1024;
854 int ret;
856 if (!(host = get_hostent_buffer( size )))
857 return NULL;
859 while ((ret = unix_funcs->gethostbyname( name, host, &size )) == ERROR_INSUFFICIENT_BUFFER)
861 if (!(host = get_hostent_buffer( size )))
862 return NULL;
865 SetLastError( ret );
866 return ret ? NULL : host;
869 if (host && host->h_addr_list[0][0] == 127 && strcmp( name, "localhost" ))
871 /* hostname != "localhost" but has loopback address. replace by our
872 * special address.*/
873 memcpy( host->h_addr_list[0], magic_loopback_addr, 4 );
876 return host;
880 /***********************************************************************
881 * gethostname (ws2_32.57)
883 int WINAPI gethostname( char *name, int namelen )
885 char buf[256];
886 int len, ret;
888 TRACE( "name %p, len %d\n", name, namelen );
890 if (!name)
892 SetLastError( WSAEFAULT );
893 return -1;
896 if ((ret = unix_funcs->gethostname( buf, sizeof(buf) )))
898 SetLastError( ret );
899 return -1;
902 TRACE( "<- %s\n", debugstr_a(buf) );
903 len = strlen( buf );
904 if (len > 15)
905 WARN( "Windows supports NetBIOS name length up to 15 bytes!\n" );
906 if (namelen <= len)
908 SetLastError( WSAEFAULT );
909 return -1;
911 strcpy( name, buf );
912 return 0;
916 /***********************************************************************
917 * GetHostNameW (ws2_32.@)
919 int WINAPI GetHostNameW( WCHAR *name, int namelen )
921 char buf[256];
922 int ret;
924 TRACE( "name %p, len %d\n", name, namelen );
926 if (!name)
928 SetLastError( WSAEFAULT );
929 return -1;
932 if ((ret = unix_funcs->gethostname( buf, sizeof(buf) )))
934 SetLastError( ret );
935 return -1;
938 if (MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 ) > namelen)
940 SetLastError( WSAEFAULT );
941 return -1;
943 MultiByteToWideChar( CP_ACP, 0, buf, -1, name, namelen );
944 return 0;
948 static char *read_etc_file( const WCHAR *filename, DWORD *ret_size )
950 WCHAR path[MAX_PATH];
951 DWORD size = sizeof(path);
952 HANDLE file;
953 char *data;
954 LONG ret;
956 if ((ret = RegGetValueW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\tcpip\\Parameters",
957 L"DatabasePath", RRF_RT_REG_SZ, NULL, path, &size )))
959 ERR( "failed to get database path, error %u\n", ret );
960 return NULL;
962 wcscat( path, L"\\" );
963 wcscat( path, filename );
965 file = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
966 if (file == INVALID_HANDLE_VALUE)
968 ERR( "failed to open %s, error %u\n", debugstr_w( path ), GetLastError() );
969 return NULL;
972 size = GetFileSize( file, NULL );
973 if (!(data = HeapAlloc( GetProcessHeap(), 0, size )) ||
974 !ReadFile( file, data, size, ret_size, NULL ))
976 WARN( "failed to read file, error %u\n", GetLastError() );
977 HeapFree( GetProcessHeap(), 0, data );
978 data = NULL;
980 CloseHandle( file );
981 return data;
984 /* returns "end" if there was no space */
985 static char *next_space( const char *p, const char *end )
987 while (p < end && !isspace( *p ))
988 ++p;
989 return (char *)p;
992 /* returns "end" if there was no non-space */
993 static char *next_non_space( const char *p, const char *end )
995 while (p < end && isspace( *p ))
996 ++p;
997 return (char *)p;
1001 static struct protoent *get_protoent_buffer( unsigned int size )
1003 struct per_thread_data *data = get_per_thread_data();
1005 if (data->pe_buffer)
1007 if (data->pe_len >= size) return data->pe_buffer;
1008 HeapFree( GetProcessHeap(), 0, data->pe_buffer );
1010 data->pe_len = size;
1011 data->pe_buffer = HeapAlloc( GetProcessHeap(), 0, size );
1012 if (!data->pe_buffer) SetLastError( WSAENOBUFS );
1013 return data->pe_buffer;
1016 /* Parse the first valid line into a protoent structure, returning NULL if
1017 * there is no valid line. Updates cursor to point to the start of the next
1018 * line or the end of the file. */
1019 static struct protoent *get_next_protocol( const char **cursor, const char *end )
1021 const char *p = *cursor;
1023 while (p < end)
1025 const char *line_end, *next_line;
1026 size_t needed_size, line_len;
1027 unsigned int alias_count = 0;
1028 struct protoent *proto;
1029 const char *name;
1030 int number;
1031 char *q;
1033 for (line_end = p; line_end < end && *line_end != '\n' && *line_end != '#'; ++line_end)
1035 TRACE( "parsing line %s\n", debugstr_an(p, line_end - p) );
1037 for (next_line = line_end; next_line < end && *next_line != '\n'; ++next_line)
1039 if (next_line < end)
1040 ++next_line; /* skip over the newline */
1042 p = next_non_space( p, line_end );
1043 if (p == line_end)
1045 p = next_line;
1046 continue;
1049 /* parse the name */
1051 name = p;
1052 line_len = line_end - name;
1054 p = next_space( p, line_end );
1055 if (p == line_end)
1057 p = next_line;
1058 continue;
1061 p = next_non_space( p, line_end );
1063 /* parse the number */
1065 number = atoi( p );
1067 p = next_space( p, line_end );
1068 p = next_non_space( p, line_end );
1070 /* we will copy the entire line after the protoent structure, then
1071 * replace spaces with null bytes as necessary */
1073 while (p < line_end)
1075 ++alias_count;
1077 p = next_space( p, line_end );
1078 p = next_non_space( p, line_end );
1080 needed_size = sizeof(*proto) + line_len + 1 + (alias_count + 1) * sizeof(char *);
1082 if (!(proto = get_protoent_buffer( needed_size )))
1084 SetLastError( WSAENOBUFS );
1085 return NULL;
1088 proto->p_proto = number;
1089 proto->p_aliases = (char **)(proto + 1);
1090 proto->p_name = (char *)(proto->p_aliases + alias_count + 1);
1092 memcpy( proto->p_name, name, line_len );
1093 proto->p_name[line_len] = 0;
1095 line_end = proto->p_name + line_len;
1097 q = proto->p_name;
1098 q = next_space( q, line_end );
1099 *q++ = 0;
1100 q = next_non_space( q, line_end );
1101 /* skip over the number */
1102 q = next_space( q, line_end );
1103 q = next_non_space( q, line_end );
1105 alias_count = 0;
1106 while (q < line_end)
1108 proto->p_aliases[alias_count++] = q;
1109 q = next_space( q, line_end );
1110 if (q < line_end) *q++ = 0;
1111 q = next_non_space( q, line_end );
1113 proto->p_aliases[alias_count] = NULL;
1115 *cursor = next_line;
1116 return proto;
1119 SetLastError( WSANO_DATA );
1120 return NULL;
1124 /***********************************************************************
1125 * getprotobyname (ws2_32.53)
1127 struct protoent * WINAPI getprotobyname( const char *name )
1129 struct protoent *proto;
1130 const char *cursor;
1131 char *file;
1132 DWORD size;
1134 TRACE( "%s\n", debugstr_a(name) );
1136 if (!(file = read_etc_file( L"protocol", &size )))
1138 SetLastError( WSANO_DATA );
1139 return NULL;
1142 cursor = file;
1143 while ((proto = get_next_protocol( &cursor, file + size )))
1145 if (!strcasecmp( proto->p_name, name ))
1146 break;
1149 HeapFree( GetProcessHeap(), 0, file );
1150 return proto;
1154 /***********************************************************************
1155 * getprotobynumber (ws2_32.54)
1157 struct protoent * WINAPI getprotobynumber( int number )
1159 struct protoent *proto;
1160 const char *cursor;
1161 char *file;
1162 DWORD size;
1164 TRACE( "%d\n", number );
1166 if (!(file = read_etc_file( L"protocol", &size )))
1168 SetLastError( WSANO_DATA );
1169 return NULL;
1172 cursor = file;
1173 while ((proto = get_next_protocol( &cursor, file + size )))
1175 if (proto->p_proto == number)
1176 break;
1179 HeapFree( GetProcessHeap(), 0, file );
1180 return proto;
1184 static struct servent *get_servent_buffer( int size )
1186 struct per_thread_data *data = get_per_thread_data();
1187 if (data->se_buffer)
1189 if (data->se_len >= size) return data->se_buffer;
1190 HeapFree( GetProcessHeap(), 0, data->se_buffer );
1192 data->se_len = size;
1193 data->se_buffer = HeapAlloc( GetProcessHeap(), 0, size );
1194 if (!data->se_buffer) SetLastError( WSAENOBUFS );
1195 return data->se_buffer;
1198 /* Parse the first valid line into a servent structure, returning NULL if
1199 * there is no valid line. Updates cursor to point to the start of the next
1200 * line or the end of the file. */
1201 static struct servent *get_next_service( const char **cursor, const char *end )
1203 const char *p = *cursor;
1205 while (p < end)
1207 const char *line_end, *next_line;
1208 size_t needed_size, line_len;
1209 unsigned int alias_count = 0;
1210 struct servent *serv;
1211 const char *name;
1212 int port;
1213 char *q;
1215 for (line_end = p; line_end < end && *line_end != '\n' && *line_end != '#'; ++line_end)
1217 TRACE( "parsing line %s\n", debugstr_an(p, line_end - p) );
1219 for (next_line = line_end; next_line < end && *next_line != '\n'; ++next_line)
1221 if (next_line < end)
1222 ++next_line; /* skip over the newline */
1224 p = next_non_space( p, line_end );
1225 if (p == line_end)
1227 p = next_line;
1228 continue;
1231 /* parse the name */
1233 name = p;
1234 line_len = line_end - name;
1236 p = next_space( p, line_end );
1237 if (p == line_end)
1239 p = next_line;
1240 continue;
1243 p = next_non_space( p, line_end );
1245 /* parse the port */
1247 port = atoi( p );
1248 p = memchr( p, '/', line_end - p );
1249 if (!p)
1251 p = next_line;
1252 continue;
1255 p = next_space( p, line_end );
1256 p = next_non_space( p, line_end );
1258 /* we will copy the entire line after the servent structure, then
1259 * replace spaces with null bytes as necessary */
1261 while (p < line_end)
1263 ++alias_count;
1265 p = next_space( p, line_end );
1266 p = next_non_space( p, line_end );
1268 needed_size = sizeof(*serv) + line_len + 1 + (alias_count + 1) * sizeof(char *);
1270 if (!(serv = get_servent_buffer( needed_size )))
1272 SetLastError( WSAENOBUFS );
1273 return NULL;
1276 serv->s_port = htons( port );
1277 serv->s_aliases = (char **)(serv + 1);
1278 serv->s_name = (char *)(serv->s_aliases + alias_count + 1);
1280 memcpy( serv->s_name, name, line_len );
1281 serv->s_name[line_len] = 0;
1283 line_end = serv->s_name + line_len;
1285 q = serv->s_name;
1286 q = next_space( q, line_end );
1287 *q++ = 0;
1288 q = next_non_space( q, line_end );
1289 /* skip over the number */
1290 q = memchr( q, '/', line_end - q );
1291 serv->s_proto = ++q;
1292 q = next_space( q, line_end );
1293 if (q < line_end) *q++ = 0;
1294 q = next_non_space( q, line_end );
1296 alias_count = 0;
1297 while (q < line_end)
1299 serv->s_aliases[alias_count++] = q;
1300 q = next_space( q, line_end );
1301 if (q < line_end) *q++ = 0;
1302 q = next_non_space( q, line_end );
1304 serv->s_aliases[alias_count] = NULL;
1306 *cursor = next_line;
1307 return serv;
1310 SetLastError( WSANO_DATA );
1311 return NULL;
1315 /***********************************************************************
1316 * getservbyname (ws2_32.55)
1318 struct servent * WINAPI getservbyname( const char *name, const char *proto )
1320 struct servent *serv;
1321 const char *cursor;
1322 char *file;
1323 DWORD size;
1325 TRACE( "name %s, proto %s\n", debugstr_a(name), debugstr_a(proto) );
1327 if (!(file = read_etc_file( L"services", &size )))
1329 SetLastError( WSANO_DATA );
1330 return NULL;
1333 cursor = file;
1334 while ((serv = get_next_service( &cursor, file + size )))
1336 if (!strcasecmp( serv->s_name, name ) && (!proto || !strcasecmp( serv->s_proto, proto )))
1337 break;
1340 HeapFree( GetProcessHeap(), 0, file );
1341 return serv;
1345 /***********************************************************************
1346 * getservbyport (ws2_32.56)
1348 struct servent * WINAPI getservbyport( int port, const char *proto )
1350 struct servent *serv;
1351 const char *cursor;
1352 char *file;
1353 DWORD size;
1355 TRACE( "port %d, proto %s\n", port, debugstr_a(proto) );
1357 if (!(file = read_etc_file( L"services", &size )))
1359 SetLastError( WSANO_DATA );
1360 return NULL;
1363 cursor = file;
1364 while ((serv = get_next_service( &cursor, file + size )))
1366 if (serv->s_port == port && (!proto || !strcasecmp( serv->s_proto, proto )))
1367 break;
1370 HeapFree( GetProcessHeap(), 0, file );
1371 return serv;
1375 /***********************************************************************
1376 * inet_ntoa (ws2_32.12)
1378 char * WINAPI inet_ntoa( struct in_addr in )
1380 unsigned int long_ip = ntohl( in.s_addr );
1381 struct per_thread_data *data = get_per_thread_data();
1383 sprintf( data->ntoa_buffer, "%u.%u.%u.%u",
1384 (long_ip >> 24) & 0xff,
1385 (long_ip >> 16) & 0xff,
1386 (long_ip >> 8) & 0xff,
1387 long_ip & 0xff );
1389 return data->ntoa_buffer;
1393 /***********************************************************************
1394 * inet_ntop (ws2_32.@)
1396 const char * WINAPI inet_ntop( int family, void *addr, char *buffer, SIZE_T len )
1398 NTSTATUS status;
1399 ULONG size = min( len, (ULONG)-1 );
1401 TRACE( "family %d, addr %p, buffer %p, len %ld\n", family, addr, buffer, len );
1402 if (!buffer)
1404 SetLastError( STATUS_INVALID_PARAMETER );
1405 return NULL;
1408 switch (family)
1410 case AF_INET:
1412 status = RtlIpv4AddressToStringExA( (IN_ADDR *)addr, 0, buffer, &size );
1413 break;
1415 case AF_INET6:
1417 status = RtlIpv6AddressToStringExA( (IN6_ADDR *)addr, 0, 0, buffer, &size );
1418 break;
1420 default:
1421 SetLastError( WSAEAFNOSUPPORT );
1422 return NULL;
1425 if (status == STATUS_SUCCESS) return buffer;
1426 SetLastError( STATUS_INVALID_PARAMETER );
1427 return NULL;
1430 /***********************************************************************
1431 * inet_pton (ws2_32.@)
1433 int WINAPI inet_pton( int family, const char *addr, void *buffer )
1435 NTSTATUS status;
1436 const char *terminator;
1438 TRACE( "family %d, addr %s, buffer %p\n", family, debugstr_a(addr), buffer );
1440 if (!addr || !buffer)
1442 SetLastError( WSAEFAULT );
1443 return -1;
1446 switch (family)
1448 case AF_INET:
1449 status = RtlIpv4StringToAddressA(addr, TRUE, &terminator, buffer);
1450 break;
1451 case AF_INET6:
1452 status = RtlIpv6StringToAddressA(addr, &terminator, buffer);
1453 break;
1454 default:
1455 SetLastError( WSAEAFNOSUPPORT );
1456 return -1;
1459 return (status == STATUS_SUCCESS && *terminator == 0);
1462 /***********************************************************************
1463 * InetPtonW (ws2_32.@)
1465 int WINAPI InetPtonW( int family, const WCHAR *addr, void *buffer )
1467 char *addrA;
1468 int len;
1469 INT ret;
1471 TRACE( "family %d, addr %s, buffer %p\n", family, debugstr_w(addr), buffer );
1473 if (!addr)
1475 SetLastError(WSAEFAULT);
1476 return SOCKET_ERROR;
1479 len = WideCharToMultiByte( CP_ACP, 0, addr, -1, NULL, 0, NULL, NULL );
1480 if (!(addrA = HeapAlloc( GetProcessHeap(), 0, len )))
1482 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1483 return -1;
1485 WideCharToMultiByte( CP_ACP, 0, addr, -1, addrA, len, NULL, NULL );
1487 ret = inet_pton( family, addrA, buffer );
1488 if (!ret) SetLastError( WSAEINVAL );
1490 HeapFree( GetProcessHeap(), 0, addrA );
1491 return ret;
1494 /***********************************************************************
1495 * InetNtopW (ws2_32.@)
1497 const WCHAR * WINAPI InetNtopW( int family, void *addr, WCHAR *buffer, SIZE_T len )
1499 char bufferA[INET6_ADDRSTRLEN];
1500 PWSTR ret = NULL;
1502 TRACE( "family %d, addr %p, buffer %p, len %ld\n", family, addr, buffer, len );
1504 if (inet_ntop( family, addr, bufferA, sizeof(bufferA) ))
1506 if (MultiByteToWideChar( CP_ACP, 0, bufferA, -1, buffer, len ))
1507 ret = buffer;
1508 else
1509 SetLastError( ERROR_INVALID_PARAMETER );
1511 return ret;
1515 /***********************************************************************
1516 * WSAStringToAddressA (ws2_32.@)
1518 int WINAPI WSAStringToAddressA( char *string, int family, WSAPROTOCOL_INFOA *protocol_info,
1519 struct sockaddr *addr, int *addr_len )
1521 NTSTATUS status;
1523 TRACE( "string %s, family %u\n", debugstr_a(string), family );
1525 if (!addr || !addr_len) return -1;
1527 if (!string)
1529 SetLastError( WSAEINVAL );
1530 return -1;
1533 if (protocol_info)
1534 FIXME( "ignoring protocol_info\n" );
1536 switch (family)
1538 case AF_INET:
1540 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1542 if (*addr_len < sizeof(struct sockaddr_in))
1544 *addr_len = sizeof(struct sockaddr_in);
1545 SetLastError( WSAEFAULT );
1546 return -1;
1548 memset( addr, 0, sizeof(struct sockaddr_in) );
1550 status = RtlIpv4StringToAddressExA( string, FALSE, &addr4->sin_addr, &addr4->sin_port );
1551 if (status != STATUS_SUCCESS)
1553 SetLastError( WSAEINVAL );
1554 return -1;
1556 addr4->sin_family = AF_INET;
1557 *addr_len = sizeof(struct sockaddr_in);
1558 return 0;
1560 case AF_INET6:
1562 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1564 if (*addr_len < sizeof(struct sockaddr_in6))
1566 *addr_len = sizeof(struct sockaddr_in6);
1567 SetLastError( WSAEFAULT );
1568 return -1;
1570 memset( addr, 0, sizeof(struct sockaddr_in6) );
1572 status = RtlIpv6StringToAddressExA( string, &addr6->sin6_addr, &addr6->sin6_scope_id, &addr6->sin6_port );
1573 if (status != STATUS_SUCCESS)
1575 SetLastError( WSAEINVAL );
1576 return -1;
1578 addr6->sin6_family = AF_INET6;
1579 *addr_len = sizeof(struct sockaddr_in6);
1580 return 0;
1582 default:
1583 /* According to MSDN, only AF_INET and AF_INET6 are supported. */
1584 TRACE( "Unsupported address family specified: %d.\n", family );
1585 SetLastError( WSAEINVAL );
1586 return -1;
1591 /***********************************************************************
1592 * WSAStringToAddressW (ws2_32.@)
1594 int WINAPI WSAStringToAddressW( WCHAR *string, int family, WSAPROTOCOL_INFOW *protocol_info,
1595 struct sockaddr *addr, int *addr_len )
1597 WSAPROTOCOL_INFOA infoA;
1598 WSAPROTOCOL_INFOA *protocol_infoA = NULL;
1599 int sizeA, ret;
1600 char *stringA;
1602 TRACE( "string %s, family %u\n", debugstr_w(string), family );
1604 if (!addr || !addr_len) return -1;
1606 if (protocol_info)
1608 protocol_infoA = &infoA;
1609 memcpy( protocol_infoA, protocol_info, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
1611 if (!WideCharToMultiByte( CP_ACP, 0, protocol_info->szProtocol, -1, protocol_infoA->szProtocol,
1612 sizeof(protocol_infoA->szProtocol), NULL, NULL ))
1614 SetLastError( WSAEINVAL );
1615 return -1;
1619 if (!string)
1621 SetLastError( WSAEINVAL );
1622 return -1;
1625 sizeA = WideCharToMultiByte( CP_ACP, 0, string, -1, NULL, 0, NULL, NULL );
1626 if (!(stringA = HeapAlloc( GetProcessHeap(), 0, sizeA )))
1628 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1629 return -1;
1631 WideCharToMultiByte( CP_ACP, 0, string, -1, stringA, sizeA, NULL, NULL );
1632 ret = WSAStringToAddressA( stringA, family, protocol_infoA, addr, addr_len );
1633 HeapFree( GetProcessHeap(), 0, stringA );
1634 return ret;
1638 /***********************************************************************
1639 * WSAAddressToStringA (ws2_32.@)
1641 int WINAPI WSAAddressToStringA( struct sockaddr *addr, DWORD addr_len,
1642 WSAPROTOCOL_INFOA *info, char *string, DWORD *string_len )
1644 char buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
1645 DWORD size;
1647 TRACE( "addr %s\n", debugstr_sockaddr(addr) );
1649 if (!addr) return SOCKET_ERROR;
1650 if (!string || !string_len) return SOCKET_ERROR;
1652 switch (addr->sa_family)
1654 case AF_INET:
1656 const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
1657 unsigned int long_ip = ntohl( addr4->sin_addr.s_addr );
1658 char *p;
1660 if (addr_len < sizeof(struct sockaddr_in)) return -1;
1661 sprintf( buffer, "%u.%u.%u.%u:%u",
1662 (long_ip >> 24) & 0xff,
1663 (long_ip >> 16) & 0xff,
1664 (long_ip >> 8) & 0xff,
1665 long_ip & 0xff,
1666 ntohs( addr4->sin_port ) );
1668 p = strchr( buffer, ':' );
1669 if (!addr4->sin_port) *p = 0;
1670 break;
1672 case AF_INET6:
1674 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1675 size_t len;
1677 buffer[0] = 0;
1678 if (addr_len < sizeof(struct sockaddr_in6)) return -1;
1679 if (addr6->sin6_port)
1680 strcpy( buffer, "[" );
1681 len = strlen( buffer );
1682 if (!inet_ntop( AF_INET6, &addr6->sin6_addr, &buffer[len], sizeof(buffer) - len ))
1684 SetLastError( WSAEINVAL );
1685 return -1;
1687 if (addr6->sin6_scope_id)
1688 sprintf( buffer + strlen( buffer ), "%%%u", addr6->sin6_scope_id );
1689 if (addr6->sin6_port)
1690 sprintf( buffer + strlen( buffer ), "]:%u", ntohs( addr6->sin6_port ) );
1691 break;
1694 default:
1695 SetLastError( WSAEINVAL );
1696 return -1;
1699 size = strlen( buffer ) + 1;
1701 if (*string_len < size)
1703 *string_len = size;
1704 SetLastError( WSAEFAULT );
1705 return -1;
1708 TRACE( "=> %s, %u bytes\n", debugstr_a(buffer), size );
1709 *string_len = size;
1710 strcpy( string, buffer );
1711 return 0;
1715 /***********************************************************************
1716 * WSAAddressToStringW (ws2_32.@)
1718 int WINAPI WSAAddressToStringW( struct sockaddr *addr, DWORD addr_len,
1719 WSAPROTOCOL_INFOW *info, WCHAR *string, DWORD *string_len )
1721 INT ret;
1722 char buf[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
1724 TRACE( "(%p, %d, %p, %p, %p)\n", addr, addr_len, info, string, string_len );
1726 if ((ret = WSAAddressToStringA( addr, addr_len, NULL, buf, string_len ))) return ret;
1728 MultiByteToWideChar( CP_ACP, 0, buf, *string_len, string, *string_len );
1729 TRACE( "=> %s, %u chars\n", debugstr_w(string), *string_len );
1730 return 0;
1734 /***********************************************************************
1735 * inet_addr (ws2_32.11)
1737 u_long WINAPI inet_addr( const char *str )
1739 u_long addr;
1741 if (inet_pton( AF_INET, str, &addr ) == 1)
1742 return addr;
1743 return INADDR_NONE;
1747 /***********************************************************************
1748 * htonl (ws2_32.8)
1750 u_long WINAPI WS_htonl( u_long hostlong )
1752 return htonl( hostlong );
1756 /***********************************************************************
1757 * htons (ws2_32.9)
1759 u_short WINAPI WS_htons( u_short hostshort )
1761 return htons( hostshort );
1765 /***********************************************************************
1766 * WSAHtonl (ws2_32.@)
1768 int WINAPI WSAHtonl( SOCKET s, u_long hostlong, u_long *netlong )
1770 if (netlong)
1772 *netlong = htonl( hostlong );
1773 return 0;
1775 SetLastError( WSAEFAULT );
1776 return -1;
1780 /***********************************************************************
1781 * WSAHtons (ws2_32.@)
1783 int WINAPI WSAHtons( SOCKET s, u_short hostshort, u_short *netshort )
1785 if (netshort)
1787 *netshort = htons( hostshort );
1788 return 0;
1790 SetLastError( WSAEFAULT );
1791 return -1;
1795 /***********************************************************************
1796 * ntohl (ws2_32.14)
1798 u_long WINAPI WS_ntohl( u_long netlong )
1800 return ntohl( netlong );
1804 /***********************************************************************
1805 * ntohs (ws2_32.15)
1807 u_short WINAPI WS_ntohs( u_short netshort )
1809 return ntohs( netshort );
1813 /***********************************************************************
1814 * WSANtohl (ws2_32.@)
1816 int WINAPI WSANtohl( SOCKET s, u_long netlong, u_long *hostlong )
1818 if (!hostlong) return WSAEFAULT;
1820 *hostlong = ntohl( netlong );
1821 return 0;
1825 /***********************************************************************
1826 * WSANtohs (ws2_32.@)
1828 int WINAPI WSANtohs( SOCKET s, u_short netshort, u_short *hostshort )
1830 if (!hostshort) return WSAEFAULT;
1832 *hostshort = ntohs( netshort );
1833 return 0;
1837 /***********************************************************************
1838 * WSAInstallServiceClassA (ws2_32.@)
1840 int WINAPI WSAInstallServiceClassA( WSASERVICECLASSINFOA *info )
1842 FIXME( "Request to install service %s\n", debugstr_a(info->lpszServiceClassName) );
1843 SetLastError( WSAEACCES );
1844 return -1;
1848 /***********************************************************************
1849 * WSAInstallServiceClassW (ws2_32.@)
1851 int WINAPI WSAInstallServiceClassW( WSASERVICECLASSINFOW *info )
1853 FIXME( "Request to install service %s\n", debugstr_w(info->lpszServiceClassName) );
1854 SetLastError( WSAEACCES );
1855 return -1;
1859 /***********************************************************************
1860 * WSARemoveServiceClass (ws2_32.@)
1862 int WINAPI WSARemoveServiceClass( GUID *info )
1864 FIXME( "Request to remove service %s\n", debugstr_guid(info) );
1865 SetLastError( WSATYPE_NOT_FOUND );
1866 return -1;
1870 /***********************************************************************
1871 * WSAGetServiceClassInfoA (ws2_32.@)
1873 int WINAPI WSAGetServiceClassInfoA( GUID *provider, GUID *service, DWORD *len,
1874 WSASERVICECLASSINFOA *info )
1876 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service), len, info );
1877 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1878 return -1;
1882 /***********************************************************************
1883 * WSAGetServiceClassInfoW (ws2_32.@)
1885 int WINAPI WSAGetServiceClassInfoW( GUID *provider, GUID *service, DWORD *len,
1886 WSASERVICECLASSINFOW *info )
1888 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service), len, info );
1889 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1890 return -1;
1894 /***********************************************************************
1895 * WSAGetServiceClassNameByClassIdA (ws2_32.@)
1897 int WINAPI WSAGetServiceClassNameByClassIdA( GUID *class, char *service, DWORD *len )
1899 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
1900 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1901 return -1;
1905 /***********************************************************************
1906 * WSAGetServiceClassNameByClassIdW (ws2_32.@)
1908 int WINAPI WSAGetServiceClassNameByClassIdW( GUID *class, WCHAR *service, DWORD *len )
1910 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
1911 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1912 return -1;
1916 /***********************************************************************
1917 * WSALookupServiceBeginA (ws2_32.@)
1919 int WINAPI WSALookupServiceBeginA( WSAQUERYSETA *query, DWORD flags, HANDLE *lookup )
1921 FIXME( "(%p 0x%08x %p) Stub!\n", query, flags, lookup );
1922 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1923 return -1;
1927 /***********************************************************************
1928 * WSALookupServiceBeginW (ws2_32.@)
1930 int WINAPI WSALookupServiceBeginW( WSAQUERYSETW *query, DWORD flags, HANDLE *lookup )
1932 FIXME( "(%p 0x%08x %p) Stub!\n", query, flags, lookup );
1933 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1934 return -1;
1938 /***********************************************************************
1939 * WSALookupServiceEnd (ws2_32.@)
1941 int WINAPI WSALookupServiceEnd( HANDLE lookup )
1943 FIXME("(%p) Stub!\n", lookup );
1944 return 0;
1948 /***********************************************************************
1949 * WSALookupServiceNextA (ws2_32.@)
1951 int WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, DWORD *len, WSAQUERYSETA *results )
1953 FIXME( "(%p 0x%08x %p %p) Stub!\n", lookup, flags, len, results );
1954 SetLastError( WSA_E_NO_MORE );
1955 return -1;
1959 /***********************************************************************
1960 * WSALookupServiceNextW (ws2_32.@)
1962 int WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, DWORD *len, WSAQUERYSETW *results )
1964 FIXME( "(%p 0x%08x %p %p) Stub!\n", lookup, flags, len, results );
1965 SetLastError( WSA_E_NO_MORE );
1966 return -1;
1970 /***********************************************************************
1971 * WSASetServiceA (ws2_32.@)
1973 int WINAPI WSASetServiceA( WSAQUERYSETA *query, WSAESETSERVICEOP operation, DWORD flags )
1975 FIXME( "(%p 0x%08x 0x%08x) Stub!\n", query, operation, flags );
1976 return 0;
1980 /***********************************************************************
1981 * WSASetServiceW (ws2_32.@)
1983 int WINAPI WSASetServiceW( WSAQUERYSETW *query, WSAESETSERVICEOP operation, DWORD flags )
1985 FIXME( "(%p 0x%08x 0x%08x) Stub!\n", query, operation, flags );
1986 return 0;
1990 /***********************************************************************
1991 * WSAEnumNameSpaceProvidersA (ws2_32.@)
1993 int WINAPI WSAEnumNameSpaceProvidersA( DWORD *len, WSANAMESPACE_INFOA *buffer )
1995 FIXME( "(%p %p) Stub!\n", len, buffer );
1996 return 0;
2000 /***********************************************************************
2001 * WSAEnumNameSpaceProvidersW (ws2_32.@)
2003 int WINAPI WSAEnumNameSpaceProvidersW( DWORD *len, WSANAMESPACE_INFOW *buffer )
2005 FIXME( "(%p %p) Stub!\n", len, buffer );
2006 return 0;
2010 /***********************************************************************
2011 * WSAProviderConfigChange (ws2_32.@)
2013 int WINAPI WSAProviderConfigChange( HANDLE *handle, OVERLAPPED *overlapped,
2014 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
2016 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
2017 return -1;
2021 /***********************************************************************
2022 * WSANSPIoctl (ws2_32.@)
2024 int WINAPI WSANSPIoctl( HANDLE lookup, DWORD code, void *in_buffer,
2025 DWORD in_size, void *out_buffer, DWORD out_size,
2026 DWORD *ret_size, WSACOMPLETION *completion )
2028 FIXME( "(%p, 0x%08x, %p, 0x%08x, %p, 0x%08x, %p, %p) Stub!\n", lookup, code,
2029 in_buffer, in_size, out_buffer, out_size, ret_size, completion );
2030 SetLastError( WSA_NOT_ENOUGH_MEMORY );
2031 return -1;
2035 /***********************************************************************
2036 * WSCEnableNSProvider (ws2_32.@)
2038 int WINAPI WSCEnableNSProvider( GUID *provider, BOOL enable )
2040 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
2041 return 0;
2045 /***********************************************************************
2046 * WSCGetProviderInfo (ws2_32.@)
2048 int WINAPI WSCGetProviderInfo( GUID *provider, WSC_PROVIDER_INFO_TYPE info_type,
2049 BYTE *info, size_t *len, DWORD flags, int *errcode )
2051 FIXME( "(%s 0x%08x %p %p 0x%08x %p) Stub!\n",
2052 debugstr_guid(provider), info_type, info, len, flags, errcode );
2054 if (!errcode)
2055 return -1;
2057 if (!provider)
2059 *errcode = WSAEFAULT;
2060 return -1;
2063 *errcode = WSANO_RECOVERY;
2064 return -1;
2068 /***********************************************************************
2069 * WSCGetProviderPath (ws2_32.@)
2071 int WINAPI WSCGetProviderPath( GUID *provider, WCHAR *path, int *len, int *errcode )
2073 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errcode );
2075 if (!provider || !len)
2077 if (errcode)
2078 *errcode = WSAEFAULT;
2079 return -1;
2082 if (*len <= 0)
2084 if (errcode)
2085 *errcode = WSAEINVAL;
2086 return -1;
2089 return 0;
2093 /***********************************************************************
2094 * WSCInstallNameSpace (ws2_32.@)
2096 int WINAPI WSCInstallNameSpace( WCHAR *identifier, WCHAR *path, DWORD namespace,
2097 DWORD version, GUID *provider )
2099 FIXME( "(%s %s 0x%08x 0x%08x %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
2100 namespace, version, debugstr_guid(provider) );
2101 return 0;
2105 /***********************************************************************
2106 * WSCUnInstallNameSpace (ws2_32.@)
2108 int WINAPI WSCUnInstallNameSpace( GUID *provider )
2110 FIXME( "(%s) Stub!\n", debugstr_guid(provider) );
2111 return NO_ERROR;
2115 /***********************************************************************
2116 * WSCWriteProviderOrder (ws2_32.@)
2118 int WINAPI WSCWriteProviderOrder( DWORD *entry, DWORD number )
2120 FIXME( "(%p 0x%08x) Stub!\n", entry, number );
2121 return 0;
2125 /***********************************************************************
2126 * WSCInstallProvider (ws2_32.@)
2128 int WINAPI WSCInstallProvider( GUID *provider, const WCHAR *path,
2129 WSAPROTOCOL_INFOW *protocol_info, DWORD count, int *err )
2131 FIXME( "(%s, %s, %p, %d, %p): stub !\n", debugstr_guid(provider),
2132 debugstr_w(path), protocol_info, count, err );
2133 *err = 0;
2134 return 0;
2138 /***********************************************************************
2139 * WSCDeinstallProvider (ws2_32.@)
2141 int WINAPI WSCDeinstallProvider( GUID *provider, int *err )
2143 FIXME( "(%s, %p): stub !\n", debugstr_guid(provider), err );
2144 *err = 0;
2145 return 0;
2149 /***********************************************************************
2150 * WSCSetApplicationCategory (ws2_32.@)
2152 int WINAPI WSCSetApplicationCategory( const WCHAR *path, DWORD len, const WCHAR *extra, DWORD extralen,
2153 DWORD lspcat, DWORD *prev_lspcat, int *err )
2155 FIXME( "(%s %d %s %d %d %p) Stub!\n", debugstr_w(path), len, debugstr_w(extra),
2156 extralen, lspcat, prev_lspcat );
2157 return 0;
2161 /***********************************************************************
2162 * WSCEnumProtocols (ws2_32.@)
2164 int WINAPI WSCEnumProtocols( int *protocols, WSAPROTOCOL_INFOW *info, DWORD *len, int *err )
2166 int ret = WSAEnumProtocolsW( protocols, info, len );
2168 if (ret == SOCKET_ERROR) *err = WSAENOBUFS;
2170 return ret;