d3d11/tests: Add some tests for ID3DUserDefinedAnnotation.
[wine.git] / dlls / ws2_32 / protocol.c
blob867e9513ca278bc386fe66e9726ff02489ea96b7
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 unixlib_handle_t ws_unix_handle = 0;
32 #define WS_CALL(func, params) __wine_unix_call( ws_unix_handle, ws_unix_ ## func, params )
34 static char *get_fqdn(void)
36 char *ret;
37 DWORD size = 0;
39 GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, NULL, &size );
40 if (GetLastError() != ERROR_MORE_DATA) return NULL;
41 if (!(ret = malloc( size ))) return NULL;
42 if (!GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified, ret, &size ))
44 free( ret );
45 return NULL;
47 return ret;
50 /* call Unix getaddrinfo, allocating a large enough buffer */
51 static int do_getaddrinfo( const char *node, const char *service,
52 const struct addrinfo *hints, struct addrinfo **info )
54 unsigned int size = 1024;
55 struct getaddrinfo_params params = { node, service, hints, NULL, &size };
56 int ret;
58 for (;;)
60 if (!(params.info = malloc( size )))
61 return WSA_NOT_ENOUGH_MEMORY;
62 if (!(ret = WS_CALL( getaddrinfo, &params )))
64 *info = params.info;
65 return ret;
67 free( params.info );
68 if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
72 static int dns_only_query( const char *node, const struct addrinfo *hints, struct addrinfo **result )
74 DNS_STATUS status;
75 DNS_RECORDA *rec = NULL, *rec6 = NULL, *ptr;
76 struct addrinfo *info, *next;
77 struct sockaddr_in *addr;
78 struct sockaddr_in6 *addr6;
79 ULONG count = 0;
81 if (hints->ai_family != AF_INET && hints->ai_family != AF_INET6 && hints->ai_family != AF_UNSPEC)
83 FIXME( "unsupported family %u\n", hints->ai_family );
84 return EAI_FAMILY;
86 if (hints->ai_family == AF_INET || hints->ai_family == AF_UNSPEC)
88 status = DnsQuery_A( node, DNS_TYPE_A, DNS_QUERY_NO_NETBT | DNS_QUERY_NO_MULTICAST, NULL, &rec, NULL );
89 if (status != ERROR_SUCCESS && status != DNS_ERROR_RCODE_NAME_ERROR) return EAI_FAIL;
91 if (hints->ai_family == AF_INET6 || hints->ai_family == AF_UNSPEC)
93 status = DnsQuery_A( node, DNS_TYPE_AAAA, DNS_QUERY_NO_NETBT | DNS_QUERY_NO_MULTICAST, NULL, &rec6, NULL );
94 if (status != ERROR_SUCCESS && status != DNS_ERROR_RCODE_NAME_ERROR)
96 DnsRecordListFree( (DNS_RECORD *)rec, DnsFreeRecordList );
97 return EAI_FAIL;
101 for (ptr = rec; ptr; ptr = ptr->pNext) count++;
102 for (ptr = rec6; ptr; ptr = ptr->pNext) count++;
103 if (!count)
105 DnsRecordListFree( (DNS_RECORD *)rec, DnsFreeRecordList );
106 DnsRecordListFree( (DNS_RECORD *)rec6, DnsFreeRecordList );
107 return WSAHOST_NOT_FOUND;
109 if (!(info = calloc( count, sizeof(*info) + sizeof(SOCKADDR_STORAGE) )))
111 DnsRecordListFree( (DNS_RECORD *)rec, DnsFreeRecordList );
112 DnsRecordListFree( (DNS_RECORD *)rec6, DnsFreeRecordList );
113 return WSA_NOT_ENOUGH_MEMORY;
115 *result = info;
117 for (ptr = rec; ptr; ptr = ptr->pNext)
119 info->ai_family = AF_INET;
120 info->ai_socktype = hints->ai_socktype;
121 info->ai_protocol = hints->ai_protocol;
122 info->ai_addrlen = sizeof(struct sockaddr_in);
123 info->ai_addr = (struct sockaddr *)(info + 1);
124 addr = (struct sockaddr_in *)info->ai_addr;
125 addr->sin_family = info->ai_family;
126 addr->sin_addr.S_un.S_addr = ptr->Data.A.IpAddress;
127 next = (struct addrinfo *)((char *)info + sizeof(*info) + sizeof(SOCKADDR_STORAGE));
128 if (--count) info->ai_next = next;
129 info = next;
131 for (ptr = rec6; ptr; ptr = ptr->pNext)
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 %ld, 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 %u, 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 %u\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 %u, serv %p, serv_len %d, 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;
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 route_addrs = realloc( route_addrs, (numroutes + 1) * sizeof(struct route) );
856 if (!route_addrs)
857 goto cleanup;
858 route_addrs[numroutes].interface = ifindex;
859 route_addrs[numroutes].metric = ifmetric;
860 route_addrs[numroutes].default_route = ifdefault;
861 /* If no IP is found in the next step (for whatever reason)
862 * then fall back to the magic loopback address.
864 memcpy( &route_addrs[numroutes].addr.s_addr, magic_loopback_addr, 4 );
865 numroutes++;
867 if (numroutes == 0)
868 goto cleanup; /* No routes, fall back to the Magic IP */
870 /* Find the IP address associated with each found interface */
871 for (i = 0; i < numroutes; i++)
873 for (k = adapters; k != NULL; k = k->Next)
875 char *ip = k->IpAddressList.IpAddress.String;
877 if (route_addrs[i].interface == k->Index)
878 route_addrs[i].addr.s_addr = inet_addr(ip);
882 /* Allocate a hostent and enough memory for all the IPs,
883 * including the NULL at the end of the list.
885 hostlist = create_hostent( hostname, 1, 0, numroutes+1, sizeof(struct in_addr) );
886 if (hostlist == NULL)
887 goto cleanup;
888 hostlist->h_addr_list[numroutes] = NULL;
889 hostlist->h_aliases[0] = NULL;
890 hostlist->h_addrtype = AF_INET;
891 hostlist->h_length = sizeof(struct in_addr);
893 /* Reorder the entries before placing them in the host list. Windows expects
894 * the IP list in order from highest priority to lowest (the critical thing
895 * is that most applications expect the first IP to be the default route).
897 if (numroutes > 1)
898 qsort( route_addrs, numroutes, sizeof(struct route), compare_routes_by_metric_asc );
900 for (i = 0; i < numroutes; i++)
901 *(struct in_addr *)hostlist->h_addr_list[i] = route_addrs[i].addr;
903 cleanup:
904 free( route_addrs );
905 free( adapters );
906 free( routes );
907 return hostlist;
911 /***********************************************************************
912 * gethostbyname (ws2_32.52)
914 struct hostent * WINAPI gethostbyname( const char *name )
916 struct hostent *host = NULL;
917 char hostname[100];
918 struct gethostname_params params = { hostname, sizeof(hostname) };
919 int ret;
921 TRACE( "%s\n", debugstr_a(name) );
923 if (!num_startup)
925 SetLastError( WSANOTINITIALISED );
926 return NULL;
929 if ((ret = WS_CALL( gethostname, &params )))
931 SetLastError( ret );
932 return NULL;
935 if (!name || !name[0])
936 name = hostname;
938 /* If the hostname of the local machine is requested then return the
939 * complete list of local IP addresses */
940 if (!strcmp( name, hostname ))
941 host = get_local_ips( hostname );
943 /* If any other hostname was requested (or the routing table lookup failed)
944 * then return the IP found by the host OS */
945 if (!host)
947 unsigned int size = 1024;
948 struct gethostbyname_params params = { name, NULL, &size };
949 int ret;
951 for (;;)
953 if (!(params.host = get_hostent_buffer( size )))
954 return NULL;
956 if ((ret = WS_CALL( gethostbyname, &params )) != ERROR_INSUFFICIENT_BUFFER)
957 break;
960 SetLastError( ret );
961 return ret ? NULL : params.host;
964 if (host && host->h_addr_list[0][0] == 127 && strcmp( name, "localhost" ))
966 /* hostname != "localhost" but has loopback address. replace by our
967 * special address.*/
968 memcpy( host->h_addr_list[0], magic_loopback_addr, 4 );
971 return host;
975 /***********************************************************************
976 * gethostname (ws2_32.57)
978 int WINAPI gethostname( char *name, int namelen )
980 char buf[256];
981 struct gethostname_params params = { buf, sizeof(buf) };
982 int len, ret;
984 TRACE( "name %p, len %d\n", name, namelen );
986 if (!name)
988 SetLastError( WSAEFAULT );
989 return -1;
992 if ((ret = WS_CALL( gethostname, &params )))
994 SetLastError( ret );
995 return -1;
998 TRACE( "<- %s\n", debugstr_a(buf) );
999 len = strlen( buf );
1000 if (len > 15)
1001 WARN( "Windows supports NetBIOS name length up to 15 bytes!\n" );
1002 if (namelen <= len)
1004 SetLastError( WSAEFAULT );
1005 return -1;
1007 strcpy( name, buf );
1008 return 0;
1012 /***********************************************************************
1013 * GetHostNameW (ws2_32.@)
1015 int WINAPI GetHostNameW( WCHAR *name, int namelen )
1017 char buf[256];
1018 struct gethostname_params params = { buf, sizeof(buf) };
1019 int ret;
1021 TRACE( "name %p, len %d\n", name, namelen );
1023 if (!name)
1025 SetLastError( WSAEFAULT );
1026 return -1;
1029 if ((ret = WS_CALL( gethostname, &params )))
1031 SetLastError( ret );
1032 return -1;
1035 if (MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 ) > namelen)
1037 SetLastError( WSAEFAULT );
1038 return -1;
1040 MultiByteToWideChar( CP_ACP, 0, buf, -1, name, namelen );
1041 return 0;
1045 static char *read_etc_file( const WCHAR *filename, DWORD *ret_size )
1047 WCHAR path[MAX_PATH];
1048 DWORD size = sizeof(path);
1049 HANDLE file;
1050 char *data;
1051 LONG ret;
1053 if ((ret = RegGetValueW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\tcpip\\Parameters",
1054 L"DatabasePath", RRF_RT_REG_SZ, NULL, path, &size )))
1056 ERR( "failed to get database path, error %u\n", ret );
1057 return NULL;
1059 wcscat( path, L"\\" );
1060 wcscat( path, filename );
1062 file = CreateFileW( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
1063 if (file == INVALID_HANDLE_VALUE)
1065 ERR( "failed to open %s, error %u\n", debugstr_w( path ), GetLastError() );
1066 return NULL;
1069 size = GetFileSize( file, NULL );
1070 if (!(data = malloc( size )) || !ReadFile( file, data, size, ret_size, NULL ))
1072 WARN( "failed to read file, error %u\n", GetLastError() );
1073 free( data );
1074 data = NULL;
1076 CloseHandle( file );
1077 return data;
1080 /* returns "end" if there was no space */
1081 static char *next_space( const char *p, const char *end )
1083 while (p < end && !isspace( *p ))
1084 ++p;
1085 return (char *)p;
1088 /* returns "end" if there was no non-space */
1089 static char *next_non_space( const char *p, const char *end )
1091 while (p < end && isspace( *p ))
1092 ++p;
1093 return (char *)p;
1097 static struct protoent *get_protoent_buffer( unsigned int size )
1099 struct per_thread_data *data = get_per_thread_data();
1100 struct protoent *new_buffer;
1102 if (data->pe_len < size)
1104 if (!(new_buffer = realloc( data->pe_buffer, size )))
1106 SetLastError( WSAENOBUFS );
1107 return NULL;
1109 data->pe_buffer = new_buffer;
1110 data->pe_len = size;
1112 return data->pe_buffer;
1115 /* Parse the first valid line into a protoent structure, returning NULL if
1116 * there is no valid line. Updates cursor to point to the start of the next
1117 * line or the end of the file. */
1118 static struct protoent *get_next_protocol( const char **cursor, const char *end )
1120 const char *p = *cursor;
1122 while (p < end)
1124 const char *line_end, *next_line;
1125 size_t needed_size, line_len;
1126 unsigned int alias_count = 0;
1127 struct protoent *proto;
1128 const char *name;
1129 int number;
1130 char *q;
1132 for (line_end = p; line_end < end && *line_end != '\n' && *line_end != '#'; ++line_end)
1134 TRACE( "parsing line %s\n", debugstr_an(p, line_end - p) );
1136 for (next_line = line_end; next_line < end && *next_line != '\n'; ++next_line)
1138 if (next_line < end)
1139 ++next_line; /* skip over the newline */
1141 p = next_non_space( p, line_end );
1142 if (p == line_end)
1144 p = next_line;
1145 continue;
1148 /* parse the name */
1150 name = p;
1151 line_len = line_end - name;
1153 p = next_space( p, line_end );
1154 if (p == line_end)
1156 p = next_line;
1157 continue;
1160 p = next_non_space( p, line_end );
1162 /* parse the number */
1164 number = atoi( p );
1166 p = next_space( p, line_end );
1167 p = next_non_space( p, line_end );
1169 /* we will copy the entire line after the protoent structure, then
1170 * replace spaces with null bytes as necessary */
1172 while (p < line_end)
1174 ++alias_count;
1176 p = next_space( p, line_end );
1177 p = next_non_space( p, line_end );
1179 needed_size = sizeof(*proto) + line_len + 1 + (alias_count + 1) * sizeof(char *);
1181 if (!(proto = get_protoent_buffer( needed_size )))
1183 SetLastError( WSAENOBUFS );
1184 return NULL;
1187 proto->p_proto = number;
1188 proto->p_aliases = (char **)(proto + 1);
1189 proto->p_name = (char *)(proto->p_aliases + alias_count + 1);
1191 memcpy( proto->p_name, name, line_len );
1192 proto->p_name[line_len] = 0;
1194 line_end = proto->p_name + line_len;
1196 q = proto->p_name;
1197 q = next_space( q, line_end );
1198 *q++ = 0;
1199 q = next_non_space( q, line_end );
1200 /* skip over the number */
1201 q = next_space( q, line_end );
1202 q = next_non_space( q, line_end );
1204 alias_count = 0;
1205 while (q < line_end)
1207 proto->p_aliases[alias_count++] = q;
1208 q = next_space( q, line_end );
1209 if (q < line_end) *q++ = 0;
1210 q = next_non_space( q, line_end );
1212 proto->p_aliases[alias_count] = NULL;
1214 *cursor = next_line;
1215 return proto;
1218 SetLastError( WSANO_DATA );
1219 return NULL;
1223 /***********************************************************************
1224 * getprotobyname (ws2_32.53)
1226 struct protoent * WINAPI getprotobyname( const char *name )
1228 struct protoent *proto;
1229 const char *cursor;
1230 char *file;
1231 DWORD size;
1233 TRACE( "%s\n", debugstr_a(name) );
1235 if (!(file = read_etc_file( L"protocol", &size )))
1237 SetLastError( WSANO_DATA );
1238 return NULL;
1241 cursor = file;
1242 while ((proto = get_next_protocol( &cursor, file + size )))
1244 if (!strcasecmp( proto->p_name, name ))
1245 break;
1248 free( file );
1249 return proto;
1253 /***********************************************************************
1254 * getprotobynumber (ws2_32.54)
1256 struct protoent * WINAPI getprotobynumber( int number )
1258 struct protoent *proto;
1259 const char *cursor;
1260 char *file;
1261 DWORD size;
1263 TRACE( "%d\n", number );
1265 if (!(file = read_etc_file( L"protocol", &size )))
1267 SetLastError( WSANO_DATA );
1268 return NULL;
1271 cursor = file;
1272 while ((proto = get_next_protocol( &cursor, file + size )))
1274 if (proto->p_proto == number)
1275 break;
1278 free( file );
1279 return proto;
1283 static struct servent *get_servent_buffer( int size )
1285 struct per_thread_data *data = get_per_thread_data();
1286 struct servent *new_buffer;
1288 if (data->se_len < size)
1290 if (!(new_buffer = realloc( data->se_buffer, size )))
1292 SetLastError( WSAENOBUFS );
1293 return NULL;
1295 data->se_buffer = new_buffer;
1296 data->se_len = size;
1298 return data->se_buffer;
1301 /* Parse the first valid line into a servent structure, returning NULL if
1302 * there is no valid line. Updates cursor to point to the start of the next
1303 * line or the end of the file. */
1304 static struct servent *get_next_service( const char **cursor, const char *end )
1306 const char *p = *cursor;
1308 while (p < end)
1310 const char *line_end, *next_line;
1311 size_t needed_size, line_len;
1312 unsigned int alias_count = 0;
1313 struct servent *serv;
1314 const char *name;
1315 int port;
1316 char *q;
1318 for (line_end = p; line_end < end && *line_end != '\n' && *line_end != '#'; ++line_end)
1320 TRACE( "parsing line %s\n", debugstr_an(p, line_end - p) );
1322 for (next_line = line_end; next_line < end && *next_line != '\n'; ++next_line)
1324 if (next_line < end)
1325 ++next_line; /* skip over the newline */
1327 p = next_non_space( p, line_end );
1328 if (p == line_end)
1330 p = next_line;
1331 continue;
1334 /* parse the name */
1336 name = p;
1337 line_len = line_end - name;
1339 p = next_space( p, line_end );
1340 if (p == line_end)
1342 p = next_line;
1343 continue;
1346 p = next_non_space( p, line_end );
1348 /* parse the port */
1350 port = atoi( p );
1351 p = memchr( p, '/', line_end - p );
1352 if (!p)
1354 p = next_line;
1355 continue;
1358 p = next_space( p, line_end );
1359 p = next_non_space( p, line_end );
1361 /* we will copy the entire line after the servent structure, then
1362 * replace spaces with null bytes as necessary */
1364 while (p < line_end)
1366 ++alias_count;
1368 p = next_space( p, line_end );
1369 p = next_non_space( p, line_end );
1371 needed_size = sizeof(*serv) + line_len + 1 + (alias_count + 1) * sizeof(char *);
1373 if (!(serv = get_servent_buffer( needed_size )))
1375 SetLastError( WSAENOBUFS );
1376 return NULL;
1379 serv->s_port = htons( port );
1380 serv->s_aliases = (char **)(serv + 1);
1381 serv->s_name = (char *)(serv->s_aliases + alias_count + 1);
1383 memcpy( serv->s_name, name, line_len );
1384 serv->s_name[line_len] = 0;
1386 line_end = serv->s_name + line_len;
1388 q = serv->s_name;
1389 q = next_space( q, line_end );
1390 *q++ = 0;
1391 q = next_non_space( q, line_end );
1392 /* skip over the number */
1393 q = memchr( q, '/', line_end - q );
1394 serv->s_proto = ++q;
1395 q = next_space( q, line_end );
1396 if (q < line_end) *q++ = 0;
1397 q = next_non_space( q, line_end );
1399 alias_count = 0;
1400 while (q < line_end)
1402 serv->s_aliases[alias_count++] = q;
1403 q = next_space( q, line_end );
1404 if (q < line_end) *q++ = 0;
1405 q = next_non_space( q, line_end );
1407 serv->s_aliases[alias_count] = NULL;
1409 *cursor = next_line;
1410 return serv;
1413 SetLastError( WSANO_DATA );
1414 return NULL;
1418 /***********************************************************************
1419 * getservbyname (ws2_32.55)
1421 struct servent * WINAPI getservbyname( const char *name, const char *proto )
1423 struct servent *serv;
1424 const char *cursor;
1425 char *file;
1426 DWORD size;
1428 TRACE( "name %s, proto %s\n", debugstr_a(name), debugstr_a(proto) );
1430 if (!(file = read_etc_file( L"services", &size )))
1432 SetLastError( WSANO_DATA );
1433 return NULL;
1436 cursor = file;
1437 while ((serv = get_next_service( &cursor, file + size )))
1439 if (!strcasecmp( serv->s_name, name ) && (!proto || !strcasecmp( serv->s_proto, proto )))
1440 break;
1443 free( file );
1444 return serv;
1448 /***********************************************************************
1449 * getservbyport (ws2_32.56)
1451 struct servent * WINAPI getservbyport( int port, const char *proto )
1453 struct servent *serv;
1454 const char *cursor;
1455 char *file;
1456 DWORD size;
1458 TRACE( "port %d, proto %s\n", port, debugstr_a(proto) );
1460 if (!(file = read_etc_file( L"services", &size )))
1462 SetLastError( WSANO_DATA );
1463 return NULL;
1466 cursor = file;
1467 while ((serv = get_next_service( &cursor, file + size )))
1469 if (serv->s_port == port && (!proto || !strcasecmp( serv->s_proto, proto )))
1470 break;
1473 free( file );
1474 return serv;
1478 /***********************************************************************
1479 * inet_ntoa (ws2_32.12)
1481 char * WINAPI inet_ntoa( struct in_addr in )
1483 unsigned int long_ip = ntohl( in.s_addr );
1484 struct per_thread_data *data = get_per_thread_data();
1486 sprintf( data->ntoa_buffer, "%u.%u.%u.%u",
1487 (long_ip >> 24) & 0xff,
1488 (long_ip >> 16) & 0xff,
1489 (long_ip >> 8) & 0xff,
1490 long_ip & 0xff );
1492 return data->ntoa_buffer;
1496 /***********************************************************************
1497 * inet_ntop (ws2_32.@)
1499 const char * WINAPI inet_ntop( int family, void *addr, char *buffer, SIZE_T len )
1501 NTSTATUS status;
1502 ULONG size = min( len, (ULONG)-1 );
1504 TRACE( "family %d, addr %p, buffer %p, len %ld\n", family, addr, buffer, len );
1505 if (!buffer)
1507 SetLastError( STATUS_INVALID_PARAMETER );
1508 return NULL;
1511 switch (family)
1513 case AF_INET:
1515 status = RtlIpv4AddressToStringExA( (IN_ADDR *)addr, 0, buffer, &size );
1516 break;
1518 case AF_INET6:
1520 status = RtlIpv6AddressToStringExA( (IN6_ADDR *)addr, 0, 0, buffer, &size );
1521 break;
1523 default:
1524 SetLastError( WSAEAFNOSUPPORT );
1525 return NULL;
1528 if (status == STATUS_SUCCESS) return buffer;
1529 SetLastError( STATUS_INVALID_PARAMETER );
1530 return NULL;
1533 /***********************************************************************
1534 * inet_pton (ws2_32.@)
1536 int WINAPI inet_pton( int family, const char *addr, void *buffer )
1538 NTSTATUS status;
1539 const char *terminator;
1541 TRACE( "family %d, addr %s, buffer %p\n", family, debugstr_a(addr), buffer );
1543 if (!addr || !buffer)
1545 SetLastError( WSAEFAULT );
1546 return -1;
1549 switch (family)
1551 case AF_INET:
1552 status = RtlIpv4StringToAddressA(addr, TRUE, &terminator, buffer);
1553 break;
1554 case AF_INET6:
1555 status = RtlIpv6StringToAddressA(addr, &terminator, buffer);
1556 break;
1557 default:
1558 SetLastError( WSAEAFNOSUPPORT );
1559 return -1;
1562 return (status == STATUS_SUCCESS && *terminator == 0);
1565 /***********************************************************************
1566 * InetPtonW (ws2_32.@)
1568 int WINAPI InetPtonW( int family, const WCHAR *addr, void *buffer )
1570 char *addrA;
1571 int len;
1572 INT ret;
1574 TRACE( "family %d, addr %s, buffer %p\n", family, debugstr_w(addr), buffer );
1576 if (!addr)
1578 SetLastError(WSAEFAULT);
1579 return SOCKET_ERROR;
1582 len = WideCharToMultiByte( CP_ACP, 0, addr, -1, NULL, 0, NULL, NULL );
1583 if (!(addrA = malloc( len )))
1585 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1586 return -1;
1588 WideCharToMultiByte( CP_ACP, 0, addr, -1, addrA, len, NULL, NULL );
1590 ret = inet_pton( family, addrA, buffer );
1591 if (!ret) SetLastError( WSAEINVAL );
1593 free( addrA );
1594 return ret;
1597 /***********************************************************************
1598 * InetNtopW (ws2_32.@)
1600 const WCHAR * WINAPI InetNtopW( int family, void *addr, WCHAR *buffer, SIZE_T len )
1602 char bufferA[INET6_ADDRSTRLEN];
1603 PWSTR ret = NULL;
1605 TRACE( "family %d, addr %p, buffer %p, len %ld\n", family, addr, buffer, len );
1607 if (inet_ntop( family, addr, bufferA, sizeof(bufferA) ))
1609 if (MultiByteToWideChar( CP_ACP, 0, bufferA, -1, buffer, len ))
1610 ret = buffer;
1611 else
1612 SetLastError( ERROR_INVALID_PARAMETER );
1614 return ret;
1618 /***********************************************************************
1619 * WSAStringToAddressA (ws2_32.@)
1621 int WINAPI WSAStringToAddressA( char *string, int family, WSAPROTOCOL_INFOA *protocol_info,
1622 struct sockaddr *addr, int *addr_len )
1624 NTSTATUS status;
1626 TRACE( "string %s, family %u\n", debugstr_a(string), family );
1628 if (!addr || !addr_len) return -1;
1630 if (!string)
1632 SetLastError( WSAEINVAL );
1633 return -1;
1636 if (protocol_info)
1637 FIXME( "ignoring protocol_info\n" );
1639 switch (family)
1641 case AF_INET:
1643 struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
1645 if (*addr_len < sizeof(struct sockaddr_in))
1647 *addr_len = sizeof(struct sockaddr_in);
1648 SetLastError( WSAEFAULT );
1649 return -1;
1651 memset( addr, 0, sizeof(struct sockaddr_in) );
1653 status = RtlIpv4StringToAddressExA( string, FALSE, &addr4->sin_addr, &addr4->sin_port );
1654 if (status != STATUS_SUCCESS)
1656 SetLastError( WSAEINVAL );
1657 return -1;
1659 addr4->sin_family = AF_INET;
1660 *addr_len = sizeof(struct sockaddr_in);
1661 return 0;
1663 case AF_INET6:
1665 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1667 if (*addr_len < sizeof(struct sockaddr_in6))
1669 *addr_len = sizeof(struct sockaddr_in6);
1670 SetLastError( WSAEFAULT );
1671 return -1;
1673 memset( addr, 0, sizeof(struct sockaddr_in6) );
1675 status = RtlIpv6StringToAddressExA( string, &addr6->sin6_addr, &addr6->sin6_scope_id, &addr6->sin6_port );
1676 if (status != STATUS_SUCCESS)
1678 SetLastError( WSAEINVAL );
1679 return -1;
1681 addr6->sin6_family = AF_INET6;
1682 *addr_len = sizeof(struct sockaddr_in6);
1683 return 0;
1685 default:
1686 /* According to MSDN, only AF_INET and AF_INET6 are supported. */
1687 TRACE( "Unsupported address family specified: %d.\n", family );
1688 SetLastError( WSAEINVAL );
1689 return -1;
1694 /***********************************************************************
1695 * WSAStringToAddressW (ws2_32.@)
1697 int WINAPI WSAStringToAddressW( WCHAR *string, int family, WSAPROTOCOL_INFOW *protocol_info,
1698 struct sockaddr *addr, int *addr_len )
1700 WSAPROTOCOL_INFOA infoA;
1701 WSAPROTOCOL_INFOA *protocol_infoA = NULL;
1702 int sizeA, ret;
1703 char *stringA;
1705 TRACE( "string %s, family %u\n", debugstr_w(string), family );
1707 if (!addr || !addr_len) return -1;
1709 if (protocol_info)
1711 protocol_infoA = &infoA;
1712 memcpy( protocol_infoA, protocol_info, FIELD_OFFSET( WSAPROTOCOL_INFOA, szProtocol ) );
1714 if (!WideCharToMultiByte( CP_ACP, 0, protocol_info->szProtocol, -1, protocol_infoA->szProtocol,
1715 sizeof(protocol_infoA->szProtocol), NULL, NULL ))
1717 SetLastError( WSAEINVAL );
1718 return -1;
1722 if (!string)
1724 SetLastError( WSAEINVAL );
1725 return -1;
1728 sizeA = WideCharToMultiByte( CP_ACP, 0, string, -1, NULL, 0, NULL, NULL );
1729 if (!(stringA = malloc( sizeA )))
1731 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1732 return -1;
1734 WideCharToMultiByte( CP_ACP, 0, string, -1, stringA, sizeA, NULL, NULL );
1735 ret = WSAStringToAddressA( stringA, family, protocol_infoA, addr, addr_len );
1736 free( stringA );
1737 return ret;
1741 /***********************************************************************
1742 * WSAAddressToStringA (ws2_32.@)
1744 int WINAPI WSAAddressToStringA( struct sockaddr *addr, DWORD addr_len,
1745 WSAPROTOCOL_INFOA *info, char *string, DWORD *string_len )
1747 char buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
1748 DWORD size;
1750 TRACE( "addr %s\n", debugstr_sockaddr(addr) );
1752 if (!addr) return SOCKET_ERROR;
1753 if (!string || !string_len) return SOCKET_ERROR;
1755 switch (addr->sa_family)
1757 case AF_INET:
1759 const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
1760 unsigned int long_ip = ntohl( addr4->sin_addr.s_addr );
1761 char *p;
1763 if (addr_len < sizeof(struct sockaddr_in)) return -1;
1764 sprintf( buffer, "%u.%u.%u.%u:%u",
1765 (long_ip >> 24) & 0xff,
1766 (long_ip >> 16) & 0xff,
1767 (long_ip >> 8) & 0xff,
1768 long_ip & 0xff,
1769 ntohs( addr4->sin_port ) );
1771 p = strchr( buffer, ':' );
1772 if (!addr4->sin_port) *p = 0;
1773 break;
1775 case AF_INET6:
1777 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
1778 size_t len;
1780 buffer[0] = 0;
1781 if (addr_len < sizeof(struct sockaddr_in6)) return -1;
1782 if (addr6->sin6_port)
1783 strcpy( buffer, "[" );
1784 len = strlen( buffer );
1785 if (!inet_ntop( AF_INET6, &addr6->sin6_addr, &buffer[len], sizeof(buffer) - len ))
1787 SetLastError( WSAEINVAL );
1788 return -1;
1790 if (addr6->sin6_scope_id)
1791 sprintf( buffer + strlen( buffer ), "%%%u", addr6->sin6_scope_id );
1792 if (addr6->sin6_port)
1793 sprintf( buffer + strlen( buffer ), "]:%u", ntohs( addr6->sin6_port ) );
1794 break;
1797 default:
1798 SetLastError( WSAEINVAL );
1799 return -1;
1802 size = strlen( buffer ) + 1;
1804 if (*string_len < size)
1806 *string_len = size;
1807 SetLastError( WSAEFAULT );
1808 return -1;
1811 TRACE( "=> %s, %u bytes\n", debugstr_a(buffer), size );
1812 *string_len = size;
1813 strcpy( string, buffer );
1814 return 0;
1818 /***********************************************************************
1819 * WSAAddressToStringW (ws2_32.@)
1821 int WINAPI WSAAddressToStringW( struct sockaddr *addr, DWORD addr_len,
1822 WSAPROTOCOL_INFOW *info, WCHAR *string, DWORD *string_len )
1824 INT ret;
1825 char buf[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
1827 TRACE( "(%p, %d, %p, %p, %p)\n", addr, addr_len, info, string, string_len );
1829 if ((ret = WSAAddressToStringA( addr, addr_len, NULL, buf, string_len ))) return ret;
1831 MultiByteToWideChar( CP_ACP, 0, buf, *string_len, string, *string_len );
1832 TRACE( "=> %s, %u chars\n", debugstr_w(string), *string_len );
1833 return 0;
1837 /***********************************************************************
1838 * inet_addr (ws2_32.11)
1840 u_long WINAPI inet_addr( const char *str )
1842 u_long addr;
1844 if (inet_pton( AF_INET, str, &addr ) == 1)
1845 return addr;
1846 return INADDR_NONE;
1850 /***********************************************************************
1851 * htonl (ws2_32.8)
1853 u_long WINAPI WS_htonl( u_long hostlong )
1855 return htonl( hostlong );
1859 /***********************************************************************
1860 * htons (ws2_32.9)
1862 u_short WINAPI WS_htons( u_short hostshort )
1864 return htons( hostshort );
1868 /***********************************************************************
1869 * WSAHtonl (ws2_32.@)
1871 int WINAPI WSAHtonl( SOCKET s, u_long hostlong, u_long *netlong )
1873 if (netlong)
1875 *netlong = htonl( hostlong );
1876 return 0;
1878 SetLastError( WSAEFAULT );
1879 return -1;
1883 /***********************************************************************
1884 * WSAHtons (ws2_32.@)
1886 int WINAPI WSAHtons( SOCKET s, u_short hostshort, u_short *netshort )
1888 if (netshort)
1890 *netshort = htons( hostshort );
1891 return 0;
1893 SetLastError( WSAEFAULT );
1894 return -1;
1898 /***********************************************************************
1899 * ntohl (ws2_32.14)
1901 u_long WINAPI WS_ntohl( u_long netlong )
1903 return ntohl( netlong );
1907 /***********************************************************************
1908 * ntohs (ws2_32.15)
1910 u_short WINAPI WS_ntohs( u_short netshort )
1912 return ntohs( netshort );
1916 /***********************************************************************
1917 * WSANtohl (ws2_32.@)
1919 int WINAPI WSANtohl( SOCKET s, u_long netlong, u_long *hostlong )
1921 if (!hostlong) return WSAEFAULT;
1923 *hostlong = ntohl( netlong );
1924 return 0;
1928 /***********************************************************************
1929 * WSANtohs (ws2_32.@)
1931 int WINAPI WSANtohs( SOCKET s, u_short netshort, u_short *hostshort )
1933 if (!hostshort) return WSAEFAULT;
1935 *hostshort = ntohs( netshort );
1936 return 0;
1940 /***********************************************************************
1941 * WSAInstallServiceClassA (ws2_32.@)
1943 int WINAPI WSAInstallServiceClassA( WSASERVICECLASSINFOA *info )
1945 FIXME( "Request to install service %s\n", debugstr_a(info->lpszServiceClassName) );
1946 SetLastError( WSAEACCES );
1947 return -1;
1951 /***********************************************************************
1952 * WSAInstallServiceClassW (ws2_32.@)
1954 int WINAPI WSAInstallServiceClassW( WSASERVICECLASSINFOW *info )
1956 FIXME( "Request to install service %s\n", debugstr_w(info->lpszServiceClassName) );
1957 SetLastError( WSAEACCES );
1958 return -1;
1962 /***********************************************************************
1963 * WSARemoveServiceClass (ws2_32.@)
1965 int WINAPI WSARemoveServiceClass( GUID *info )
1967 FIXME( "Request to remove service %s\n", debugstr_guid(info) );
1968 SetLastError( WSATYPE_NOT_FOUND );
1969 return -1;
1973 /***********************************************************************
1974 * WSAGetServiceClassInfoA (ws2_32.@)
1976 int WINAPI WSAGetServiceClassInfoA( GUID *provider, GUID *service, DWORD *len,
1977 WSASERVICECLASSINFOA *info )
1979 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service), len, info );
1980 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1981 return -1;
1985 /***********************************************************************
1986 * WSAGetServiceClassInfoW (ws2_32.@)
1988 int WINAPI WSAGetServiceClassInfoW( GUID *provider, GUID *service, DWORD *len,
1989 WSASERVICECLASSINFOW *info )
1991 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider), debugstr_guid(service), len, info );
1992 SetLastError( WSA_NOT_ENOUGH_MEMORY );
1993 return -1;
1997 /***********************************************************************
1998 * WSAGetServiceClassNameByClassIdA (ws2_32.@)
2000 int WINAPI WSAGetServiceClassNameByClassIdA( GUID *class, char *service, DWORD *len )
2002 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
2003 SetLastError( WSA_NOT_ENOUGH_MEMORY );
2004 return -1;
2008 /***********************************************************************
2009 * WSAGetServiceClassNameByClassIdW (ws2_32.@)
2011 int WINAPI WSAGetServiceClassNameByClassIdW( GUID *class, WCHAR *service, DWORD *len )
2013 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service, len );
2014 SetLastError( WSA_NOT_ENOUGH_MEMORY );
2015 return -1;
2019 /***********************************************************************
2020 * WSALookupServiceBeginA (ws2_32.@)
2022 int WINAPI WSALookupServiceBeginA( WSAQUERYSETA *query, DWORD flags, HANDLE *lookup )
2024 FIXME( "(%p 0x%08x %p) Stub!\n", query, flags, lookup );
2025 SetLastError( WSA_NOT_ENOUGH_MEMORY );
2026 return -1;
2030 /***********************************************************************
2031 * WSALookupServiceBeginW (ws2_32.@)
2033 int WINAPI WSALookupServiceBeginW( WSAQUERYSETW *query, DWORD flags, HANDLE *lookup )
2035 FIXME( "(%p 0x%08x %p) Stub!\n", query, flags, lookup );
2036 SetLastError( WSA_NOT_ENOUGH_MEMORY );
2037 return -1;
2041 /***********************************************************************
2042 * WSALookupServiceEnd (ws2_32.@)
2044 int WINAPI WSALookupServiceEnd( HANDLE lookup )
2046 FIXME("(%p) Stub!\n", lookup );
2047 return 0;
2051 /***********************************************************************
2052 * WSALookupServiceNextA (ws2_32.@)
2054 int WINAPI WSALookupServiceNextA( HANDLE lookup, DWORD flags, DWORD *len, WSAQUERYSETA *results )
2056 FIXME( "(%p 0x%08x %p %p) Stub!\n", lookup, flags, len, results );
2057 SetLastError( WSA_E_NO_MORE );
2058 return -1;
2062 /***********************************************************************
2063 * WSALookupServiceNextW (ws2_32.@)
2065 int WINAPI WSALookupServiceNextW( HANDLE lookup, DWORD flags, DWORD *len, WSAQUERYSETW *results )
2067 FIXME( "(%p 0x%08x %p %p) Stub!\n", lookup, flags, len, results );
2068 SetLastError( WSA_E_NO_MORE );
2069 return -1;
2073 /***********************************************************************
2074 * WSASetServiceA (ws2_32.@)
2076 int WINAPI WSASetServiceA( WSAQUERYSETA *query, WSAESETSERVICEOP operation, DWORD flags )
2078 FIXME( "(%p 0x%08x 0x%08x) Stub!\n", query, operation, flags );
2079 return 0;
2083 /***********************************************************************
2084 * WSASetServiceW (ws2_32.@)
2086 int WINAPI WSASetServiceW( WSAQUERYSETW *query, WSAESETSERVICEOP operation, DWORD flags )
2088 FIXME( "(%p 0x%08x 0x%08x) Stub!\n", query, operation, flags );
2089 return 0;
2093 /***********************************************************************
2094 * WSAEnumNameSpaceProvidersA (ws2_32.@)
2096 int WINAPI WSAEnumNameSpaceProvidersA( DWORD *len, WSANAMESPACE_INFOA *buffer )
2098 FIXME( "(%p %p) Stub!\n", len, buffer );
2099 return 0;
2103 /***********************************************************************
2104 * WSAEnumNameSpaceProvidersW (ws2_32.@)
2106 int WINAPI WSAEnumNameSpaceProvidersW( DWORD *len, WSANAMESPACE_INFOW *buffer )
2108 FIXME( "(%p %p) Stub!\n", len, buffer );
2109 return 0;
2113 /***********************************************************************
2114 * WSAProviderConfigChange (ws2_32.@)
2116 int WINAPI WSAProviderConfigChange( HANDLE *handle, OVERLAPPED *overlapped,
2117 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion )
2119 FIXME( "(%p %p %p) Stub!\n", handle, overlapped, completion );
2120 return -1;
2124 /***********************************************************************
2125 * WSANSPIoctl (ws2_32.@)
2127 int WINAPI WSANSPIoctl( HANDLE lookup, DWORD code, void *in_buffer,
2128 DWORD in_size, void *out_buffer, DWORD out_size,
2129 DWORD *ret_size, WSACOMPLETION *completion )
2131 FIXME( "(%p, 0x%08x, %p, 0x%08x, %p, 0x%08x, %p, %p) Stub!\n", lookup, code,
2132 in_buffer, in_size, out_buffer, out_size, ret_size, completion );
2133 SetLastError( WSA_NOT_ENOUGH_MEMORY );
2134 return -1;
2138 /***********************************************************************
2139 * WSCEnableNSProvider (ws2_32.@)
2141 int WINAPI WSCEnableNSProvider( GUID *provider, BOOL enable )
2143 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
2144 return 0;
2148 /***********************************************************************
2149 * WSCGetProviderInfo (ws2_32.@)
2151 int WINAPI WSCGetProviderInfo( GUID *provider, WSC_PROVIDER_INFO_TYPE info_type,
2152 BYTE *info, size_t *len, DWORD flags, int *errcode )
2154 FIXME( "(%s 0x%08x %p %p 0x%08x %p) Stub!\n",
2155 debugstr_guid(provider), info_type, info, len, flags, errcode );
2157 if (!errcode)
2158 return -1;
2160 if (!provider)
2162 *errcode = WSAEFAULT;
2163 return -1;
2166 *errcode = WSANO_RECOVERY;
2167 return -1;
2171 /***********************************************************************
2172 * WSCGetProviderPath (ws2_32.@)
2174 int WINAPI WSCGetProviderPath( GUID *provider, WCHAR *path, int *len, int *errcode )
2176 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider), path, len, errcode );
2178 if (!provider || !len)
2180 if (errcode)
2181 *errcode = WSAEFAULT;
2182 return -1;
2185 if (*len <= 0)
2187 if (errcode)
2188 *errcode = WSAEINVAL;
2189 return -1;
2192 return 0;
2196 /***********************************************************************
2197 * WSCInstallNameSpace (ws2_32.@)
2199 int WINAPI WSCInstallNameSpace( WCHAR *identifier, WCHAR *path, DWORD namespace,
2200 DWORD version, GUID *provider )
2202 FIXME( "(%s %s 0x%08x 0x%08x %s) Stub!\n", debugstr_w(identifier), debugstr_w(path),
2203 namespace, version, debugstr_guid(provider) );
2204 return 0;
2208 /***********************************************************************
2209 * WSCUnInstallNameSpace (ws2_32.@)
2211 int WINAPI WSCUnInstallNameSpace( GUID *provider )
2213 FIXME( "(%s) Stub!\n", debugstr_guid(provider) );
2214 return NO_ERROR;
2218 /***********************************************************************
2219 * WSCWriteProviderOrder (ws2_32.@)
2221 int WINAPI WSCWriteProviderOrder( DWORD *entry, DWORD number )
2223 FIXME( "(%p 0x%08x) Stub!\n", entry, number );
2224 return 0;
2228 /***********************************************************************
2229 * WSCInstallProvider (ws2_32.@)
2231 int WINAPI WSCInstallProvider( GUID *provider, const WCHAR *path,
2232 WSAPROTOCOL_INFOW *protocol_info, DWORD count, int *err )
2234 FIXME( "(%s, %s, %p, %d, %p): stub !\n", debugstr_guid(provider),
2235 debugstr_w(path), protocol_info, count, err );
2236 *err = 0;
2237 return 0;
2241 /***********************************************************************
2242 * WSCDeinstallProvider (ws2_32.@)
2244 int WINAPI WSCDeinstallProvider( GUID *provider, int *err )
2246 FIXME( "(%s, %p): stub !\n", debugstr_guid(provider), err );
2247 *err = 0;
2248 return 0;
2252 /***********************************************************************
2253 * WSCSetApplicationCategory (ws2_32.@)
2255 int WINAPI WSCSetApplicationCategory( const WCHAR *path, DWORD len, const WCHAR *extra, DWORD extralen,
2256 DWORD lspcat, DWORD *prev_lspcat, int *err )
2258 FIXME( "(%s %d %s %d %d %p) Stub!\n", debugstr_w(path), len, debugstr_w(extra),
2259 extralen, lspcat, prev_lspcat );
2260 return 0;
2264 /***********************************************************************
2265 * WSCEnumProtocols (ws2_32.@)
2267 int WINAPI WSCEnumProtocols( int *protocols, WSAPROTOCOL_INFOW *info, DWORD *len, int *err )
2269 int ret = WSAEnumProtocolsW( protocols, info, len );
2271 if (ret == SOCKET_ERROR) *err = WSAENOBUFS;
2273 return ret;