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)
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
))
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
};
60 if (!(params
.info
= malloc( size
)))
61 return WSA_NOT_ENOUGH_MEMORY
;
62 if (!(ret
= WS_CALL( getaddrinfo
, ¶ms
)))
68 if (ret
!= ERROR_INSUFFICIENT_BUFFER
) return ret
;
72 static int dns_only_query( const char *node
, const struct addrinfo
*hints
, struct addrinfo
**result
)
75 DNS_RECORDA
*rec
= NULL
, *rec6
= NULL
, *ptr
;
76 struct addrinfo
*info
, *next
;
77 struct sockaddr_in
*addr
;
78 struct sockaddr_in6
*addr6
;
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
);
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
);
101 for (ptr
= rec
; ptr
; ptr
= ptr
->pNext
) count
++;
102 for (ptr
= rec6
; ptr
; ptr
= ptr
->pNext
) 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
;
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
;
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
;
146 DnsRecordListFree( (DNS_RECORD
*)rec
, DnsFreeRecordList
);
147 DnsRecordListFree( (DNS_RECORD
*)rec6
, DnsFreeRecordList
);
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
;
160 TRACE( "node %s, service %s, hints %p\n", debugstr_a(node
), debugstr_a(service
), hints
);
164 if (!node
&& !service
)
166 SetLastError( WSAHOST_NOT_FOUND
);
167 return WSAHOST_NOT_FOUND
;
174 if (!(fqdn
= get_fqdn())) return WSA_NOT_ENOUGH_MEMORY
;
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
);
182 else if (!hints
|| hints
->ai_family
== AF_UNSPEC
|| hints
->ai_family
== AF_INET6
)
184 /* [ipv6] or [ipv6]:portnumber are supported by Windows */
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
);
197 ret
= do_getaddrinfo( node
, service
, hints
, info
);
199 if (ret
&& (!hints
|| !(hints
->ai_flags
& AI_NUMERICHOST
)) && node
)
201 if (!fqdn
&& !(fqdn
= get_fqdn()))
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
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
);
226 if (!ret
&& TRACE_ON(winsock
))
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
) );
243 static ADDRINFOEXW
*addrinfo_AtoW( const struct addrinfo
*ai
)
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
;
257 ret
->ai_provider
= 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
) )))
267 MultiByteToWideChar( CP_ACP
, 0, ai
->ai_canonname
, -1, ret
->ai_canonname
, len
);
271 if (!(ret
->ai_addr
= malloc( ai
->ai_addrlen
)))
273 free( ret
->ai_canonname
);
277 memcpy( ret
->ai_addr
, ai
->ai_addr
, ai
->ai_addrlen
);
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
);
294 infoW
= infoW
->ai_next
;
295 info
= info
->ai_next
;
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
;
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
)))
321 WideCharToMultiByte( CP_ACP
, 0, ai
->ai_canonname
, -1, ret
->ai_canonname
, len
, NULL
, NULL
);
325 if (!(ret
->ai_addr
= malloc( sizeof(struct sockaddr
) )))
327 free( ret
->ai_canonname
);
331 memcpy( ret
->ai_addr
, ai
->ai_addr
, sizeof(struct sockaddr
) );
336 struct getaddrinfo_args
338 OVERLAPPED
*overlapped
;
339 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine
;
340 ADDRINFOEXW
**result
;
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
;
355 ret
= getaddrinfo( args
->nodename
, args
->servname
, args
->hints
, &res
);
358 *args
->result
= addrinfo_list_AtoW(res
);
359 overlapped
->u
.Pointer
= args
->result
;
363 free( args
->nodename
);
364 free( args
->servname
);
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
;
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')
394 if (hints
&& (hints
->ai_flags
& AI_DISABLE_IDN_ENCODING
))
396 /* Name requires conversion but it was disabled */
397 ret
= WSAHOST_NOT_FOUND
;
402 len
= IdnToAscii( 0, nodename
, -1, NULL
, 0 );
405 ERR("Failed to convert %s to punycode\n", debugstr_w(nodename
));
409 if (!(local_nodenameW
= malloc( len
* sizeof(WCHAR
) ))) goto end
;
410 IdnToAscii( 0, nodename
, -1, local_nodenameW
, len
);
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
);
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
);
428 struct getaddrinfo_args
*args
;
430 if (overlapped
->hEvent
&& completion_routine
)
436 if (!(args
= malloc( sizeof(*args
) + sizeof(*args
->hints
) ))) goto end
;
437 args
->overlapped
= overlapped
;
438 args
->completion_routine
= completion_routine
;
440 args
->nodename
= nodenameA
;
441 args
->servname
= servnameA
;
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
))
456 ret
= GetLastError();
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
);
469 *res
= addrinfo_list_AtoW( resA
);
470 freeaddrinfo( resA
);
474 if (local_nodenameW
!= nodename
)
475 free( local_nodenameW
);
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
)
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 );
498 FIXME( "Unsupported namespace_id %s\n", debugstr_guid(namespace_id
) );
500 FIXME( "Unsupported timeout\n" );
502 FIXME( "Unsupported cancel handle\n" );
504 ret
= getaddrinfoW( name
, servname
, (struct addrinfo
*)hints
, result
, overlapped
, completion_routine
);
506 if (handle
) *handle
= (HANDLE
)0xdeadbeef;
511 /***********************************************************************
512 * GetAddrInfoExOverlappedResult (ws2_32.@)
514 int WINAPI
GetAddrInfoExOverlappedResult( OVERLAPPED
*overlapped
)
516 TRACE( "(%p)\n", overlapped
);
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
;
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
);
548 if (hints
) hintsA
= addrinfo_WtoA( hints
);
549 ret
= getaddrinfoW( nodename
, servname
, hintsA
, &resex
, NULL
, NULL
);
550 freeaddrinfo( hintsA
);
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
;
568 /***********************************************************************
569 * freeaddrinfo (ws2_32.@)
571 void WINAPI
freeaddrinfo( struct addrinfo
*info
)
573 TRACE( "%p\n", info
);
579 /***********************************************************************
580 * FreeAddrInfoW (ws2_32.@)
582 void WINAPI
FreeAddrInfoW( ADDRINFOW
*ai
)
587 free( ai
->ai_canonname
);
596 /***********************************************************************
597 * FreeAddrInfoEx (ws2_32.@)
599 void WINAPI
FreeAddrInfoEx( ADDRINFOEXA
*ai
)
601 TRACE( "(%p)\n", ai
);
606 free( ai
->ai_canonname
);
615 /***********************************************************************
616 * FreeAddrInfoExW (ws2_32.@)
618 void WINAPI
FreeAddrInfoExW( ADDRINFOEXW
*ai
)
620 TRACE( "(%p)\n", ai
);
625 free( ai
->ai_canonname
);
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
, ¶ms
);
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
)
656 char *hostA
= NULL
, *servA
= NULL
;
658 if (host
&& !(hostA
= malloc( host_len
)))
660 if (serv
&& !(servA
= malloc( serv_len
)))
666 ret
= getnameinfo( addr
, addr_len
, hostA
, host_len
, servA
, serv_len
, flags
);
669 if (host
) MultiByteToWideChar( CP_ACP
, 0, hostA
, -1, host
, host_len
);
670 if (serv
) MultiByteToWideChar( CP_ACP
, 0, servA
, -1, serv
, serv_len
);
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
);
691 data
->he_buffer
= new_buffer
;
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
;
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).
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
};
763 if (!(params
.host
= get_hostent_buffer( size
)))
766 if ((ret
= WS_CALL( gethostbyaddr
, ¶ms
)) != ERROR_INSUFFICIENT_BUFFER
)
771 return ret
? NULL
: params
.host
;
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
)
789 if (b
->default_route
&& !a
->default_route
)
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
)
815 if (GetIpForwardTable( NULL
, &route_size
, FALSE
) != ERROR_INSUFFICIENT_BUFFER
)
818 adapters
= malloc( adap_size
);
819 routes
= malloc( route_size
);
820 if (!adapters
|| !routes
)
823 /* Obtain the adapter list and the full routing table */
824 if (GetAdaptersInfo( adapters
, &adap_size
) != NO_ERROR
)
826 if (GetIpForwardTable( routes
, &route_size
, FALSE
) != NO_ERROR
)
829 /* Store the interface associated with each route */
830 for (n
= 0; n
< routes
->dwNumEntries
; n
++)
833 DWORD ifmetric
, ifdefault
= 0;
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
)
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
;
855 route_addrs
= realloc( route_addrs
, (numroutes
+ 1) * sizeof(struct route
) );
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 );
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
)
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).
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
;
911 /***********************************************************************
912 * gethostbyname (ws2_32.52)
914 struct hostent
* WINAPI
gethostbyname( const char *name
)
916 struct hostent
*host
= NULL
;
918 struct gethostname_params params
= { hostname
, sizeof(hostname
) };
921 TRACE( "%s\n", debugstr_a(name
) );
925 SetLastError( WSANOTINITIALISED
);
929 if ((ret
= WS_CALL( gethostname
, ¶ms
)))
935 if (!name
|| !name
[0])
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 */
947 unsigned int size
= 1024;
948 struct gethostbyname_params params
= { name
, NULL
, &size
};
953 if (!(params
.host
= get_hostent_buffer( size
)))
956 if ((ret
= WS_CALL( gethostbyname
, ¶ms
)) != ERROR_INSUFFICIENT_BUFFER
)
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
968 memcpy( host
->h_addr_list
[0], magic_loopback_addr
, 4 );
975 /***********************************************************************
976 * gethostname (ws2_32.57)
978 int WINAPI
gethostname( char *name
, int namelen
)
981 struct gethostname_params params
= { buf
, sizeof(buf
) };
984 TRACE( "name %p, len %d\n", name
, namelen
);
988 SetLastError( WSAEFAULT
);
992 if ((ret
= WS_CALL( gethostname
, ¶ms
)))
998 TRACE( "<- %s\n", debugstr_a(buf
) );
1001 WARN( "Windows supports NetBIOS name length up to 15 bytes!\n" );
1004 SetLastError( WSAEFAULT
);
1007 strcpy( name
, buf
);
1012 /***********************************************************************
1013 * GetHostNameW (ws2_32.@)
1015 int WINAPI
GetHostNameW( WCHAR
*name
, int namelen
)
1018 struct gethostname_params params
= { buf
, sizeof(buf
) };
1021 TRACE( "name %p, len %d\n", name
, namelen
);
1025 SetLastError( WSAEFAULT
);
1029 if ((ret
= WS_CALL( gethostname
, ¶ms
)))
1031 SetLastError( ret
);
1035 if (MultiByteToWideChar( CP_ACP
, 0, buf
, -1, NULL
, 0 ) > namelen
)
1037 SetLastError( WSAEFAULT
);
1040 MultiByteToWideChar( CP_ACP
, 0, buf
, -1, name
, namelen
);
1045 static char *read_etc_file( const WCHAR
*filename
, DWORD
*ret_size
)
1047 WCHAR path
[MAX_PATH
];
1048 DWORD size
= sizeof(path
);
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
);
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() );
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() );
1076 CloseHandle( file
);
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
))
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
))
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
);
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
;
1124 const char *line_end
, *next_line
;
1125 size_t needed_size
, line_len
;
1126 unsigned int alias_count
= 0;
1127 struct protoent
*proto
;
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
);
1148 /* parse the name */
1151 line_len
= line_end
- name
;
1153 p
= next_space( p
, line_end
);
1160 p
= next_non_space( p
, line_end
);
1162 /* parse the number */
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
)
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
);
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
;
1197 q
= next_space( q
, line_end
);
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
);
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
;
1218 SetLastError( WSANO_DATA
);
1223 /***********************************************************************
1224 * getprotobyname (ws2_32.53)
1226 struct protoent
* WINAPI
getprotobyname( const char *name
)
1228 struct protoent
*proto
;
1233 TRACE( "%s\n", debugstr_a(name
) );
1235 if (!(file
= read_etc_file( L
"protocol", &size
)))
1237 SetLastError( WSANO_DATA
);
1242 while ((proto
= get_next_protocol( &cursor
, file
+ size
)))
1244 if (!strcasecmp( proto
->p_name
, name
))
1253 /***********************************************************************
1254 * getprotobynumber (ws2_32.54)
1256 struct protoent
* WINAPI
getprotobynumber( int number
)
1258 struct protoent
*proto
;
1263 TRACE( "%d\n", number
);
1265 if (!(file
= read_etc_file( L
"protocol", &size
)))
1267 SetLastError( WSANO_DATA
);
1272 while ((proto
= get_next_protocol( &cursor
, file
+ size
)))
1274 if (proto
->p_proto
== number
)
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
);
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
;
1310 const char *line_end
, *next_line
;
1311 size_t needed_size
, line_len
;
1312 unsigned int alias_count
= 0;
1313 struct servent
*serv
;
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
);
1334 /* parse the name */
1337 line_len
= line_end
- name
;
1339 p
= next_space( p
, line_end
);
1346 p
= next_non_space( p
, line_end
);
1348 /* parse the port */
1351 p
= memchr( p
, '/', line_end
- p
);
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
)
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
);
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
;
1389 q
= next_space( q
, line_end
);
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
);
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
;
1413 SetLastError( WSANO_DATA
);
1418 /***********************************************************************
1419 * getservbyname (ws2_32.55)
1421 struct servent
* WINAPI
getservbyname( const char *name
, const char *proto
)
1423 struct servent
*serv
;
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
);
1437 while ((serv
= get_next_service( &cursor
, file
+ size
)))
1439 if (!strcasecmp( serv
->s_name
, name
) && (!proto
|| !strcasecmp( serv
->s_proto
, proto
)))
1448 /***********************************************************************
1449 * getservbyport (ws2_32.56)
1451 struct servent
* WINAPI
getservbyport( int port
, const char *proto
)
1453 struct servent
*serv
;
1458 TRACE( "port %d, proto %s\n", port
, debugstr_a(proto
) );
1460 if (!(file
= read_etc_file( L
"services", &size
)))
1462 SetLastError( WSANO_DATA
);
1467 while ((serv
= get_next_service( &cursor
, file
+ size
)))
1469 if (serv
->s_port
== port
&& (!proto
|| !strcasecmp( serv
->s_proto
, proto
)))
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,
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
)
1502 ULONG size
= min( len
, (ULONG
)-1 );
1504 TRACE( "family %d, addr %p, buffer %p, len %ld\n", family
, addr
, buffer
, len
);
1507 SetLastError( STATUS_INVALID_PARAMETER
);
1515 status
= RtlIpv4AddressToStringExA( (IN_ADDR
*)addr
, 0, buffer
, &size
);
1520 status
= RtlIpv6AddressToStringExA( (IN6_ADDR
*)addr
, 0, 0, buffer
, &size
);
1524 SetLastError( WSAEAFNOSUPPORT
);
1528 if (status
== STATUS_SUCCESS
) return buffer
;
1529 SetLastError( STATUS_INVALID_PARAMETER
);
1533 /***********************************************************************
1534 * inet_pton (ws2_32.@)
1536 int WINAPI
inet_pton( int family
, const char *addr
, void *buffer
)
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
);
1552 status
= RtlIpv4StringToAddressA(addr
, TRUE
, &terminator
, buffer
);
1555 status
= RtlIpv6StringToAddressA(addr
, &terminator
, buffer
);
1558 SetLastError( WSAEAFNOSUPPORT
);
1562 return (status
== STATUS_SUCCESS
&& *terminator
== 0);
1565 /***********************************************************************
1566 * InetPtonW (ws2_32.@)
1568 int WINAPI
InetPtonW( int family
, const WCHAR
*addr
, void *buffer
)
1574 TRACE( "family %d, addr %s, buffer %p\n", family
, debugstr_w(addr
), buffer
);
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
);
1588 WideCharToMultiByte( CP_ACP
, 0, addr
, -1, addrA
, len
, NULL
, NULL
);
1590 ret
= inet_pton( family
, addrA
, buffer
);
1591 if (!ret
) SetLastError( WSAEINVAL
);
1597 /***********************************************************************
1598 * InetNtopW (ws2_32.@)
1600 const WCHAR
* WINAPI
InetNtopW( int family
, void *addr
, WCHAR
*buffer
, SIZE_T len
)
1602 char bufferA
[INET6_ADDRSTRLEN
];
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
))
1612 SetLastError( ERROR_INVALID_PARAMETER
);
1618 /***********************************************************************
1619 * WSAStringToAddressA (ws2_32.@)
1621 int WINAPI
WSAStringToAddressA( char *string
, int family
, WSAPROTOCOL_INFOA
*protocol_info
,
1622 struct sockaddr
*addr
, int *addr_len
)
1626 TRACE( "string %s, family %u\n", debugstr_a(string
), family
);
1628 if (!addr
|| !addr_len
) return -1;
1632 SetLastError( WSAEINVAL
);
1637 FIXME( "ignoring protocol_info\n" );
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
);
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
);
1659 addr4
->sin_family
= AF_INET
;
1660 *addr_len
= sizeof(struct sockaddr_in
);
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
);
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
);
1681 addr6
->sin6_family
= AF_INET6
;
1682 *addr_len
= sizeof(struct sockaddr_in6
);
1686 /* According to MSDN, only AF_INET and AF_INET6 are supported. */
1687 TRACE( "Unsupported address family specified: %d.\n", family
);
1688 SetLastError( WSAEINVAL
);
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
;
1705 TRACE( "string %s, family %u\n", debugstr_w(string
), family
);
1707 if (!addr
|| !addr_len
) return -1;
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
);
1724 SetLastError( WSAEINVAL
);
1728 sizeA
= WideCharToMultiByte( CP_ACP
, 0, string
, -1, NULL
, 0, NULL
, NULL
);
1729 if (!(stringA
= malloc( sizeA
)))
1731 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
1734 WideCharToMultiByte( CP_ACP
, 0, string
, -1, stringA
, sizeA
, NULL
, NULL
);
1735 ret
= WSAStringToAddressA( stringA
, family
, protocol_infoA
, addr
, addr_len
);
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' */
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
)
1759 const struct sockaddr_in
*addr4
= (const struct sockaddr_in
*)addr
;
1760 unsigned int long_ip
= ntohl( addr4
->sin_addr
.s_addr
);
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,
1769 ntohs( addr4
->sin_port
) );
1771 p
= strchr( buffer
, ':' );
1772 if (!addr4
->sin_port
) *p
= 0;
1777 struct sockaddr_in6
*addr6
= (struct sockaddr_in6
*)addr
;
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
);
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
) );
1798 SetLastError( WSAEINVAL
);
1802 size
= strlen( buffer
) + 1;
1804 if (*string_len
< size
)
1807 SetLastError( WSAEFAULT
);
1811 TRACE( "=> %s, %u bytes\n", debugstr_a(buffer
), size
);
1813 strcpy( string
, buffer
);
1818 /***********************************************************************
1819 * WSAAddressToStringW (ws2_32.@)
1821 int WINAPI
WSAAddressToStringW( struct sockaddr
*addr
, DWORD addr_len
,
1822 WSAPROTOCOL_INFOW
*info
, WCHAR
*string
, DWORD
*string_len
)
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
);
1837 /***********************************************************************
1838 * inet_addr (ws2_32.11)
1840 u_long WINAPI
inet_addr( const char *str
)
1844 if (inet_pton( AF_INET
, str
, &addr
) == 1)
1850 /***********************************************************************
1853 u_long WINAPI
WS_htonl( u_long hostlong
)
1855 return htonl( hostlong
);
1859 /***********************************************************************
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
)
1875 *netlong
= htonl( hostlong
);
1878 SetLastError( WSAEFAULT
);
1883 /***********************************************************************
1884 * WSAHtons (ws2_32.@)
1886 int WINAPI
WSAHtons( SOCKET s
, u_short hostshort
, u_short
*netshort
)
1890 *netshort
= htons( hostshort
);
1893 SetLastError( WSAEFAULT
);
1898 /***********************************************************************
1901 u_long WINAPI
WS_ntohl( u_long netlong
)
1903 return ntohl( netlong
);
1907 /***********************************************************************
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
2041 /***********************************************************************
2042 * WSALookupServiceEnd (ws2_32.@)
2044 int WINAPI
WSALookupServiceEnd( HANDLE lookup
)
2046 FIXME("(%p) Stub!\n", lookup
);
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
);
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
);
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
);
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
);
2093 /***********************************************************************
2094 * WSAEnumNameSpaceProvidersA (ws2_32.@)
2096 int WINAPI
WSAEnumNameSpaceProvidersA( DWORD
*len
, WSANAMESPACE_INFOA
*buffer
)
2098 FIXME( "(%p %p) Stub!\n", len
, buffer
);
2103 /***********************************************************************
2104 * WSAEnumNameSpaceProvidersW (ws2_32.@)
2106 int WINAPI
WSAEnumNameSpaceProvidersW( DWORD
*len
, WSANAMESPACE_INFOW
*buffer
)
2108 FIXME( "(%p %p) Stub!\n", len
, buffer
);
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
);
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
);
2138 /***********************************************************************
2139 * WSCEnableNSProvider (ws2_32.@)
2141 int WINAPI
WSCEnableNSProvider( GUID
*provider
, BOOL enable
)
2143 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider
), enable
);
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
);
2162 *errcode
= WSAEFAULT
;
2166 *errcode
= WSANO_RECOVERY
;
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
)
2181 *errcode
= WSAEFAULT
;
2188 *errcode
= WSAEINVAL
;
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
) );
2208 /***********************************************************************
2209 * WSCUnInstallNameSpace (ws2_32.@)
2211 int WINAPI
WSCUnInstallNameSpace( GUID
*provider
)
2213 FIXME( "(%s) Stub!\n", debugstr_guid(provider
) );
2218 /***********************************************************************
2219 * WSCWriteProviderOrder (ws2_32.@)
2221 int WINAPI
WSCWriteProviderOrder( DWORD
*entry
, DWORD number
)
2223 FIXME( "(%p 0x%08x) Stub!\n", entry
, number
);
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
);
2241 /***********************************************************************
2242 * WSCDeinstallProvider (ws2_32.@)
2244 int WINAPI
WSCDeinstallProvider( GUID
*provider
, int *err
)
2246 FIXME( "(%s, %p): stub !\n", debugstr_guid(provider
), err
);
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
);
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
;