sapi: Add SpMMAudioOut stub.
[wine.git] / dlls / ws2_32 / protocol.c
blobf746257a4fc1c70d030a8368cda21a1b0f3e7fc1
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 #define WS_CALL(func, params) WINE_UNIX_CALL( ws_unix_ ## func, params )
32 static char *get_fqdn(void)
34 char *ret;
35 DWORD size = 0;
37 GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, NULL, &size );
38 if (GetLastError() != ERROR_MORE_DATA) return NULL;
39 if (!(ret = malloc( size ))) return NULL;
40 if (!GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, ret, &size ))
42 free( ret );
43 return NULL;
45 return ret;
48 /* call Unix getaddrinfo, allocating a large enough buffer */
49 static int do_getaddrinfo( const char *node, const char *service,
50 const struct addrinfo *hints, struct addrinfo **info )
52 unsigned int size = 1024;
53 struct getaddrinfo_params params = { node, service, hints, NULL, &size };
54 int ret;
56 for (;;)
58 if (!(params.info = malloc( size )))
59 return WSA_NOT_ENOUGH_MEMORY;
60 if (!(ret = WS_CALL( getaddrinfo, &params )))
62 *info = params.info;
63 return ret;
65 free( params.info );
66 if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
70 static int dns_only_query( const char *node, const struct addrinfo *hints, struct addrinfo **result )
72 DNS_STATUS status;
73 DNS_RECORDA *rec = NULL, *rec6 = NULL, *ptr;
74 struct addrinfo *info, *next;
75 struct sockaddr_in *addr;
76 struct sockaddr_in6 *addr6;
77 ULONG count = 0;
79 if (hints->ai_family != AF_INET && hints->ai_family != AF_INET6 && hints->ai_family != AF_UNSPEC)
81 FIXME( "unsupported family %u\n", hints->ai_family );
82 return EAI_FAMILY;
84 if (hints->ai_family == AF_INET || hints->ai_family == AF_UNSPEC)
86 status = DnsQuery_A( node, DNS_TYPE_A, DNS_QUERY_NO_NETBT | DNS_QUERY_NO_MULTICAST, NULL, &rec, NULL );
87 if (status != ERROR_SUCCESS && status != DNS_ERROR_RCODE_NAME_ERROR) return EAI_FAIL;
89 if (hints->ai_family == AF_INET6 || hints->ai_family == AF_UNSPEC)
91 status = DnsQuery_A( node, DNS_TYPE_AAAA, DNS_QUERY_NO_NETBT | DNS_QUERY_NO_MULTICAST, NULL, &rec6, NULL );
92 if (status != ERROR_SUCCESS && status != DNS_ERROR_RCODE_NAME_ERROR)
94 DnsRecordListFree( (DNS_RECORD *)rec, DnsFreeRecordList );
95 return EAI_FAIL;
99 for (ptr = rec; ptr; ptr = ptr->pNext) { if (ptr->wType == DNS_TYPE_A) count++; };
100 for (ptr = rec6; ptr; ptr = ptr->pNext) { if (ptr->wType == DNS_TYPE_AAAA) count++; };
101 if (!count)
103 DnsRecordListFree( (DNS_RECORD *)rec, DnsFreeRecordList );
104 DnsRecordListFree( (DNS_RECORD *)rec6, DnsFreeRecordList );
105 return WSAHOST_NOT_FOUND;
107 if (!(info = calloc( count, sizeof(*info) + sizeof(SOCKADDR_STORAGE) )))
109 DnsRecordListFree( (DNS_RECORD *)rec, DnsFreeRecordList );
110 DnsRecordListFree( (DNS_RECORD *)rec6, DnsFreeRecordList );
111 return WSA_NOT_ENOUGH_MEMORY;
113 *result = info;
115 for (ptr = rec; ptr; ptr = ptr->pNext)
117 if (ptr->wType != DNS_TYPE_A) continue;
118 info->ai_family = AF_INET;
119 info->ai_socktype = hints->ai_socktype;
120 info->ai_protocol = hints->ai_protocol;
121 info->ai_addrlen = sizeof(struct sockaddr_in);
122 info->ai_addr = (struct sockaddr *)(info + 1);
123 addr = (struct sockaddr_in *)info->ai_addr;
124 addr->sin_family = info->ai_family;
125 addr->sin_addr.S_un.S_addr = ptr->Data.A.IpAddress;
126 next = (struct addrinfo *)((char *)info + sizeof(*info) + sizeof(SOCKADDR_STORAGE));
127 if (--count) info->ai_next = next;
128 info = next;
130 for (ptr = rec6; ptr; ptr = ptr->pNext)
132 if (ptr->wType != DNS_TYPE_AAAA) continue;
133 info->ai_family = AF_INET6;
134 info->ai_socktype = hints->ai_socktype;
135 info->ai_protocol = hints->ai_protocol;
136 info->ai_addrlen = sizeof(struct sockaddr_in6);
137 info->ai_addr = (struct sockaddr *)(info + 1);
138 addr6 = (struct sockaddr_in6 *)info->ai_addr;
139 addr6->sin6_family = info->ai_family;
140 memcpy( &addr6->sin6_addr, &ptr->Data.AAAA.Ip6Address, sizeof(addr6->sin6_addr) );
141 next = (struct addrinfo *)((char *)info + sizeof(*info) + sizeof(SOCKADDR_STORAGE));
142 if (--count) info->ai_next = next;
143 info = next;
146 DnsRecordListFree( (DNS_RECORD *)rec, DnsFreeRecordList );
147 DnsRecordListFree( (DNS_RECORD *)rec6, DnsFreeRecordList );
148 return 0;
151 /***********************************************************************
152 * getaddrinfo (ws2_32.@)
154 int WINAPI getaddrinfo( const char *node, const char *service,
155 const struct addrinfo *hints, struct addrinfo **info )
157 char *nodev6 = NULL, *fqdn = NULL;
158 int ret;
160 TRACE( "node %s, service %s, hints %p\n", debugstr_a(node), debugstr_a(service), hints );
162 *info = NULL;
164 if (!node && !service)
166 SetLastError( WSAHOST_NOT_FOUND );
167 return WSAHOST_NOT_FOUND;
170 if (node)
172 if (!node[0])
174 if (!(fqdn = get_fqdn())) return WSA_NOT_ENOUGH_MEMORY;
175 node = fqdn;
177 else if (!service && hints && (hints->ai_flags == AI_DNS_ONLY || hints->ai_flags == (AI_ALL | AI_DNS_ONLY)))
179 ret = dns_only_query( node, hints, info );
180 goto done;
182 else if (!hints || hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET6)
184 /* [ipv6] or [ipv6]:portnumber are supported by Windows */
185 char *close_bracket;
187 if (node[0] == '[' && (close_bracket = strchr(node + 1, ']')))
189 if (!(nodev6 = malloc( close_bracket - node )))
190 return WSA_NOT_ENOUGH_MEMORY;
191 lstrcpynA( nodev6, node + 1, close_bracket - node );
192 node = nodev6;
197 ret = do_getaddrinfo( node, service, hints, info );
199 if (ret && (!hints || !(hints->ai_flags & AI_NUMERICHOST)) && node)
201 if (!fqdn && !(fqdn = get_fqdn()))
203 free( nodev6 );
204 return WSA_NOT_ENOUGH_MEMORY;
206 if (!strcmp( fqdn, node ) || (!strncmp( fqdn, node, strlen( node ) ) && fqdn[strlen( node )] == '.'))
208 /* If it didn't work it means the host name IP is not in /etc/hosts, try again
209 * by sending a NULL host and avoid sending a NULL servname too because that
210 * is invalid */
211 ERR_(winediag)( "Failed to resolve your host name IP\n" );
212 ret = do_getaddrinfo( NULL, service, hints, info );
213 if (!ret && hints && (hints->ai_flags & AI_CANONNAME) && *info && !(*info)->ai_canonname)
215 freeaddrinfo( *info );
216 *info = NULL;
217 return EAI_NONAME;
222 free( fqdn );
223 free( nodev6 );
225 done:
226 if (!ret && TRACE_ON(winsock))
228 struct addrinfo *ai;
230 for (ai = *info; ai != NULL; ai = ai->ai_next)
232 TRACE( "=> %p, flags %#x, family %d, type %d, protocol %d, len %Id, name %s, addr %s\n",
233 ai, ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol, ai->ai_addrlen,
234 ai->ai_canonname, debugstr_sockaddr(ai->ai_addr) );
238 SetLastError( ret );
239 return ret;
243 static ADDRINFOEXW *addrinfo_AtoW( const struct addrinfo *ai )
245 ADDRINFOEXW *ret;
247 if (!(ret = malloc( sizeof(ADDRINFOEXW) ))) return NULL;
248 ret->ai_flags = ai->ai_flags;
249 ret->ai_family = ai->ai_family;
250 ret->ai_socktype = ai->ai_socktype;
251 ret->ai_protocol = ai->ai_protocol;
252 ret->ai_addrlen = ai->ai_addrlen;
253 ret->ai_canonname = NULL;
254 ret->ai_addr = NULL;
255 ret->ai_blob = NULL;
256 ret->ai_bloblen = 0;
257 ret->ai_provider = NULL;
258 ret->ai_next = NULL;
259 if (ai->ai_canonname)
261 int len = MultiByteToWideChar( CP_ACP, 0, ai->ai_canonname, -1, NULL, 0 );
262 if (!(ret->ai_canonname = malloc( len * sizeof(WCHAR) )))
264 free( ret );
265 return NULL;
267 MultiByteToWideChar( CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len );
269 if (ai->ai_addr)
271 if (!(ret->ai_addr = malloc( ai->ai_addrlen )))
273 free( ret->ai_canonname );
274 free( ret );
275 return NULL;
277 memcpy( ret->ai_addr, ai->ai_addr, ai->ai_addrlen );
279 return ret;
282 static ADDRINFOEXW *addrinfo_list_AtoW( const struct addrinfo *info )
284 ADDRINFOEXW *ret, *infoW;
286 if (!(ret = infoW = addrinfo_AtoW( info ))) return NULL;
287 while (info->ai_next)
289 if (!(infoW->ai_next = addrinfo_AtoW( info->ai_next )))
291 FreeAddrInfoExW( ret );
292 return NULL;
294 infoW = infoW->ai_next;
295 info = info->ai_next;
297 return ret;
300 static struct addrinfo *addrinfo_WtoA( const struct addrinfoW *ai )
302 struct addrinfo *ret;
304 if (!(ret = malloc( sizeof(struct addrinfo) ))) return NULL;
305 ret->ai_flags = ai->ai_flags;
306 ret->ai_family = ai->ai_family;
307 ret->ai_socktype = ai->ai_socktype;
308 ret->ai_protocol = ai->ai_protocol;
309 ret->ai_addrlen = ai->ai_addrlen;
310 ret->ai_canonname = NULL;
311 ret->ai_addr = NULL;
312 ret->ai_next = NULL;
313 if (ai->ai_canonname)
315 int len = WideCharToMultiByte( CP_ACP, 0, ai->ai_canonname, -1, NULL, 0, NULL, NULL );
316 if (!(ret->ai_canonname = malloc( len )))
318 free( ret );
319 return NULL;
321 WideCharToMultiByte( CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len, NULL, NULL );
323 if (ai->ai_addr)
325 if (!(ret->ai_addr = malloc( sizeof(struct sockaddr) )))
327 free( ret->ai_canonname );
328 free( ret );
329 return NULL;
331 memcpy( ret->ai_addr, ai->ai_addr, sizeof(struct sockaddr) );
333 return ret;
336 struct getaddrinfo_args
338 OVERLAPPED *overlapped;
339 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine;
340 ADDRINFOEXW **result;
341 char *nodename;
342 char *servname;
343 struct addrinfo *hints;
346 static void WINAPI getaddrinfo_callback(TP_CALLBACK_INSTANCE *instance, void *context)
348 struct getaddrinfo_args *args = context;
349 OVERLAPPED *overlapped = args->overlapped;
350 HANDLE event = overlapped->hEvent;
351 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine = args->completion_routine;
352 struct addrinfo *res;
353 int ret;
355 ret = getaddrinfo( args->nodename, args->servname, args->hints, &res );
356 if (res)
358 *args->result = addrinfo_list_AtoW(res);
359 overlapped->u.Pointer = args->result;
360 freeaddrinfo(res);
363 free( args->nodename );
364 free( args->servname );
365 free( args );
367 overlapped->Internal = ret;
368 if (completion_routine) completion_routine( ret, 0, overlapped );
369 if (event) SetEvent( event );
372 static int getaddrinfoW( const WCHAR *nodename, const WCHAR *servname,
373 const struct addrinfo *hints, ADDRINFOEXW **res, OVERLAPPED *overlapped,
374 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine )
376 int ret = EAI_MEMORY, len, i;
377 char *nodenameA = NULL, *servnameA = NULL;
378 struct addrinfo *resA;
379 WCHAR *local_nodenameW = (WCHAR *)nodename;
381 *res = NULL;
382 if (nodename)
384 /* Is this an IDN? Most likely if any char is above the Ascii table, this
385 * is the simplest validation possible, further validation will be done by
386 * the native getaddrinfo() */
387 for (i = 0; nodename[i]; i++)
389 if (nodename[i] > 'z')
390 break;
392 if (nodename[i])
394 if (hints && (hints->ai_flags & AI_DISABLE_IDN_ENCODING))
396 /* Name requires conversion but it was disabled */
397 ret = WSAHOST_NOT_FOUND;
398 SetLastError( ret );
399 goto end;
402 len = IdnToAscii( 0, nodename, -1, NULL, 0 );
403 if (!len)
405 ERR("Failed to convert %s to punycode\n", debugstr_w(nodename));
406 ret = EAI_FAIL;
407 goto end;
409 if (!(local_nodenameW = malloc( len * sizeof(WCHAR) ))) goto end;
410 IdnToAscii( 0, nodename, -1, local_nodenameW, len );
413 if (local_nodenameW)
415 len = WideCharToMultiByte( CP_ACP, 0, local_nodenameW, -1, NULL, 0, NULL, NULL );
416 if (!(nodenameA = malloc( len ))) goto end;
417 WideCharToMultiByte( CP_ACP, 0, local_nodenameW, -1, nodenameA, len, NULL, NULL );
419 if (servname)
421 len = WideCharToMultiByte( CP_ACP, 0, servname, -1, NULL, 0, NULL, NULL );
422 if (!(servnameA = malloc( len ))) goto end;
423 WideCharToMultiByte( CP_ACP, 0, servname, -1, servnameA, len, NULL, NULL );
426 if (overlapped)
428 struct getaddrinfo_args *args;
430 if (overlapped->hEvent && completion_routine)
432 ret = WSAEINVAL;
433 goto end;
436 if (!(args = malloc( sizeof(*args) + sizeof(*args->hints) ))) goto end;
437 args->overlapped = overlapped;
438 args->completion_routine = completion_routine;
439 args->result = res;
440 args->nodename = nodenameA;
441 args->servname = servnameA;
442 if (hints)
444 args->hints = (struct addrinfo *)(args + 1);
445 args->hints->ai_flags = hints->ai_flags;
446 args->hints->ai_family = hints->ai_family;
447 args->hints->ai_socktype = hints->ai_socktype;
448 args->hints->ai_protocol = hints->ai_protocol;
450 else args->hints = NULL;
452 overlapped->Internal = WSAEINPROGRESS;
453 if (!TrySubmitThreadpoolCallback( getaddrinfo_callback, args, NULL ))
455 free( args );
456 ret = GetLastError();
457 goto end;
460 if (local_nodenameW != nodename)
461 free( local_nodenameW );
462 SetLastError( ERROR_IO_PENDING );
463 return ERROR_IO_PENDING;
466 ret = getaddrinfo( nodenameA, servnameA, hints, &resA );
467 if (!ret)
469 *res = addrinfo_list_AtoW( resA );
470 freeaddrinfo( resA );
473 end:
474 if (local_nodenameW != nodename)
475 free( local_nodenameW );
476 free( nodenameA );
477 free( servnameA );
478 return ret;
482 /***********************************************************************
483 * GetAddrInfoExW (ws2_32.@)
485 int WINAPI GetAddrInfoExW( const WCHAR *name, const WCHAR *servname, DWORD namespace,
486 GUID *namespace_id, const ADDRINFOEXW *hints, ADDRINFOEXW **result,
487 struct timeval *timeout, OVERLAPPED *overlapped,
488 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine, HANDLE *handle )
490 int ret;
492 TRACE( "name %s, servname %s, namespace %lu, namespace_id %s)\n",
493 debugstr_w(name), debugstr_w(servname), namespace, debugstr_guid(namespace_id) );
495 if (namespace != NS_DNS)
496 FIXME( "Unsupported namespace %lu\n", namespace );
497 if (namespace_id)
498 FIXME( "Unsupported namespace_id %s\n", debugstr_guid(namespace_id) );
499 if (timeout)
500 FIXME( "Unsupported timeout\n" );
501 if (handle)
502 FIXME( "Unsupported cancel handle\n" );
504 ret = getaddrinfoW( name, servname, (struct addrinfo *)hints, result, overlapped, completion_routine );
505 if (ret) return ret;
506 if (handle) *handle = (HANDLE)0xdeadbeef;
507 return 0;
511 /***********************************************************************
512 * GetAddrInfoExOverlappedResult (ws2_32.@)
514 int WINAPI GetAddrInfoExOverlappedResult( OVERLAPPED *overlapped )
516 TRACE( "(%p)\n", overlapped );
518 if (!overlapped)
519 return WSAEINVAL;
521 return overlapped->Internal;
525 /***********************************************************************
526 * GetAddrInfoExCancel (ws2_32.@)
528 int WINAPI GetAddrInfoExCancel( HANDLE *handle )
530 FIXME( "(%p)\n", handle );
531 return WSA_INVALID_HANDLE;
535 /***********************************************************************
536 * GetAddrInfoW (ws2_32.@)
538 int WINAPI GetAddrInfoW(const WCHAR *nodename, const WCHAR *servname, const ADDRINFOW *hints, ADDRINFOW **res)
540 struct addrinfo *hintsA = NULL;
541 ADDRINFOEXW *resex;
542 int ret = EAI_MEMORY;
544 TRACE( "nodename %s, servname %s, hints %p, result %p\n",
545 debugstr_w(nodename), debugstr_w(servname), hints, res );
547 *res = NULL;
548 if (hints) hintsA = addrinfo_WtoA( hints );
549 ret = getaddrinfoW( nodename, servname, hintsA, &resex, NULL, NULL );
550 freeaddrinfo( hintsA );
551 if (ret) return ret;
553 if (resex)
555 /* ADDRINFOEXW has a layout compatible with ADDRINFOW except for the
556 * ai_next field, so we may convert it in place */
557 *res = (ADDRINFOW *)resex;
560 ((ADDRINFOW *)resex)->ai_next = (ADDRINFOW *)resex->ai_next;
561 resex = resex->ai_next;
562 } while (resex);
564 return 0;
568 /***********************************************************************
569 * freeaddrinfo (ws2_32.@)
571 void WINAPI freeaddrinfo( struct addrinfo *info )
573 TRACE( "%p\n", info );
575 free( info );
579 /***********************************************************************
580 * FreeAddrInfoW (ws2_32.@)
582 void WINAPI FreeAddrInfoW( ADDRINFOW *ai )
584 while (ai)
586 ADDRINFOW *next;
587 free( ai->ai_canonname );
588 free( ai->ai_addr );
589 next = ai->ai_next;
590 free( ai );
591 ai = next;
596 /***********************************************************************
597 * FreeAddrInfoEx (ws2_32.@)
599 void WINAPI FreeAddrInfoEx( ADDRINFOEXA *ai )
601 TRACE( "(%p)\n", ai );
603 while (ai)
605 ADDRINFOEXA *next;
606 free( ai->ai_canonname );
607 free( ai->ai_addr );
608 next = ai->ai_next;
609 free( ai );
610 ai = next;
615 /***********************************************************************
616 * FreeAddrInfoExW (ws2_32.@)
618 void WINAPI FreeAddrInfoExW( ADDRINFOEXW *ai )
620 TRACE( "(%p)\n", ai );
622 while (ai)
624 ADDRINFOEXW *next;
625 free( ai->ai_canonname );
626 free( ai->ai_addr );
627 next = ai->ai_next;
628 free( ai );
629 ai = next;
634 /***********************************************************************
635 * getnameinfo (ws2_32.@)
637 int WINAPI getnameinfo( const SOCKADDR *addr, socklen_t addr_len, char *host,
638 DWORD host_len, char *serv, DWORD serv_len, int flags )
640 struct getnameinfo_params params = { addr, addr_len, host, host_len, serv, serv_len, flags };
642 TRACE( "addr %s, addr_len %d, host %p, host_len %lu, serv %p, serv_len %lu, flags %#x\n",
643 debugstr_sockaddr(addr), addr_len, host, host_len, serv, serv_len, flags );
645 return WS_CALL( getnameinfo, &params );
649 /***********************************************************************
650 * GetNameInfoW (ws2_32.@)
652 int WINAPI GetNameInfoW( const SOCKADDR *addr, socklen_t addr_len, WCHAR *host,
653 DWORD host_len, WCHAR *serv, DWORD serv_len, int flags )
655 int ret;
656 char *hostA = NULL, *servA = NULL;
658 if (host && !(hostA = malloc( host_len )))
659 return EAI_MEMORY;
660 if (serv && !(servA = malloc( serv_len )))
662 free( hostA );
663 return EAI_MEMORY;
666 ret = getnameinfo( addr, addr_len, hostA, host_len, servA, serv_len, flags );
667 if (!ret)
669 if (host) MultiByteToWideChar( CP_ACP, 0, hostA, -1, host, host_len );
670 if (serv) MultiByteToWideChar( CP_ACP, 0, servA, -1, serv, serv_len );
673 free( hostA );
674 free( servA );
675 return ret;
679 static struct hostent *get_hostent_buffer( unsigned int size )
681 struct per_thread_data *data = get_per_thread_data();
682 struct hostent *new_buffer;
684 if (data->he_len < size)
686 if (!(new_buffer = realloc( data->he_buffer, size )))
688 SetLastError( WSAENOBUFS );
689 return NULL;
691 data->he_buffer = new_buffer;
692 data->he_len = size;
694 return data->he_buffer;
697 /* create a hostent entry
699 * Creates the entry with enough memory for the name, aliases
700 * addresses, and the address pointers. Also copies the name
701 * and sets up all the pointers.
703 * NOTE: The alias and address lists must be allocated with room
704 * for the NULL item terminating the list. This is true even if
705 * the list has no items ("aliases" and "addresses" must be
706 * at least "1", a truly empty list is invalid).
708 static struct hostent *create_hostent( char *name, int alias_count, int aliases_size,
709 int address_count, int address_length )
711 struct hostent *p_to;
712 char *p;
713 unsigned int size = sizeof(struct hostent), i;
715 size += strlen(name) + 1;
716 size += alias_count * sizeof(char *);
717 size += aliases_size;
718 size += address_count * sizeof(char *);
719 size += (address_count - 1) * address_length;
721 if (!(p_to = get_hostent_buffer( size ))) return NULL;
722 memset( p_to, 0, size );
724 /* Use the memory in the same way winsock does.
725 * First set the pointer for aliases, second set the pointers for addresses.
726 * Third fill the addresses indexes, fourth jump aliases names size.
727 * Fifth fill the hostname.
728 * NOTE: This method is valid for OS versions >= XP.
730 p = (char *)(p_to + 1);
731 p_to->h_aliases = (char **)p;
732 p += alias_count * sizeof(char *);
734 p_to->h_addr_list = (char **)p;
735 p += address_count * sizeof(char *);
737 for (i = 0, address_count--; i < address_count; i++, p += address_length)
738 p_to->h_addr_list[i] = p;
740 /* h_aliases must be filled in manually because we don't know each string
741 * size. Leave these pointers NULL (already set to NULL by memset earlier).
743 p += aliases_size;
745 p_to->h_name = p;
746 strcpy( p, name );
748 return p_to;
752 /***********************************************************************
753 * gethostbyaddr (ws2_32.51)
755 struct hostent * WINAPI gethostbyaddr( const char *addr, int len, int family )
757 unsigned int size = 1024;
758 struct gethostbyaddr_params params = { addr, len, family, NULL, &size };
759 int ret;
761 for (;;)
763 if (!(params.host = get_hostent_buffer( size )))
764 return NULL;
766 if ((ret = WS_CALL( gethostbyaddr, &params )) != ERROR_INSUFFICIENT_BUFFER)
767 break;
770 SetLastError( ret );
771 return ret ? NULL : params.host;
775 struct route
777 struct in_addr addr;
778 IF_INDEX interface;
779 DWORD metric, default_route;
782 static int __cdecl compare_routes_by_metric_asc( const void *left, const void *right )
784 const struct route *a = left, *b = right;
785 if (a->default_route && b->default_route)
786 return a->default_route - b->default_route;
787 if (a->default_route && !b->default_route)
788 return -1;
789 if (b->default_route && !a->default_route)
790 return 1;
791 return a->metric - b->metric;
794 /* Returns the list of local IP addresses by going through the network
795 * adapters and using the local routing table to sort the addresses
796 * from highest routing priority to lowest routing priority. This
797 * functionality is inferred from the description for obtaining local
798 * IP addresses given in the Knowledge Base Article Q160215.
800 * Please note that the returned hostent is only freed when the thread
801 * closes and is replaced if another hostent is requested.
803 static struct hostent *get_local_ips( char *hostname )
805 int numroutes = 0, i, j, default_routes = 0;
806 IP_ADAPTER_INFO *adapters = NULL, *k;
807 struct hostent *hostlist = NULL;
808 MIB_IPFORWARDTABLE *routes = NULL;
809 struct route *route_addrs = NULL, *new_route_addrs;
810 DWORD adap_size, route_size, n;
812 /* Obtain the size of the adapter list and routing table, also allocate memory */
813 if (GetAdaptersInfo( NULL, &adap_size ) != ERROR_BUFFER_OVERFLOW)
814 return NULL;
815 if (GetIpForwardTable( NULL, &route_size, FALSE ) != ERROR_INSUFFICIENT_BUFFER)
816 return NULL;
818 adapters = malloc( adap_size );
819 routes = malloc( route_size );
820 if (!adapters || !routes)
821 goto cleanup;
823 /* Obtain the adapter list and the full routing table */
824 if (GetAdaptersInfo( adapters, &adap_size ) != NO_ERROR)
825 goto cleanup;
826 if (GetIpForwardTable( routes, &route_size, FALSE ) != NO_ERROR)
827 goto cleanup;
829 /* Store the interface associated with each route */
830 for (n = 0; n < routes->dwNumEntries; n++)
832 IF_INDEX ifindex;
833 DWORD ifmetric, ifdefault = 0;
834 BOOL exists = FALSE;
836 /* Check if this is a default route (there may be more than one) */
837 if (!routes->table[n].dwForwardDest)
838 ifdefault = ++default_routes;
839 else if (routes->table[n].u1.ForwardType != MIB_IPROUTE_TYPE_DIRECT)
840 continue;
841 ifindex = routes->table[n].dwForwardIfIndex;
842 ifmetric = routes->table[n].dwForwardMetric1;
843 /* Only store the lowest valued metric for an interface */
844 for (j = 0; j < numroutes; j++)
846 if (route_addrs[j].interface == ifindex)
848 if (route_addrs[j].metric > ifmetric)
849 route_addrs[j].metric = ifmetric;
850 exists = TRUE;
853 if (exists)
854 continue;
855 new_route_addrs = realloc( route_addrs, (numroutes + 1) * sizeof(struct route) );
856 if (!new_route_addrs)
857 goto cleanup;
858 route_addrs = new_route_addrs;
859 route_addrs[numroutes].interface = ifindex;
860 route_addrs[numroutes].metric = ifmetric;
861 route_addrs[numroutes].default_route = ifdefault;
862 /* If no IP is found in the next step (for whatever reason)
863 * then fall back to the magic loopback address.
865 memcpy( &route_addrs[numroutes].addr.s_addr, magic_loopback_addr, 4 );
866 numroutes++;
868 if (numroutes == 0)
869 goto cleanup; /* No routes, fall back to the Magic IP */
871 /* Find the IP address associated with each found interface */
872 for (i = 0; i < numroutes; i++)
874 for (k = adapters; k != NULL; k = k->Next)
876 char *ip = k->IpAddressList.IpAddress.String;
878 if (route_addrs[i].interface == k->Index)
879 route_addrs[i].addr.s_addr = inet_addr(ip);
883 /* Allocate a hostent and enough memory for all the IPs,
884 * including the NULL at the end of the list.
886 hostlist = create_hostent( hostname, 1, 0, numroutes+1, sizeof(struct in_addr) );
887 if (hostlist == NULL)
888 goto cleanup;
889 hostlist->h_addr_list[numroutes] = NULL;
890 hostlist->h_aliases[0] = NULL;
891 hostlist->h_addrtype = AF_INET;
892 hostlist->h_length = sizeof(struct in_addr);
894 /* Reorder the entries before placing them in the host list. Windows expects
895 * the IP list in order from highest priority to lowest (the critical thing
896 * is that most applications expect the first IP to be the default route).
898 if (numroutes > 1)
899 qsort( route_addrs, numroutes, sizeof(struct route), compare_routes_by_metric_asc );
901 for (i = 0; i < numroutes; i++)
902 *(struct in_addr *)hostlist->h_addr_list[i] = route_addrs[i].addr;
904 cleanup:
905 free( route_addrs );
906 free( adapters );
907 free( routes );
908 return hostlist;
912 /***********************************************************************
913 * gethostbyname (ws2_32.52)
915 struct hostent * WINAPI gethostbyname( const char *name )
917 struct hostent *host = NULL;
918 char hostname[100];
919 struct gethostname_params params = { hostname, sizeof(hostname) };
920 int ret;
922 TRACE( "%s\n", debugstr_a(name) );
924 if (!num_startup)
926 SetLastError( WSANOTINITIALISED );
927 return NULL;
930 if ((ret = WS_CALL( gethostname, &params )))
932 SetLastError( ret );
933 return NULL;
936 if (!name || !name[0])
937 name = hostname;
939 /* If the hostname of the local machine is requested then return the
940 * complete list of local IP addresses */
941 if (!strcmp( name, hostname ))
942 host = get_local_ips( hostname );
944 /* If any other hostname was requested (or the routing table lookup failed)
945 * then return the IP found by the host OS */
946 if (!host)
948 unsigned int size = 1024;
949 struct gethostbyname_params params = { name, NULL, &size };
950 int ret;
952 for (;;)
954 if (!(params.host = get_hostent_buffer( size )))
955 return NULL;
957 if ((ret = WS_CALL( gethostbyname, &params )) != ERROR_INSUFFICIENT_BUFFER)
958 break;
961 SetLastError( ret );
962 return ret ? NULL : params.host;
965 if (host && host->h_addr_list[0][0] == 127 && strcmp( name, "localhost" ))
967 /* hostname != "localhost" but has loopback address. replace by our
968 * special address.*/
969 memcpy( host->h_addr_list[0], magic_loopback_addr, 4 );
972 return host;
976 /***********************************************************************
977 * gethostname (ws2_32.57)
979 int WINAPI gethostname( char *name, int namelen )
981 char buf[256];
982 struct gethostname_params params = { buf, sizeof(buf) };
983 int len, ret;
985 TRACE( "name %p, len %d\n", name, namelen );
987 if (!name)
989 SetLastError( WSAEFAULT );
990 return -1;
993 if ((ret = WS_CALL( gethostname, &params )))
995 SetLastError( ret );
996 return -1;
999 TRACE( "<- %s\n", debugstr_a(buf) );
1000 len = strlen( buf );
1001 if (len > 15)
1002 WARN( "Windows supports NetBIOS name length up to 15 bytes!\n" );
1003 if (namelen <= len)
1005 SetLastError( WSAEFAULT );
1006 return -1;
1008 strcpy( name, buf );
1009 return 0;
1013 /***********************************************************************
1014 * GetHostNameW (ws2_32.@)
1016 int WINAPI GetHostNameW( WCHAR *name, int namelen )
1018 char buf[256];
1019 struct gethostname_params params = { buf, sizeof(buf) };
1020 int ret;
1022 TRACE( "name %p, len %d\n", name, namelen );
1024 if (!name)
1026 SetLastError( WSAEFAULT );
1027 return -1;
1030 if ((ret = WS_CALL( gethostname, &params )))
1032 SetLastError( ret );
1033 return -1;
1036 if (MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 ) > namelen)
1038 SetLastError( WSAEFAULT );
1039 return -1;
1041 MultiByteToWideChar( CP_ACP, 0, buf, -1, name, namelen );
1042 return 0;
1046 static char *read_etc_file( const WCHAR *filename, DWORD *ret_size )
1048 WCHAR path[MAX_PATH];
1049 DWORD size = sizeof(path);
1050 HANDLE file;
1051 char *data;
1052 LONG ret;
1054 if ((ret = RegGetValueW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\tcpip\\Parameters",
1055 L"DatabasePath", RRF_RT_REG_SZ, NULL, path, &size )))
1057 ERR( "failed to get database path, error %lu\n", ret );
1058 return NULL;
1060 wcscat( path, L"\\" );
1061 wcscat( path, filename );
1063 file = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
1064 if (file == INVALID_HANDLE_VALUE)
1066 ERR( "failed to open %s, error %lu\n", debugstr_w( path ), GetLastError() );
1067 return NULL;
1070 size = GetFileSize( file, NULL );
1071 if (!(data = malloc( size )) || !ReadFile( file, data, size, ret_size, NULL ))
1073 WARN( "failed to read file, error %lu\n", GetLastError() );
1074 free( data );
1075 data = NULL;
1077 CloseHandle( file );
1078 return data;
1081 /* returns "end" if there was no space */
1082 static char *next_space( const char *p, const char *end )
1084 while (p < end && !isspace( *p ))
1085 ++p;
1086 return (char *)p;
1089 /* returns "end" if there was no non-space */
1090 static char *next_non_space( const char *p, const char *end )
1092 while (p < end && isspace( *p ))
1093 ++p;
1094 return (char *)p;
1098 static struct protoent *get_protoent_buffer( unsigned int size )
1100 struct per_thread_data *data = get_per_thread_data();
1101 struct protoent *new_buffer;
1103 if (data->pe_len < size)
1105 if (!(new_buffer = realloc( data->pe_buffer, size )))
1107 SetLastError( WSAENOBUFS );
1108 return NULL;
1110 data->pe_buffer = new_buffer;
1111 data->pe_len = size;
1113 return data->pe_buffer;
1116 /* Parse the first valid line into a protoent structure, returning NULL if
1117 * there is no valid line. Updates cursor to point to the start of the next
1118 * line or the end of the file. */
1119 static struct protoent *get_next_protocol( const char **cursor, const char *end )
1121 const char *p = *cursor;
1123 while (p < end)
1125 const char *line_end, *next_line;
1126 size_t needed_size, line_len;
1127 unsigned int alias_count = 0;
1128 struct protoent *proto;
1129 const char *name;
1130 int number;
1131 char *q;
1133 for (line_end = p; line_end < end && *line_end != '\n' && *line_end != '#'; ++line_end)
1135 TRACE( "parsing line %s\n", debugstr_an(p, line_end - p) );
1137 for (next_line = line_end; next_line < end && *next_line != '\n'; ++next_line)
1139 if (next_line < end)
1140 ++next_line; /* skip over the newline */
1142 p = next_non_space( p, line_end );
1143 if (p == line_end)
1145 p = next_line;
1146 continue;
1149 /* parse the name */
1151 name = p;
1152 line_len = line_end - name;
1154 p = next_space( p, line_end );
1155 if (p == line_end)
1157 p = next_line;
1158 continue;
1161 p = next_non_space( p, line_end );
1163 /* parse the number */
1165 number = atoi( p );
1167 p = next_space( p, line_end );
1168 p = next_non_space( p, line_end );
1170 /* we will copy the entire line after the protoent structure, then
1171 * replace spaces with null bytes as necessary */
1173 while (p < line_end)
1175 ++alias_count;
1177 p = next_space( p, line_end );
1178 p = next_non_space( p, line_end );
1180 needed_size = sizeof(*proto) + line_len + 1 + (alias_count + 1) * sizeof(char *);
1182 if (!(proto = get_protoent_buffer( needed_size )))
1184 SetLastError( WSAENOBUFS );
1185 return NULL;
1188 proto->p_proto = number;
1189 proto->p_aliases = (char **)(proto + 1);
1190 proto->p_name = (char *)(proto->p_aliases + alias_count + 1);
1192 memcpy( proto->p_name, name, line_len );
1193 proto->p_name[line_len] = 0;
1195 line_end = proto->p_name + line_len;
1197 q = proto->p_name;
1198 q = next_space( q, line_end );
1199 *q++ = 0;
1200 q = next_non_space( q, line_end );
1201 /* skip over the number */
1202 q = next_space( q, line_end );
1203 q = next_non_space( q, line_end );
1205 alias_count = 0;
1206 while (q < line_end)
1208 proto->p_aliases[alias_count++] = q;
1209 q = next_space( q, line_end );
1210 if (q < line_end) *q++ = 0;
1211 q = next_non_space( q, line_end );
1213 proto->p_aliases[alias_count] = NULL;
1215 *cursor = next_line;
1216 return proto;
1219 SetLastError( WSANO_DATA );
1220 return NULL;
1224 /***********************************************************************
1225 * getprotobyname (ws2_32.53)
1227 struct protoent * WINAPI getprotobyname( const char *name )
1229 struct protoent *proto;
1230 const char *cursor;
1231 char *file;
1232 DWORD size;
1234 TRACE( "%s\n", debugstr_a(name) );
1236 if (!(file = read_etc_file( L"protocol", &size )))
1238 SetLastError( WSANO_DATA );
1239 return NULL;
1242 cursor = file;
1243 while ((proto = get_next_protocol( &cursor, file + size )))
1245 if (!strcasecmp( proto->p_name, name ))
1246 break;
1249 free( file );
1250 return proto;
1254 /***********************************************************************
1255 * getprotobynumber (ws2_32.54)
1257 struct protoent * WINAPI getprotobynumber( int number )
1259 struct protoent *proto;
1260 const char *cursor;
1261 char *file;
1262 DWORD size;
1264 TRACE( "%d\n", number );
1266 if (!(file = read_etc_file( L"protocol", &size )))
1268 SetLastError( WSANO_DATA );
1269 return NULL;
1272 cursor = file;
1273 while ((proto = get_next_protocol( &cursor, file + size )))
1275 if (proto->p_proto == number)
1276 break;
1279 free( file );
1280 return proto;
1284 static struct servent *get_servent_buffer( int size )
1286 struct per_thread_data *data = get_per_thread_data();
1287 struct servent *new_buffer;
1289 if (data->se_len < size)
1291 if (!(new_buffer = realloc( data->se_buffer, size )))
1293 SetLastError( WSAENOBUFS );
1294 return NULL;
1296 data->se_buffer = new_buffer;
1297 data->se_len = size;
1299 return data->se_buffer;
1302 /* Parse the first valid line into a servent structure, returning NULL if
1303 * there is no valid line. Updates cursor to point to the start of the next
1304 * line or the end of the file. */
1305 static struct servent *get_next_service( const char **cursor, const char *end )
1307 const char *p = *cursor;
1309 while (p < end)
1311 const char *line_end, *next_line;
1312 size_t needed_size, line_len;
1313 unsigned int alias_count = 0;
1314 struct servent *serv;
1315 const char *name;
1316 int port;
1317 char *q;
1319 for (line_end = p; line_end < end && *line_end != '\n' && *line_end != '#'; ++line_end)
1321 TRACE( "parsing line %s\n", debugstr_an(p, line_end - p) );
1323 for (next_line = line_end; next_line < end && *next_line != '\n'; ++next_line)
1325 if (next_line < end)
1326 ++next_line; /* skip over the newline */
1328 p = next_non_space( p, line_end );
1329 if (p == line_end)
1331 p = next_line;
1332 continue;
1335 /* parse the name */
1337 name = p;
1338 line_len = line_end - name;
1340 p = next_space( p, line_end );
1341 if (p == line_end)
1343 p = next_line;
1344 continue;
1347 p = next_non_space( p, line_end );
1349 /* parse the port */
1351 port = atoi( p );
1352 p = memchr( p, '/', line_end - p );
1353 if (!p)
1355 p = next_line;
1356 continue;
1359 p = next_space( p, line_end );
1360 p = next_non_space( p, line_end );
1362 /* we will copy the entire line after the servent structure, then
1363 * replace spaces with null bytes as necessary */
1365 while (p < line_end)
1367 ++alias_count;
1369 p = next_space( p, line_end );
1370 p = next_non_space( p, line_end );
1372 needed_size = sizeof(*serv) + line_len + 1 + (alias_count + 1) * sizeof(char *);
1374 if (!(serv = get_servent_buffer( needed_size )))
1376 SetLastError( WSAENOBUFS );
1377 return NULL;
1380 serv->s_port = htons( port );
1381 serv->s_aliases = (char **)(serv + 1);
1382 serv->s_name = (char *)(serv->s_aliases + alias_count + 1);
1384 memcpy( serv->s_name, name, line_len );
1385 serv->s_name[line_len] = 0;
1387 line_end = serv->s_name + line_len;
1389 q = serv->s_name;
1390 q = next_space( q, line_end );
1391 *q++ = 0;
1392 q = next_non_space( q, line_end );
1393 /* skip over the number */
1394 q = memchr( q, '/', line_end - q );
1395 serv->s_proto = ++q;
1396 q = next_space( q, line_end );
1397 if (q < line_end) *q++ = 0;
1398 q = next_non_space( q, line_end );
1400 alias_count = 0;
1401 while (q < line_end)
1403 serv->s_aliases[alias_count++] = q;
1404 q = next_space( q, line_end );
1405 if (q < line_end) *q++ = 0;
1406 q = next_non_space( q, line_end );
1408 serv->s_aliases[alias_count] = NULL;
1410 *cursor = next_line;
1411 return serv;
1414 SetLastError( WSANO_DATA );
1415 return NULL;
1419 /***********************************************************************
1420 * getservbyname (ws2_32.55)
1422 struct servent * WINAPI getservbyname( const char *name, const char *proto )
1424 struct servent *serv;
1425 const char *cursor;
1426 char *file;
1427 DWORD size;
1429 TRACE( "name %s, proto %s\n", debugstr_a(name), debugstr_a(proto) );
1431 if (!(file = read_etc_file( L"services", &size )))
1433 SetLastError( WSANO_DATA );
1434 return NULL;
1437 cursor = file;
1438 while ((serv = get_next_service( &cursor, file + size )))
1440 if (!strcasecmp( serv->s_name, name ) && (!proto || !strcasecmp( serv->s_proto, proto )))
1441 break;
1444 free( file );
1445 return serv;
1449 /***********************************************************************
1450 * getservbyport (ws2_32.56)
1452 struct servent * WINAPI getservbyport( int port, const char *proto )
1454 struct servent *serv;
1455 const char *cursor;
1456 char *file;
1457 DWORD size;
1459 TRACE( "port %d, proto %s\n", port, debugstr_a(proto) );
1461 if (!(file = read_etc_file( L"services", &size )))
1463 SetLastError( WSANO_DATA );
1464 return NULL;
1467 cursor = file;
1468 while ((serv = get_next_service( &cursor, file + size )))
1470 if (serv->s_port == port && (!proto || !strcasecmp( serv->s_proto, proto )))
1471 break;
1474 free( file );
1475 return serv;
1479 /***********************************************************************
1480 * inet_ntoa (ws2_32.12)
1482 char * WINAPI inet_ntoa( struct in_addr in )
1484 unsigned int long_ip = ntohl( in.s_addr );
1485 struct per_thread_data *data = get_per_thread_data();
1487 sprintf( data->ntoa_buffer, "%u.%u.%u.%u",
1488 (long_ip >> 24) & 0xff,
1489 (long_ip >> 16) & 0xff,
1490 (long_ip >> 8) & 0xff,
1491 long_ip & 0xff );
1493 return data->ntoa_buffer;
1497 /***********************************************************************
1498 * inet_ntop (ws2_32.@)
1500 const char * WINAPI inet_ntop( int family, void *addr, char *buffer, SIZE_T len )
1502 NTSTATUS status;
1503 ULONG size = min( len, (ULONG)-1 );
1505 TRACE( "family %d, addr %p, buffer %p, len %Id\n", family, addr, buffer, len );
1506 if (!buffer)
1508 SetLastError( STATUS_INVALID_PARAMETER );
1509 return NULL;
1512 switch (family)
1514 case AF_INET:
1516 status = RtlIpv4AddressToStringExA( (IN_ADDR *)addr, 0, buffer, &size );
1517 break;
1519 case AF_INET6:
1521 status = RtlIpv6AddressToStringExA( (IN6_ADDR *)addr, 0, 0, buffer, &size );
1522 break;
1524 default:
1525 SetLastError( WSAEAFNOSUPPORT );
1526 return NULL;
1529 if (status == STATUS_SUCCESS) return buffer;
1530 SetLastError( STATUS_INVALID_PARAMETER );
1531 return NULL;
1534 /***********************************************************************
1535 * inet_pton (ws2_32.@)
1537 int WINAPI inet_pton( int family, const char *addr, void *buffer )
1539 NTSTATUS status;
1540 const char *terminator;
1542 TRACE( "family %d, addr %s, buffer %p\n", family, debugstr_a(addr), buffer );
1544 if (!addr || !buffer)
1546 SetLastError( WSAEFAULT );
1547 return -1;
1550 switch (family)
1552 case AF_INET:
1553 status = RtlIpv4StringToAddressA(addr, TRUE, &terminator, buffer);
1554 break;
1555 case AF_INET6:
1556 status = RtlIpv6StringToAddressA(addr, &terminator, buffer);
1557 break;
1558 default:
1559 SetLastError( WSAEAFNOSUPPORT );
1560 return -1;
1563 return (status == STATUS_SUCCESS && *terminator == 0);
1566 /***********************************************************************
1567 * InetPtonW (ws2_32.@)
1569 int WINAPI InetPtonW( int family, const WCHAR *addr, void *buffer )
1571 char *addrA;
1572 int len;
1573 INT ret;
1575 TRACE( "family %d, addr %s, buffer %p\n", family, debugstr_w(addr), buffer );
1577 if (!addr)
1579 SetLastError(WSAEFAULT);
1580 return SOCKET_ERROR;
1583 len = WideCharToMultiByte( CP_ACP, 0, addr, -1, NULL, 0, NULL, NULL );
1584 if (!(addrA = malloc( len )))
1586 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1587 return -1;
1589 WideCharToMultiByte( CP_ACP, 0, addr, -1, addrA, len, NULL, NULL );
1591 ret = inet_pton( family, addrA, buffer );
1592 if (!ret) SetLastError( WSAEINVAL );
1594 free( addrA );
1595 return ret;
1598 /***********************************************************************
1599 * InetNtopW (ws2_32.@)
1601 const WCHAR * WINAPI InetNtopW( int family, void *addr, WCHAR *buffer, SIZE_T len )
1603 char bufferA[INET6_ADDRSTRLEN];
1604 PWSTR ret = NULL;
1606 TRACE( "family %d, addr %p, buffer %p, len %Iu\n", family, addr, buffer, len );
1608 if (inet_ntop( family, addr, bufferA, sizeof(bufferA) ))
1610 if (MultiByteToWideChar( CP_ACP, 0, bufferA, -1, buffer, len ))
1611 ret = buffer;
1612 else
1613 SetLastError( ERROR_INVALID_PARAMETER );
1615 return ret;
1619 /***********************************************************************
1620 * WSAStringToAddressA (ws2_32.@)
1622 int WINAPI WSAStringToAddressA( char *string, int family, WSAPROTOCOL_INFOA *protocol_info,
1623 struct sockaddr *addr, int *addr_len )
1625 NTSTATUS status;
1627 TRACE( "string %s, family %u\n", debugstr_a(string), family );
1629 if (!addr || !addr_len) return -1;
1631 if (!string)
1633 SetLastError( WSAEINVAL );
1634 return -1;
1637 if (protocol_info)
1638 FIXME( "ignoring protocol_info\n" );
1640 switch (family)
1642 case AF_INET:
1644 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1646 if (*addr_len < sizeof(struct sockaddr_in))
1648 *addr_len = sizeof(struct sockaddr_in);
1649 SetLastError( WSAEFAULT );
1650 return -1;
1652 memset( addr, 0, sizeof(struct sockaddr_in) );
1654 status = RtlIpv4StringToAddressExA( string, FALSE, &addr4->sin_addr, &addr4->sin_port );
1655 if (status != STATUS_SUCCESS)
1657 SetLastError( WSAEINVAL );
1658 return -1;
1660 addr4->sin_family = AF_INET;
1661 *addr_len = sizeof(struct sockaddr_in);
1662 return 0;
1664 case AF_INET6:
1666 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1668 if (*addr_len < sizeof(struct sockaddr_in6))
1670 *addr_len = sizeof(struct sockaddr_in6);
1671 SetLastError( WSAEFAULT );
1672 return -1;
1674 memset( addr, 0, sizeof(struct sockaddr_in6) );
1676 status = RtlIpv6StringToAddressExA( string, &addr6->sin6_addr, &addr6->sin6_scope_id, &addr6->sin6_port );
1677 if (status != STATUS_SUCCESS)
1679 SetLastError( WSAEINVAL );
1680 return -1;
1682 addr6->sin6_family = AF_INET6;
1683 *addr_len = sizeof(struct sockaddr_in6);
1684 return 0;
1686 default:
1687 /* According to MSDN, only AF_INET and AF_INET6 are supported. */
1688 TRACE( "Unsupported address family specified: %d.\n", family );
1689 SetLastError( WSAEINVAL );
1690 return -1;
1695 /***********************************************************************
1696 * WSAStringToAddressW (ws2_32.@)
1698 int WINAPI WSAStringToAddressW( WCHAR *string, int family, WSAPROTOCOL_INFOW *protocol_info,
1699 struct sockaddr *addr, int *addr_len )
1701 WSAPROTOCOL_INFOA infoA;
1702 WSAPROTOCOL_INFOA *protocol_infoA = NULL;
1703 int sizeA, ret;
1704 char *stringA;
1706 TRACE( "string %s, family %u\n", debugstr_w(string), family );
1708 if (!addr || !addr_len) return -1;
1710 if (protocol_info)
1712 protocol_infoA = &infoA;
1713 memcpy( protocol_infoA, protocol_info, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
1715 if (!WideCharToMultiByte( CP_ACP, 0, protocol_info->szProtocol, -1, protocol_infoA->szProtocol,
1716 sizeof(protocol_infoA->szProtocol), NULL, NULL ))
1718 SetLastError( WSAEINVAL );
1719 return -1;
1723 if (!string)
1725 SetLastError( WSAEINVAL );
1726 return -1;
1729 sizeA = WideCharToMultiByte( CP_ACP, 0, string, -1, NULL, 0, NULL, NULL );
1730 if (!(stringA = malloc( sizeA )))
1732 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1733 return -1;
1735 WideCharToMultiByte( CP_ACP, 0, string, -1, stringA, sizeA, NULL, NULL );
1736 ret = WSAStringToAddressA( stringA, family, protocol_infoA, addr, addr_len );
1737 free( stringA );
1738 return ret;
1742 /***********************************************************************
1743 * WSAAddressToStringA (ws2_32.@)
1745 int WINAPI WSAAddressToStringA( struct sockaddr *addr, DWORD addr_len,
1746 WSAPROTOCOL_INFOA *info, char *string, DWORD *string_len )
1748 char buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
1749 DWORD size;
1751 TRACE( "addr %s\n", debugstr_sockaddr(addr) );
1753 if (!addr) return SOCKET_ERROR;
1754 if (!string || !string_len) return SOCKET_ERROR;
1756 switch (addr->sa_family)
1758 case AF_INET:
1760 const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
1761 unsigned int long_ip = ntohl( addr4->sin_addr.s_addr );
1762 char *p;
1764 if (addr_len < sizeof(struct sockaddr_in)) return -1;
1765 sprintf( buffer, "%u.%u.%u.%u:%u",
1766 (long_ip >> 24) & 0xff,
1767 (long_ip >> 16) & 0xff,
1768 (long_ip >> 8) & 0xff,
1769 long_ip & 0xff,
1770 ntohs( addr4->sin_port ) );
1772 p = strchr( buffer, ':' );
1773 if (!addr4->sin_port) *p = 0;
1774 break;
1776 case AF_INET6:
1778 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1779 size_t len;
1781 buffer[0] = 0;
1782 if (addr_len < sizeof(struct sockaddr_in6)) return -1;
1783 if (addr6->sin6_port)
1784 strcpy( buffer, "[" );
1785 len = strlen( buffer );
1786 if (!inet_ntop( AF_INET6, &addr6->sin6_addr, &buffer[len], sizeof(buffer) - len ))
1788 SetLastError( WSAEINVAL );
1789 return -1;
1791 if (addr6->sin6_scope_id)
1792 sprintf( buffer + strlen( buffer ), "%%%lu", addr6->sin6_scope_id );
1793 if (addr6->sin6_port)
1794 sprintf( buffer + strlen( buffer ), "]:%u", ntohs( addr6->sin6_port ) );
1795 break;
1798 default:
1799 SetLastError( WSAEINVAL );
1800 return -1;
1803 size = strlen( buffer ) + 1;
1805 if (*string_len < size)
1807 *string_len = size;
1808 SetLastError( WSAEFAULT );
1809 return -1;
1812 TRACE( "=> %s, %lu chars\n", debugstr_a(buffer), size );
1813 *string_len = size;
1814 strcpy( string, buffer );
1815 return 0;
1819 /***********************************************************************
1820 * WSAAddressToStringW (ws2_32.@)
1822 int WINAPI WSAAddressToStringW( struct sockaddr *addr, DWORD addr_len,
1823 WSAPROTOCOL_INFOW *info, WCHAR *string, DWORD *string_len )
1825 INT ret;
1826 char buf[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
1828 TRACE( "(%p, %lu, %p, %p, %p)\n", addr, addr_len, info, string, string_len );
1830 if ((ret = WSAAddressToStringA( addr, addr_len, NULL, buf, string_len ))) return ret;
1832 MultiByteToWideChar( CP_ACP, 0, buf, *string_len, string, *string_len );
1833 TRACE( "=> %s, %lu chars\n", debugstr_w(string), *string_len );
1834 return 0;
1837 /***********************************************************************
1838 * inet_addr (ws2_32.11)
1840 u_long WINAPI inet_addr( const char *str )
1842 unsigned long a[4] = { 0 };
1843 const char *s = str;
1844 unsigned char *d;
1845 unsigned int i;
1846 u_long addr;
1847 char *z;
1849 TRACE( "str %s.\n", debugstr_a(str) );
1851 if (!s)
1853 SetLastError( WSAEFAULT );
1854 return INADDR_NONE;
1857 d = (unsigned char *)&addr;
1859 if (s[0] == ' ' && !s[1]) return 0;
1861 for (i = 0; i < 4; ++i)
1863 a[i] = strtoul( s, &z, 0 );
1864 if (z == s || !isdigit( *s )) return INADDR_NONE;
1865 if (!*z || isspace(*z)) break;
1866 if (*z != '.') return INADDR_NONE;
1867 s = z + 1;
1870 if (i == 4) return INADDR_NONE;
1872 switch (i)
1874 case 0:
1875 a[1] = a[0] & 0xffffff;
1876 a[0] >>= 24;
1877 /* fallthrough */
1878 case 1:
1879 a[2] = a[1] & 0xffff;
1880 a[1] >>= 16;
1881 /* fallthrough */
1882 case 2:
1883 a[3] = a[2] & 0xff;
1884 a[2] >>= 8;
1886 for (i = 0; i < 4; ++i)
1888 if (a[i] > 255) return INADDR_NONE;
1889 d[i] = a[i];
1891 return addr;
1895 /***********************************************************************
1896 * htonl (ws2_32.8)
1898 u_long WINAPI WS_htonl( u_long hostlong )
1900 return htonl( hostlong );
1904 /***********************************************************************
1905 * htons (ws2_32.9)
1907 u_short WINAPI WS_htons( u_short hostshort )
1909 return htons( hostshort );
1913 /***********************************************************************
1914 * WSAHtonl (ws2_32.@)
1916 int WINAPI WSAHtonl( SOCKET s, u_long hostlong, u_long *netlong )
1918 if (netlong)
1920 *netlong = htonl( hostlong );
1921 return 0;
1923 SetLastError( WSAEFAULT );
1924 return -1;
1928 /***********************************************************************
1929 * WSAHtons (ws2_32.@)
1931 int WINAPI WSAHtons( SOCKET s, u_short hostshort, u_short *netshort )
1933 if (netshort)
1935 *netshort = htons( hostshort );
1936 return 0;
1938 SetLastError( WSAEFAULT );
1939 return -1;
1943 /***********************************************************************
1944 * ntohl (ws2_32.14)
1946 u_long WINAPI WS_ntohl( u_long netlong )
1948 return ntohl( netlong );
1952 /***********************************************************************
1953 * ntohs (ws2_32.15)
1955 u_short WINAPI WS_ntohs( u_short netshort )
1957 return ntohs( netshort );
1961 /***********************************************************************
1962 * WSANtohl (ws2_32.@)
1964 int WINAPI WSANtohl( SOCKET s, u_long netlong, u_long *hostlong )
1966 if (!hostlong) return WSAEFAULT;
1968 *hostlong = ntohl( netlong );
1969 return 0;
1973 /***********************************************************************
1974 * WSANtohs (ws2_32.@)
1976 int WINAPI WSANtohs( SOCKET s, u_short netshort, u_short *hostshort )
1978 if (!hostshort) return WSAEFAULT;
1980 *hostshort = ntohs( netshort );
1981 return 0;
1985 /***********************************************************************
1986 * WSAInstallServiceClassA (ws2_32.@)
1988 int WINAPI WSAInstallServiceClassA( WSASERVICECLASSINFOA *info )
1990 FIXME( "Request to install service %s\n", debugstr_a(info->lpszServiceClassName) );
1991 SetLastError( WSAEACCES );
1992 return -1;
1996 /***********************************************************************
1997 * WSAInstallServiceClassW (ws2_32.@)
1999 int WINAPI WSAInstallServiceClassW( WSASERVICECLASSINFOW *info )
2001 FIXME( "Request to install service %s\n", debugstr_w(info->lpszServiceClassName) );
2002 SetLastError( WSAEACCES );
2003 return -1;
2007 /***********************************************************************
2008 * WSARemoveServiceClass (ws2_32.@)
2010 int WINAPI WSARemoveServiceClass( GUID *info )
2012 FIXME( "Request to remove service %s\n", debugstr_guid(info) );
2013 SetLastError( WSATYPE_NOT_FOUND );
2014 return -1;
2018 /***********************************************************************
2019 * WSAGetServiceClassInfoA (ws2_32.@)
2021 int WINAPI WSAGetServiceClassInfoA( GUID *provider, GUID *service, DWORD *len,
2022 WSASERVICECLASSINFOA *info )
2024 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service), len, info );
2025 SetLastError( WSA_NOT_ENOUGH_MEMORY );
2026 return -1;
2030 /***********************************************************************
2031 * WSAGetServiceClassInfoW (ws2_32.@)
2033 int WINAPI WSAGetServiceClassInfoW( GUID *provider, GUID *service, DWORD *len,
2034 WSASERVICECLASSINFOW *info )
2036 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service), len, info );
2037 SetLastError( WSA_NOT_ENOUGH_MEMORY );
2038 return -1;
2042 /***********************************************************************
2043 * WSAGetServiceClassNameByClassIdA (ws2_32.@)
2045 int WINAPI WSAGetServiceClassNameByClassIdA( GUID *class, char *service, DWORD *len )
2047 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
2048 SetLastError( WSA_NOT_ENOUGH_MEMORY );
2049 return -1;
2053 /***********************************************************************
2054 * WSAGetServiceClassNameByClassIdW (ws2_32.@)
2056 int WINAPI WSAGetServiceClassNameByClassIdW( GUID *class, WCHAR *service, DWORD *len )
2058 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
2059 SetLastError( WSA_NOT_ENOUGH_MEMORY );
2060 return -1;
2064 /***********************************************************************
2065 * WSALookupServiceBeginA (ws2_32.@)
2067 int WINAPI WSALookupServiceBeginA( WSAQUERYSETA *query, DWORD flags, HANDLE *lookup )
2069 FIXME( "(%p %#lx %p) Stub!\n", query, flags, lookup );
2070 SetLastError( WSA_NOT_ENOUGH_MEMORY );
2071 return -1;
2075 /***********************************************************************
2076 * WSALookupServiceBeginW (ws2_32.@)
2078 int WINAPI WSALookupServiceBeginW( WSAQUERYSETW *query, DWORD flags, HANDLE *lookup )
2080 FIXME( "(%p %#lx %p) Stub!\n", query, flags, lookup );
2081 SetLastError( WSA_NOT_ENOUGH_MEMORY );
2082 return -1;
2086 /***********************************************************************
2087 * WSALookupServiceEnd (ws2_32.@)
2089 int WINAPI WSALookupServiceEnd( HANDLE lookup )
2091 FIXME("(%p) Stub!\n", lookup );
2092 return 0;
2096 /***********************************************************************
2097 * WSALookupServiceNextA (ws2_32.@)
2099 int WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, DWORD *len, WSAQUERYSETA *results )
2101 FIXME( "(%p %#lx %p %p) Stub!\n", lookup, flags, len, results );
2102 SetLastError( WSA_E_NO_MORE );
2103 return -1;
2107 /***********************************************************************
2108 * WSALookupServiceNextW (ws2_32.@)
2110 int WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, DWORD *len, WSAQUERYSETW *results )
2112 FIXME( "(%p %#lx %p %p) Stub!\n", lookup, flags, len, results );
2113 SetLastError( WSA_E_NO_MORE );
2114 return -1;
2118 /***********************************************************************
2119 * WSASetServiceA (ws2_32.@)
2121 int WINAPI WSASetServiceA( WSAQUERYSETA *query, WSAESETSERVICEOP operation, DWORD flags )
2123 FIXME( "(%p %#x %#lx) Stub!\n", query, operation, flags );
2124 return 0;
2128 /***********************************************************************
2129 * WSASetServiceW (ws2_32.@)
2131 int WINAPI WSASetServiceW( WSAQUERYSETW *query, WSAESETSERVICEOP operation, DWORD flags )
2133 FIXME( "(%p %#x %#lx) Stub!\n", query, operation, flags );
2134 return 0;
2138 /***********************************************************************
2139 * WSAEnumNameSpaceProvidersA (ws2_32.@)
2141 int WINAPI WSAEnumNameSpaceProvidersA( DWORD *len, WSANAMESPACE_INFOA *buffer )
2143 FIXME( "(%p %p) Stub!\n", len, buffer );
2144 return 0;
2148 /***********************************************************************
2149 * WSAEnumNameSpaceProvidersW (ws2_32.@)
2151 int WINAPI WSAEnumNameSpaceProvidersW( DWORD *len, WSANAMESPACE_INFOW *buffer )
2153 FIXME( "(%p %p) Stub!\n", len, buffer );
2154 return 0;
2158 /***********************************************************************
2159 * WSAProviderConfigChange (ws2_32.@)
2161 int WINAPI WSAProviderConfigChange( HANDLE *handle, OVERLAPPED *overlapped,
2162 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
2164 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
2165 return -1;
2169 /***********************************************************************
2170 * WSANSPIoctl (ws2_32.@)
2172 int WINAPI WSANSPIoctl( HANDLE lookup, DWORD code, void *in_buffer,
2173 DWORD in_size, void *out_buffer, DWORD out_size,
2174 DWORD *ret_size, WSACOMPLETION *completion )
2176 FIXME( "(%p, %#lx, %p, %#lx, %p, %#lx, %p, %p) Stub!\n", lookup, code,
2177 in_buffer, in_size, out_buffer, out_size, ret_size, completion );
2178 SetLastError( WSA_NOT_ENOUGH_MEMORY );
2179 return -1;
2183 /***********************************************************************
2184 * WSCEnableNSProvider (ws2_32.@)
2186 int WINAPI WSCEnableNSProvider( GUID *provider, BOOL enable )
2188 FIXME( "(%s %d) Stub!\n", debugstr_guid(provider), enable );
2189 return 0;
2193 /***********************************************************************
2194 * WSCGetProviderInfo (ws2_32.@)
2196 int WINAPI WSCGetProviderInfo( GUID *provider, WSC_PROVIDER_INFO_TYPE info_type,
2197 BYTE *info, size_t *len, DWORD flags, int *errcode )
2199 FIXME( "(%s %#x %p %p %#lx %p) Stub!\n",
2200 debugstr_guid(provider), info_type, info, len, flags, errcode );
2202 if (!errcode)
2203 return -1;
2205 if (!provider)
2207 *errcode = WSAEFAULT;
2208 return -1;
2211 *errcode = WSANO_RECOVERY;
2212 return -1;
2216 /***********************************************************************
2217 * WSCGetProviderPath (ws2_32.@)
2219 int WINAPI WSCGetProviderPath( GUID *provider, WCHAR *path, int *len, int *errcode )
2221 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errcode );
2223 if (!provider || !len)
2225 if (errcode)
2226 *errcode = WSAEFAULT;
2227 return -1;
2230 if (*len <= 0)
2232 if (errcode)
2233 *errcode = WSAEINVAL;
2234 return -1;
2237 return 0;
2241 /***********************************************************************
2242 * WSCInstallNameSpace (ws2_32.@)
2244 int WINAPI WSCInstallNameSpace( WCHAR *identifier, WCHAR *path, DWORD namespace,
2245 DWORD version, GUID *provider )
2247 FIXME( "(%s %s %#lx %#lx %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
2248 namespace, version, debugstr_guid(provider) );
2249 return 0;
2253 /***********************************************************************
2254 * WSCUnInstallNameSpace (ws2_32.@)
2256 int WINAPI WSCUnInstallNameSpace( GUID *provider )
2258 FIXME( "(%s) Stub!\n", debugstr_guid(provider) );
2259 return NO_ERROR;
2263 /***********************************************************************
2264 * WSCWriteProviderOrder (ws2_32.@)
2266 int WINAPI WSCWriteProviderOrder( DWORD *entry, DWORD number )
2268 FIXME( "(%p %#lx) Stub!\n", entry, number );
2269 return 0;
2273 /***********************************************************************
2274 * WSCInstallProvider (ws2_32.@)
2276 int WINAPI WSCInstallProvider( GUID *provider, const WCHAR *path,
2277 WSAPROTOCOL_INFOW *protocol_info, DWORD count, int *err )
2279 FIXME( "(%s, %s, %p, %lu, %p): stub !\n", debugstr_guid(provider),
2280 debugstr_w(path), protocol_info, count, err );
2281 *err = 0;
2282 return 0;
2286 /***********************************************************************
2287 * WSCDeinstallProvider (ws2_32.@)
2289 int WINAPI WSCDeinstallProvider( GUID *provider, int *err )
2291 FIXME( "(%s, %p): stub !\n", debugstr_guid(provider), err );
2292 *err = 0;
2293 return 0;
2297 /***********************************************************************
2298 * WSCSetApplicationCategory (ws2_32.@)
2300 int WINAPI WSCSetApplicationCategory( const WCHAR *path, DWORD len, const WCHAR *extra, DWORD extralen,
2301 DWORD lspcat, DWORD *prev_lspcat, int *err )
2303 FIXME( "(%s %lu %s %lu %#lx %p) Stub!\n", debugstr_w(path), len, debugstr_w(extra),
2304 extralen, lspcat, prev_lspcat );
2305 return 0;
2309 /***********************************************************************
2310 * WSCEnumProtocols (ws2_32.@)
2312 int WINAPI WSCEnumProtocols( int *protocols, WSAPROTOCOL_INFOW *info, DWORD *len, int *err )
2314 int ret = WSAEnumProtocolsW( protocols, info, len );
2316 if (ret == SOCKET_ERROR) *err = WSAENOBUFS;
2318 return ret;