2 * Protocol-level socket functions
4 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
5 * Copyright (C) 2001 Stefan Leichter
6 * Copyright (C) 2004 Hans Leidekker
7 * Copyright (C) 2005 Marcus Meissner
8 * Copyright (C) 2006-2008 Kai Blin
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "ws2_32_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(winsock
);
28 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
30 #define WS_CALL(func, params) WINE_UNIX_CALL( ws_unix_ ## func, params )
32 static char *get_fqdn(void)
37 GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified
, NULL
, &size
);
38 if (GetLastError() != ERROR_MORE_DATA
) return NULL
;
39 if (!(ret
= malloc( size
))) return NULL
;
40 if (!GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified
, ret
, &size
))
48 /* call Unix getaddrinfo, allocating a large enough buffer */
49 static int do_getaddrinfo( const char *node
, const char *service
,
50 const struct addrinfo
*hints
, struct addrinfo
**info
)
52 unsigned int size
= 1024;
53 struct getaddrinfo_params params
= { node
, service
, hints
, NULL
, &size
};
58 if (!(params
.info
= malloc( size
)))
59 return WSA_NOT_ENOUGH_MEMORY
;
60 if (!(ret
= WS_CALL( getaddrinfo
, ¶ms
)))
66 if (ret
!= ERROR_INSUFFICIENT_BUFFER
) return ret
;
70 static int dns_only_query( const char *node
, const struct addrinfo
*hints
, struct addrinfo
**result
)
73 DNS_RECORDA
*rec
= NULL
, *rec6
= NULL
, *ptr
;
74 struct addrinfo
*info
, *next
;
75 struct sockaddr_in
*addr
;
76 struct sockaddr_in6
*addr6
;
79 if (hints
->ai_family
!= AF_INET
&& hints
->ai_family
!= AF_INET6
&& hints
->ai_family
!= AF_UNSPEC
)
81 FIXME( "unsupported family %u\n", hints
->ai_family
);
84 if (hints
->ai_family
== AF_INET
|| hints
->ai_family
== AF_UNSPEC
)
86 status
= DnsQuery_A( node
, DNS_TYPE_A
, DNS_QUERY_NO_NETBT
| DNS_QUERY_NO_MULTICAST
, NULL
, &rec
, NULL
);
87 if (status
!= ERROR_SUCCESS
&& status
!= DNS_ERROR_RCODE_NAME_ERROR
) return EAI_FAIL
;
89 if (hints
->ai_family
== AF_INET6
|| hints
->ai_family
== AF_UNSPEC
)
91 status
= DnsQuery_A( node
, DNS_TYPE_AAAA
, DNS_QUERY_NO_NETBT
| DNS_QUERY_NO_MULTICAST
, NULL
, &rec6
, NULL
);
92 if (status
!= ERROR_SUCCESS
&& status
!= DNS_ERROR_RCODE_NAME_ERROR
)
94 DnsRecordListFree( (DNS_RECORD
*)rec
, DnsFreeRecordList
);
99 for (ptr
= rec
; ptr
; ptr
= ptr
->pNext
) { if (ptr
->wType
== DNS_TYPE_A
) count
++; };
100 for (ptr
= rec6
; ptr
; ptr
= ptr
->pNext
) { if (ptr
->wType
== DNS_TYPE_AAAA
) count
++; };
103 DnsRecordListFree( (DNS_RECORD
*)rec
, DnsFreeRecordList
);
104 DnsRecordListFree( (DNS_RECORD
*)rec6
, DnsFreeRecordList
);
105 return WSAHOST_NOT_FOUND
;
107 if (!(info
= calloc( count
, sizeof(*info
) + sizeof(SOCKADDR_STORAGE
) )))
109 DnsRecordListFree( (DNS_RECORD
*)rec
, DnsFreeRecordList
);
110 DnsRecordListFree( (DNS_RECORD
*)rec6
, DnsFreeRecordList
);
111 return WSA_NOT_ENOUGH_MEMORY
;
115 for (ptr
= rec
; ptr
; ptr
= ptr
->pNext
)
117 if (ptr
->wType
!= DNS_TYPE_A
) continue;
118 info
->ai_family
= AF_INET
;
119 info
->ai_socktype
= hints
->ai_socktype
;
120 info
->ai_protocol
= hints
->ai_protocol
;
121 info
->ai_addrlen
= sizeof(struct sockaddr_in
);
122 info
->ai_addr
= (struct sockaddr
*)(info
+ 1);
123 addr
= (struct sockaddr_in
*)info
->ai_addr
;
124 addr
->sin_family
= info
->ai_family
;
125 addr
->sin_addr
.S_un
.S_addr
= ptr
->Data
.A
.IpAddress
;
126 next
= (struct addrinfo
*)((char *)info
+ sizeof(*info
) + sizeof(SOCKADDR_STORAGE
));
127 if (--count
) info
->ai_next
= next
;
130 for (ptr
= rec6
; ptr
; ptr
= ptr
->pNext
)
132 if (ptr
->wType
!= DNS_TYPE_AAAA
) continue;
133 info
->ai_family
= AF_INET6
;
134 info
->ai_socktype
= hints
->ai_socktype
;
135 info
->ai_protocol
= hints
->ai_protocol
;
136 info
->ai_addrlen
= sizeof(struct sockaddr_in6
);
137 info
->ai_addr
= (struct sockaddr
*)(info
+ 1);
138 addr6
= (struct sockaddr_in6
*)info
->ai_addr
;
139 addr6
->sin6_family
= info
->ai_family
;
140 memcpy( &addr6
->sin6_addr
, &ptr
->Data
.AAAA
.Ip6Address
, sizeof(addr6
->sin6_addr
) );
141 next
= (struct addrinfo
*)((char *)info
+ sizeof(*info
) + sizeof(SOCKADDR_STORAGE
));
142 if (--count
) info
->ai_next
= next
;
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 %Id, name %s, addr %s\n",
233 ai
, ai
->ai_flags
, ai
->ai_family
, ai
->ai_socktype
, ai
->ai_protocol
, ai
->ai_addrlen
,
234 ai
->ai_canonname
, debugstr_sockaddr(ai
->ai_addr
) );
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 %lu, namespace_id %s)\n",
493 debugstr_w(name
), debugstr_w(servname
), namespace, debugstr_guid(namespace_id
) );
495 if (namespace != NS_DNS
)
496 FIXME( "Unsupported namespace %lu\n", namespace );
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 %lu, serv %p, serv_len %lu, flags %#x\n",
643 debugstr_sockaddr(addr
), addr_len
, host
, host_len
, serv
, serv_len
, flags
);
645 return WS_CALL( getnameinfo
, ¶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
, *new_route_addrs
;
810 DWORD adap_size
, route_size
, n
;
812 /* Obtain the size of the adapter list and routing table, also allocate memory */
813 if (GetAdaptersInfo( NULL
, &adap_size
) != ERROR_BUFFER_OVERFLOW
)
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 new_route_addrs
= realloc( route_addrs
, (numroutes
+ 1) * sizeof(struct route
) );
856 if (!new_route_addrs
)
858 route_addrs
= new_route_addrs
;
859 route_addrs
[numroutes
].interface
= ifindex
;
860 route_addrs
[numroutes
].metric
= ifmetric
;
861 route_addrs
[numroutes
].default_route
= ifdefault
;
862 /* If no IP is found in the next step (for whatever reason)
863 * then fall back to the magic loopback address.
865 memcpy( &route_addrs
[numroutes
].addr
.s_addr
, magic_loopback_addr
, 4 );
869 goto cleanup
; /* No routes, fall back to the Magic IP */
871 /* Find the IP address associated with each found interface */
872 for (i
= 0; i
< numroutes
; i
++)
874 for (k
= adapters
; k
!= NULL
; k
= k
->Next
)
876 char *ip
= k
->IpAddressList
.IpAddress
.String
;
878 if (route_addrs
[i
].interface
== k
->Index
)
879 route_addrs
[i
].addr
.s_addr
= inet_addr(ip
);
883 /* Allocate a hostent and enough memory for all the IPs,
884 * including the NULL at the end of the list.
886 hostlist
= create_hostent( hostname
, 1, 0, numroutes
+1, sizeof(struct in_addr
) );
887 if (hostlist
== NULL
)
889 hostlist
->h_addr_list
[numroutes
] = NULL
;
890 hostlist
->h_aliases
[0] = NULL
;
891 hostlist
->h_addrtype
= AF_INET
;
892 hostlist
->h_length
= sizeof(struct in_addr
);
894 /* Reorder the entries before placing them in the host list. Windows expects
895 * the IP list in order from highest priority to lowest (the critical thing
896 * is that most applications expect the first IP to be the default route).
899 qsort( route_addrs
, numroutes
, sizeof(struct route
), compare_routes_by_metric_asc
);
901 for (i
= 0; i
< numroutes
; i
++)
902 *(struct in_addr
*)hostlist
->h_addr_list
[i
] = route_addrs
[i
].addr
;
912 /***********************************************************************
913 * gethostbyname (ws2_32.52)
915 struct hostent
* WINAPI
gethostbyname( const char *name
)
917 struct hostent
*host
= NULL
;
919 struct gethostname_params params
= { hostname
, sizeof(hostname
) };
922 TRACE( "%s\n", debugstr_a(name
) );
926 SetLastError( WSANOTINITIALISED
);
930 if ((ret
= WS_CALL( gethostname
, ¶ms
)))
936 if (!name
|| !name
[0])
939 /* If the hostname of the local machine is requested then return the
940 * complete list of local IP addresses */
941 if (!strcmp( name
, hostname
))
942 host
= get_local_ips( hostname
);
944 /* If any other hostname was requested (or the routing table lookup failed)
945 * then return the IP found by the host OS */
948 unsigned int size
= 1024;
949 struct gethostbyname_params params
= { name
, NULL
, &size
};
954 if (!(params
.host
= get_hostent_buffer( size
)))
957 if ((ret
= WS_CALL( gethostbyname
, ¶ms
)) != ERROR_INSUFFICIENT_BUFFER
)
962 return ret
? NULL
: params
.host
;
965 if (host
&& host
->h_addr_list
[0][0] == 127 && strcmp( name
, "localhost" ))
967 /* hostname != "localhost" but has loopback address. replace by our
969 memcpy( host
->h_addr_list
[0], magic_loopback_addr
, 4 );
976 /***********************************************************************
977 * gethostname (ws2_32.57)
979 int WINAPI
gethostname( char *name
, int namelen
)
982 struct gethostname_params params
= { buf
, sizeof(buf
) };
985 TRACE( "name %p, len %d\n", name
, namelen
);
989 SetLastError( WSAEFAULT
);
993 if ((ret
= WS_CALL( gethostname
, ¶ms
)))
999 TRACE( "<- %s\n", debugstr_a(buf
) );
1000 len
= strlen( buf
);
1002 WARN( "Windows supports NetBIOS name length up to 15 bytes!\n" );
1005 SetLastError( WSAEFAULT
);
1008 strcpy( name
, buf
);
1013 /***********************************************************************
1014 * GetHostNameW (ws2_32.@)
1016 int WINAPI
GetHostNameW( WCHAR
*name
, int namelen
)
1019 struct gethostname_params params
= { buf
, sizeof(buf
) };
1022 TRACE( "name %p, len %d\n", name
, namelen
);
1026 SetLastError( WSAEFAULT
);
1030 if ((ret
= WS_CALL( gethostname
, ¶ms
)))
1032 SetLastError( ret
);
1036 if (MultiByteToWideChar( CP_ACP
, 0, buf
, -1, NULL
, 0 ) > namelen
)
1038 SetLastError( WSAEFAULT
);
1041 MultiByteToWideChar( CP_ACP
, 0, buf
, -1, name
, namelen
);
1046 static char *read_etc_file( const WCHAR
*filename
, DWORD
*ret_size
)
1048 WCHAR path
[MAX_PATH
];
1049 DWORD size
= sizeof(path
);
1054 if ((ret
= RegGetValueW( HKEY_LOCAL_MACHINE
, L
"System\\CurrentControlSet\\Services\\tcpip\\Parameters",
1055 L
"DatabasePath", RRF_RT_REG_SZ
, NULL
, path
, &size
)))
1057 ERR( "failed to get database path, error %lu\n", ret
);
1060 wcscat( path
, L
"\\" );
1061 wcscat( path
, filename
);
1063 file
= CreateFileW( path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
1064 if (file
== INVALID_HANDLE_VALUE
)
1066 ERR( "failed to open %s, error %lu\n", debugstr_w( path
), GetLastError() );
1070 size
= GetFileSize( file
, NULL
);
1071 if (!(data
= malloc( size
)) || !ReadFile( file
, data
, size
, ret_size
, NULL
))
1073 WARN( "failed to read file, error %lu\n", GetLastError() );
1077 CloseHandle( file
);
1081 /* returns "end" if there was no space */
1082 static char *next_space( const char *p
, const char *end
)
1084 while (p
< end
&& !isspace( *p
))
1089 /* returns "end" if there was no non-space */
1090 static char *next_non_space( const char *p
, const char *end
)
1092 while (p
< end
&& isspace( *p
))
1098 static struct protoent
*get_protoent_buffer( unsigned int size
)
1100 struct per_thread_data
*data
= get_per_thread_data();
1101 struct protoent
*new_buffer
;
1103 if (data
->pe_len
< size
)
1105 if (!(new_buffer
= realloc( data
->pe_buffer
, size
)))
1107 SetLastError( WSAENOBUFS
);
1110 data
->pe_buffer
= new_buffer
;
1111 data
->pe_len
= size
;
1113 return data
->pe_buffer
;
1116 /* Parse the first valid line into a protoent structure, returning NULL if
1117 * there is no valid line. Updates cursor to point to the start of the next
1118 * line or the end of the file. */
1119 static struct protoent
*get_next_protocol( const char **cursor
, const char *end
)
1121 const char *p
= *cursor
;
1125 const char *line_end
, *next_line
;
1126 size_t needed_size
, line_len
;
1127 unsigned int alias_count
= 0;
1128 struct protoent
*proto
;
1133 for (line_end
= p
; line_end
< end
&& *line_end
!= '\n' && *line_end
!= '#'; ++line_end
)
1135 TRACE( "parsing line %s\n", debugstr_an(p
, line_end
- p
) );
1137 for (next_line
= line_end
; next_line
< end
&& *next_line
!= '\n'; ++next_line
)
1139 if (next_line
< end
)
1140 ++next_line
; /* skip over the newline */
1142 p
= next_non_space( p
, line_end
);
1149 /* parse the name */
1152 line_len
= line_end
- name
;
1154 p
= next_space( p
, line_end
);
1161 p
= next_non_space( p
, line_end
);
1163 /* parse the number */
1167 p
= next_space( p
, line_end
);
1168 p
= next_non_space( p
, line_end
);
1170 /* we will copy the entire line after the protoent structure, then
1171 * replace spaces with null bytes as necessary */
1173 while (p
< line_end
)
1177 p
= next_space( p
, line_end
);
1178 p
= next_non_space( p
, line_end
);
1180 needed_size
= sizeof(*proto
) + line_len
+ 1 + (alias_count
+ 1) * sizeof(char *);
1182 if (!(proto
= get_protoent_buffer( needed_size
)))
1184 SetLastError( WSAENOBUFS
);
1188 proto
->p_proto
= number
;
1189 proto
->p_aliases
= (char **)(proto
+ 1);
1190 proto
->p_name
= (char *)(proto
->p_aliases
+ alias_count
+ 1);
1192 memcpy( proto
->p_name
, name
, line_len
);
1193 proto
->p_name
[line_len
] = 0;
1195 line_end
= proto
->p_name
+ line_len
;
1198 q
= next_space( q
, line_end
);
1200 q
= next_non_space( q
, line_end
);
1201 /* skip over the number */
1202 q
= next_space( q
, line_end
);
1203 q
= next_non_space( q
, line_end
);
1206 while (q
< line_end
)
1208 proto
->p_aliases
[alias_count
++] = q
;
1209 q
= next_space( q
, line_end
);
1210 if (q
< line_end
) *q
++ = 0;
1211 q
= next_non_space( q
, line_end
);
1213 proto
->p_aliases
[alias_count
] = NULL
;
1215 *cursor
= next_line
;
1219 SetLastError( WSANO_DATA
);
1224 /***********************************************************************
1225 * getprotobyname (ws2_32.53)
1227 struct protoent
* WINAPI
getprotobyname( const char *name
)
1229 struct protoent
*proto
;
1234 TRACE( "%s\n", debugstr_a(name
) );
1236 if (!(file
= read_etc_file( L
"protocol", &size
)))
1238 SetLastError( WSANO_DATA
);
1243 while ((proto
= get_next_protocol( &cursor
, file
+ size
)))
1245 if (!strcasecmp( proto
->p_name
, name
))
1254 /***********************************************************************
1255 * getprotobynumber (ws2_32.54)
1257 struct protoent
* WINAPI
getprotobynumber( int number
)
1259 struct protoent
*proto
;
1264 TRACE( "%d\n", number
);
1266 if (!(file
= read_etc_file( L
"protocol", &size
)))
1268 SetLastError( WSANO_DATA
);
1273 while ((proto
= get_next_protocol( &cursor
, file
+ size
)))
1275 if (proto
->p_proto
== number
)
1284 static struct servent
*get_servent_buffer( int size
)
1286 struct per_thread_data
*data
= get_per_thread_data();
1287 struct servent
*new_buffer
;
1289 if (data
->se_len
< size
)
1291 if (!(new_buffer
= realloc( data
->se_buffer
, size
)))
1293 SetLastError( WSAENOBUFS
);
1296 data
->se_buffer
= new_buffer
;
1297 data
->se_len
= size
;
1299 return data
->se_buffer
;
1302 /* Parse the first valid line into a servent structure, returning NULL if
1303 * there is no valid line. Updates cursor to point to the start of the next
1304 * line or the end of the file. */
1305 static struct servent
*get_next_service( const char **cursor
, const char *end
)
1307 const char *p
= *cursor
;
1311 const char *line_end
, *next_line
;
1312 size_t needed_size
, line_len
;
1313 unsigned int alias_count
= 0;
1314 struct servent
*serv
;
1319 for (line_end
= p
; line_end
< end
&& *line_end
!= '\n' && *line_end
!= '#'; ++line_end
)
1321 TRACE( "parsing line %s\n", debugstr_an(p
, line_end
- p
) );
1323 for (next_line
= line_end
; next_line
< end
&& *next_line
!= '\n'; ++next_line
)
1325 if (next_line
< end
)
1326 ++next_line
; /* skip over the newline */
1328 p
= next_non_space( p
, line_end
);
1335 /* parse the name */
1338 line_len
= line_end
- name
;
1340 p
= next_space( p
, line_end
);
1347 p
= next_non_space( p
, line_end
);
1349 /* parse the port */
1352 p
= memchr( p
, '/', line_end
- p
);
1359 p
= next_space( p
, line_end
);
1360 p
= next_non_space( p
, line_end
);
1362 /* we will copy the entire line after the servent structure, then
1363 * replace spaces with null bytes as necessary */
1365 while (p
< line_end
)
1369 p
= next_space( p
, line_end
);
1370 p
= next_non_space( p
, line_end
);
1372 needed_size
= sizeof(*serv
) + line_len
+ 1 + (alias_count
+ 1) * sizeof(char *);
1374 if (!(serv
= get_servent_buffer( needed_size
)))
1376 SetLastError( WSAENOBUFS
);
1380 serv
->s_port
= htons( port
);
1381 serv
->s_aliases
= (char **)(serv
+ 1);
1382 serv
->s_name
= (char *)(serv
->s_aliases
+ alias_count
+ 1);
1384 memcpy( serv
->s_name
, name
, line_len
);
1385 serv
->s_name
[line_len
] = 0;
1387 line_end
= serv
->s_name
+ line_len
;
1390 q
= next_space( q
, line_end
);
1392 q
= next_non_space( q
, line_end
);
1393 /* skip over the number */
1394 q
= memchr( q
, '/', line_end
- q
);
1395 serv
->s_proto
= ++q
;
1396 q
= next_space( q
, line_end
);
1397 if (q
< line_end
) *q
++ = 0;
1398 q
= next_non_space( q
, line_end
);
1401 while (q
< line_end
)
1403 serv
->s_aliases
[alias_count
++] = q
;
1404 q
= next_space( q
, line_end
);
1405 if (q
< line_end
) *q
++ = 0;
1406 q
= next_non_space( q
, line_end
);
1408 serv
->s_aliases
[alias_count
] = NULL
;
1410 *cursor
= next_line
;
1414 SetLastError( WSANO_DATA
);
1419 /***********************************************************************
1420 * getservbyname (ws2_32.55)
1422 struct servent
* WINAPI
getservbyname( const char *name
, const char *proto
)
1424 struct servent
*serv
;
1429 TRACE( "name %s, proto %s\n", debugstr_a(name
), debugstr_a(proto
) );
1431 if (!(file
= read_etc_file( L
"services", &size
)))
1433 SetLastError( WSANO_DATA
);
1438 while ((serv
= get_next_service( &cursor
, file
+ size
)))
1440 if (!strcasecmp( serv
->s_name
, name
) && (!proto
|| !strcasecmp( serv
->s_proto
, proto
)))
1449 /***********************************************************************
1450 * getservbyport (ws2_32.56)
1452 struct servent
* WINAPI
getservbyport( int port
, const char *proto
)
1454 struct servent
*serv
;
1459 TRACE( "port %d, proto %s\n", port
, debugstr_a(proto
) );
1461 if (!(file
= read_etc_file( L
"services", &size
)))
1463 SetLastError( WSANO_DATA
);
1468 while ((serv
= get_next_service( &cursor
, file
+ size
)))
1470 if (serv
->s_port
== port
&& (!proto
|| !strcasecmp( serv
->s_proto
, proto
)))
1479 /***********************************************************************
1480 * inet_ntoa (ws2_32.12)
1482 char * WINAPI
inet_ntoa( struct in_addr in
)
1484 unsigned int long_ip
= ntohl( in
.s_addr
);
1485 struct per_thread_data
*data
= get_per_thread_data();
1487 sprintf( data
->ntoa_buffer
, "%u.%u.%u.%u",
1488 (long_ip
>> 24) & 0xff,
1489 (long_ip
>> 16) & 0xff,
1490 (long_ip
>> 8) & 0xff,
1493 return data
->ntoa_buffer
;
1497 /***********************************************************************
1498 * inet_ntop (ws2_32.@)
1500 const char * WINAPI
inet_ntop( int family
, void *addr
, char *buffer
, SIZE_T len
)
1503 ULONG size
= min( len
, (ULONG
)-1 );
1505 TRACE( "family %d, addr %p, buffer %p, len %Id\n", family
, addr
, buffer
, len
);
1508 SetLastError( STATUS_INVALID_PARAMETER
);
1516 status
= RtlIpv4AddressToStringExA( (IN_ADDR
*)addr
, 0, buffer
, &size
);
1521 status
= RtlIpv6AddressToStringExA( (IN6_ADDR
*)addr
, 0, 0, buffer
, &size
);
1525 SetLastError( WSAEAFNOSUPPORT
);
1529 if (status
== STATUS_SUCCESS
) return buffer
;
1530 SetLastError( STATUS_INVALID_PARAMETER
);
1534 /***********************************************************************
1535 * inet_pton (ws2_32.@)
1537 int WINAPI
inet_pton( int family
, const char *addr
, void *buffer
)
1540 const char *terminator
;
1542 TRACE( "family %d, addr %s, buffer %p\n", family
, debugstr_a(addr
), buffer
);
1544 if (!addr
|| !buffer
)
1546 SetLastError( WSAEFAULT
);
1553 status
= RtlIpv4StringToAddressA(addr
, TRUE
, &terminator
, buffer
);
1556 status
= RtlIpv6StringToAddressA(addr
, &terminator
, buffer
);
1559 SetLastError( WSAEAFNOSUPPORT
);
1563 return (status
== STATUS_SUCCESS
&& *terminator
== 0);
1566 /***********************************************************************
1567 * InetPtonW (ws2_32.@)
1569 int WINAPI
InetPtonW( int family
, const WCHAR
*addr
, void *buffer
)
1575 TRACE( "family %d, addr %s, buffer %p\n", family
, debugstr_w(addr
), buffer
);
1579 SetLastError(WSAEFAULT
);
1580 return SOCKET_ERROR
;
1583 len
= WideCharToMultiByte( CP_ACP
, 0, addr
, -1, NULL
, 0, NULL
, NULL
);
1584 if (!(addrA
= malloc( len
)))
1586 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
1589 WideCharToMultiByte( CP_ACP
, 0, addr
, -1, addrA
, len
, NULL
, NULL
);
1591 ret
= inet_pton( family
, addrA
, buffer
);
1592 if (!ret
) SetLastError( WSAEINVAL
);
1598 /***********************************************************************
1599 * InetNtopW (ws2_32.@)
1601 const WCHAR
* WINAPI
InetNtopW( int family
, void *addr
, WCHAR
*buffer
, SIZE_T len
)
1603 char bufferA
[INET6_ADDRSTRLEN
];
1606 TRACE( "family %d, addr %p, buffer %p, len %Iu\n", family
, addr
, buffer
, len
);
1608 if (inet_ntop( family
, addr
, bufferA
, sizeof(bufferA
) ))
1610 if (MultiByteToWideChar( CP_ACP
, 0, bufferA
, -1, buffer
, len
))
1613 SetLastError( ERROR_INVALID_PARAMETER
);
1619 /***********************************************************************
1620 * WSAStringToAddressA (ws2_32.@)
1622 int WINAPI
WSAStringToAddressA( char *string
, int family
, WSAPROTOCOL_INFOA
*protocol_info
,
1623 struct sockaddr
*addr
, int *addr_len
)
1627 TRACE( "string %s, family %u\n", debugstr_a(string
), family
);
1629 if (!addr
|| !addr_len
) return -1;
1633 SetLastError( WSAEINVAL
);
1638 FIXME( "ignoring protocol_info\n" );
1644 struct sockaddr_in
*addr4
= (struct sockaddr_in
*)addr
;
1646 if (*addr_len
< sizeof(struct sockaddr_in
))
1648 *addr_len
= sizeof(struct sockaddr_in
);
1649 SetLastError( WSAEFAULT
);
1652 memset( addr
, 0, sizeof(struct sockaddr_in
) );
1654 status
= RtlIpv4StringToAddressExA( string
, FALSE
, &addr4
->sin_addr
, &addr4
->sin_port
);
1655 if (status
!= STATUS_SUCCESS
)
1657 SetLastError( WSAEINVAL
);
1660 addr4
->sin_family
= AF_INET
;
1661 *addr_len
= sizeof(struct sockaddr_in
);
1666 struct sockaddr_in6
*addr6
= (struct sockaddr_in6
*)addr
;
1668 if (*addr_len
< sizeof(struct sockaddr_in6
))
1670 *addr_len
= sizeof(struct sockaddr_in6
);
1671 SetLastError( WSAEFAULT
);
1674 memset( addr
, 0, sizeof(struct sockaddr_in6
) );
1676 status
= RtlIpv6StringToAddressExA( string
, &addr6
->sin6_addr
, &addr6
->sin6_scope_id
, &addr6
->sin6_port
);
1677 if (status
!= STATUS_SUCCESS
)
1679 SetLastError( WSAEINVAL
);
1682 addr6
->sin6_family
= AF_INET6
;
1683 *addr_len
= sizeof(struct sockaddr_in6
);
1687 /* According to MSDN, only AF_INET and AF_INET6 are supported. */
1688 TRACE( "Unsupported address family specified: %d.\n", family
);
1689 SetLastError( WSAEINVAL
);
1695 /***********************************************************************
1696 * WSAStringToAddressW (ws2_32.@)
1698 int WINAPI
WSAStringToAddressW( WCHAR
*string
, int family
, WSAPROTOCOL_INFOW
*protocol_info
,
1699 struct sockaddr
*addr
, int *addr_len
)
1701 WSAPROTOCOL_INFOA infoA
;
1702 WSAPROTOCOL_INFOA
*protocol_infoA
= NULL
;
1706 TRACE( "string %s, family %u\n", debugstr_w(string
), family
);
1708 if (!addr
|| !addr_len
) return -1;
1712 protocol_infoA
= &infoA
;
1713 memcpy( protocol_infoA
, protocol_info
, FIELD_OFFSET( WSAPROTOCOL_INFOA
, szProtocol
) );
1715 if (!WideCharToMultiByte( CP_ACP
, 0, protocol_info
->szProtocol
, -1, protocol_infoA
->szProtocol
,
1716 sizeof(protocol_infoA
->szProtocol
), NULL
, NULL
))
1718 SetLastError( WSAEINVAL
);
1725 SetLastError( WSAEINVAL
);
1729 sizeA
= WideCharToMultiByte( CP_ACP
, 0, string
, -1, NULL
, 0, NULL
, NULL
);
1730 if (!(stringA
= malloc( sizeA
)))
1732 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
1735 WideCharToMultiByte( CP_ACP
, 0, string
, -1, stringA
, sizeA
, NULL
, NULL
);
1736 ret
= WSAStringToAddressA( stringA
, family
, protocol_infoA
, addr
, addr_len
);
1742 /***********************************************************************
1743 * WSAAddressToStringA (ws2_32.@)
1745 int WINAPI
WSAAddressToStringA( struct sockaddr
*addr
, DWORD addr_len
,
1746 WSAPROTOCOL_INFOA
*info
, char *string
, DWORD
*string_len
)
1748 char buffer
[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
1751 TRACE( "addr %s\n", debugstr_sockaddr(addr
) );
1753 if (!addr
) return SOCKET_ERROR
;
1754 if (!string
|| !string_len
) return SOCKET_ERROR
;
1756 switch (addr
->sa_family
)
1760 const struct sockaddr_in
*addr4
= (const struct sockaddr_in
*)addr
;
1761 unsigned int long_ip
= ntohl( addr4
->sin_addr
.s_addr
);
1764 if (addr_len
< sizeof(struct sockaddr_in
)) return -1;
1765 sprintf( buffer
, "%u.%u.%u.%u:%u",
1766 (long_ip
>> 24) & 0xff,
1767 (long_ip
>> 16) & 0xff,
1768 (long_ip
>> 8) & 0xff,
1770 ntohs( addr4
->sin_port
) );
1772 p
= strchr( buffer
, ':' );
1773 if (!addr4
->sin_port
) *p
= 0;
1778 struct sockaddr_in6
*addr6
= (struct sockaddr_in6
*)addr
;
1782 if (addr_len
< sizeof(struct sockaddr_in6
)) return -1;
1783 if (addr6
->sin6_port
)
1784 strcpy( buffer
, "[" );
1785 len
= strlen( buffer
);
1786 if (!inet_ntop( AF_INET6
, &addr6
->sin6_addr
, &buffer
[len
], sizeof(buffer
) - len
))
1788 SetLastError( WSAEINVAL
);
1791 if (addr6
->sin6_scope_id
)
1792 sprintf( buffer
+ strlen( buffer
), "%%%lu", addr6
->sin6_scope_id
);
1793 if (addr6
->sin6_port
)
1794 sprintf( buffer
+ strlen( buffer
), "]:%u", ntohs( addr6
->sin6_port
) );
1799 SetLastError( WSAEINVAL
);
1803 size
= strlen( buffer
) + 1;
1805 if (*string_len
< size
)
1808 SetLastError( WSAEFAULT
);
1812 TRACE( "=> %s, %lu chars\n", debugstr_a(buffer
), size
);
1814 strcpy( string
, buffer
);
1819 /***********************************************************************
1820 * WSAAddressToStringW (ws2_32.@)
1822 int WINAPI
WSAAddressToStringW( struct sockaddr
*addr
, DWORD addr_len
,
1823 WSAPROTOCOL_INFOW
*info
, WCHAR
*string
, DWORD
*string_len
)
1826 char buf
[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
1828 TRACE( "(%p, %lu, %p, %p, %p)\n", addr
, addr_len
, info
, string
, string_len
);
1830 if ((ret
= WSAAddressToStringA( addr
, addr_len
, NULL
, buf
, string_len
))) return ret
;
1832 MultiByteToWideChar( CP_ACP
, 0, buf
, *string_len
, string
, *string_len
);
1833 TRACE( "=> %s, %lu chars\n", debugstr_w(string
), *string_len
);
1837 /***********************************************************************
1838 * inet_addr (ws2_32.11)
1840 u_long WINAPI
inet_addr( const char *str
)
1842 unsigned long a
[4] = { 0 };
1843 const char *s
= str
;
1849 TRACE( "str %s.\n", debugstr_a(str
) );
1853 SetLastError( WSAEFAULT
);
1857 d
= (unsigned char *)&addr
;
1859 if (s
[0] == ' ' && !s
[1]) return 0;
1861 for (i
= 0; i
< 4; ++i
)
1863 a
[i
] = strtoul( s
, &z
, 0 );
1864 if (z
== s
|| !isdigit( *s
)) return INADDR_NONE
;
1865 if (!*z
|| isspace(*z
)) break;
1866 if (*z
!= '.') return INADDR_NONE
;
1870 if (i
== 4) return INADDR_NONE
;
1875 a
[1] = a
[0] & 0xffffff;
1879 a
[2] = a
[1] & 0xffff;
1886 for (i
= 0; i
< 4; ++i
)
1888 if (a
[i
] > 255) return INADDR_NONE
;
1895 /***********************************************************************
1898 u_long WINAPI
WS_htonl( u_long hostlong
)
1900 return htonl( hostlong
);
1904 /***********************************************************************
1907 u_short WINAPI
WS_htons( u_short hostshort
)
1909 return htons( hostshort
);
1913 /***********************************************************************
1914 * WSAHtonl (ws2_32.@)
1916 int WINAPI
WSAHtonl( SOCKET s
, u_long hostlong
, u_long
*netlong
)
1920 *netlong
= htonl( hostlong
);
1923 SetLastError( WSAEFAULT
);
1928 /***********************************************************************
1929 * WSAHtons (ws2_32.@)
1931 int WINAPI
WSAHtons( SOCKET s
, u_short hostshort
, u_short
*netshort
)
1935 *netshort
= htons( hostshort
);
1938 SetLastError( WSAEFAULT
);
1943 /***********************************************************************
1946 u_long WINAPI
WS_ntohl( u_long netlong
)
1948 return ntohl( netlong
);
1952 /***********************************************************************
1955 u_short WINAPI
WS_ntohs( u_short netshort
)
1957 return ntohs( netshort
);
1961 /***********************************************************************
1962 * WSANtohl (ws2_32.@)
1964 int WINAPI
WSANtohl( SOCKET s
, u_long netlong
, u_long
*hostlong
)
1966 if (!hostlong
) return WSAEFAULT
;
1968 *hostlong
= ntohl( netlong
);
1973 /***********************************************************************
1974 * WSANtohs (ws2_32.@)
1976 int WINAPI
WSANtohs( SOCKET s
, u_short netshort
, u_short
*hostshort
)
1978 if (!hostshort
) return WSAEFAULT
;
1980 *hostshort
= ntohs( netshort
);
1985 /***********************************************************************
1986 * WSAInstallServiceClassA (ws2_32.@)
1988 int WINAPI
WSAInstallServiceClassA( WSASERVICECLASSINFOA
*info
)
1990 FIXME( "Request to install service %s\n", debugstr_a(info
->lpszServiceClassName
) );
1991 SetLastError( WSAEACCES
);
1996 /***********************************************************************
1997 * WSAInstallServiceClassW (ws2_32.@)
1999 int WINAPI
WSAInstallServiceClassW( WSASERVICECLASSINFOW
*info
)
2001 FIXME( "Request to install service %s\n", debugstr_w(info
->lpszServiceClassName
) );
2002 SetLastError( WSAEACCES
);
2007 /***********************************************************************
2008 * WSARemoveServiceClass (ws2_32.@)
2010 int WINAPI
WSARemoveServiceClass( GUID
*info
)
2012 FIXME( "Request to remove service %s\n", debugstr_guid(info
) );
2013 SetLastError( WSATYPE_NOT_FOUND
);
2018 /***********************************************************************
2019 * WSAGetServiceClassInfoA (ws2_32.@)
2021 int WINAPI
WSAGetServiceClassInfoA( GUID
*provider
, GUID
*service
, DWORD
*len
,
2022 WSASERVICECLASSINFOA
*info
)
2024 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider
), debugstr_guid(service
), len
, info
);
2025 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2030 /***********************************************************************
2031 * WSAGetServiceClassInfoW (ws2_32.@)
2033 int WINAPI
WSAGetServiceClassInfoW( GUID
*provider
, GUID
*service
, DWORD
*len
,
2034 WSASERVICECLASSINFOW
*info
)
2036 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider
), debugstr_guid(service
), len
, info
);
2037 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2042 /***********************************************************************
2043 * WSAGetServiceClassNameByClassIdA (ws2_32.@)
2045 int WINAPI
WSAGetServiceClassNameByClassIdA( GUID
*class, char *service
, DWORD
*len
)
2047 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service
, len
);
2048 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2053 /***********************************************************************
2054 * WSAGetServiceClassNameByClassIdW (ws2_32.@)
2056 int WINAPI
WSAGetServiceClassNameByClassIdW( GUID
*class, WCHAR
*service
, DWORD
*len
)
2058 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service
, len
);
2059 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2064 /***********************************************************************
2065 * WSALookupServiceBeginA (ws2_32.@)
2067 int WINAPI
WSALookupServiceBeginA( WSAQUERYSETA
*query
, DWORD flags
, HANDLE
*lookup
)
2069 FIXME( "(%p %#lx %p) Stub!\n", query
, flags
, lookup
);
2070 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2075 /***********************************************************************
2076 * WSALookupServiceBeginW (ws2_32.@)
2078 int WINAPI
WSALookupServiceBeginW( WSAQUERYSETW
*query
, DWORD flags
, HANDLE
*lookup
)
2080 FIXME( "(%p %#lx %p) Stub!\n", query
, flags
, lookup
);
2081 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2086 /***********************************************************************
2087 * WSALookupServiceEnd (ws2_32.@)
2089 int WINAPI
WSALookupServiceEnd( HANDLE lookup
)
2091 FIXME("(%p) Stub!\n", lookup
);
2096 /***********************************************************************
2097 * WSALookupServiceNextA (ws2_32.@)
2099 int WINAPI
WSALookupServiceNextA( HANDLE lookup
, DWORD flags
, DWORD
*len
, WSAQUERYSETA
*results
)
2101 FIXME( "(%p %#lx %p %p) Stub!\n", lookup
, flags
, len
, results
);
2102 SetLastError( WSA_E_NO_MORE
);
2107 /***********************************************************************
2108 * WSALookupServiceNextW (ws2_32.@)
2110 int WINAPI
WSALookupServiceNextW( HANDLE lookup
, DWORD flags
, DWORD
*len
, WSAQUERYSETW
*results
)
2112 FIXME( "(%p %#lx %p %p) Stub!\n", lookup
, flags
, len
, results
);
2113 SetLastError( WSA_E_NO_MORE
);
2118 /***********************************************************************
2119 * WSASetServiceA (ws2_32.@)
2121 int WINAPI
WSASetServiceA( WSAQUERYSETA
*query
, WSAESETSERVICEOP operation
, DWORD flags
)
2123 FIXME( "(%p %#x %#lx) Stub!\n", query
, operation
, flags
);
2128 /***********************************************************************
2129 * WSASetServiceW (ws2_32.@)
2131 int WINAPI
WSASetServiceW( WSAQUERYSETW
*query
, WSAESETSERVICEOP operation
, DWORD flags
)
2133 FIXME( "(%p %#x %#lx) Stub!\n", query
, operation
, flags
);
2138 /***********************************************************************
2139 * WSAEnumNameSpaceProvidersA (ws2_32.@)
2141 int WINAPI
WSAEnumNameSpaceProvidersA( DWORD
*len
, WSANAMESPACE_INFOA
*buffer
)
2143 FIXME( "(%p %p) Stub!\n", len
, buffer
);
2148 /***********************************************************************
2149 * WSAEnumNameSpaceProvidersW (ws2_32.@)
2151 int WINAPI
WSAEnumNameSpaceProvidersW( DWORD
*len
, WSANAMESPACE_INFOW
*buffer
)
2153 FIXME( "(%p %p) Stub!\n", len
, buffer
);
2158 /***********************************************************************
2159 * WSAProviderConfigChange (ws2_32.@)
2161 int WINAPI
WSAProviderConfigChange( HANDLE
*handle
, OVERLAPPED
*overlapped
,
2162 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion
)
2164 FIXME( "(%p %p %p) Stub!\n", handle
, overlapped
, completion
);
2169 /***********************************************************************
2170 * WSANSPIoctl (ws2_32.@)
2172 int WINAPI
WSANSPIoctl( HANDLE lookup
, DWORD code
, void *in_buffer
,
2173 DWORD in_size
, void *out_buffer
, DWORD out_size
,
2174 DWORD
*ret_size
, WSACOMPLETION
*completion
)
2176 FIXME( "(%p, %#lx, %p, %#lx, %p, %#lx, %p, %p) Stub!\n", lookup
, code
,
2177 in_buffer
, in_size
, out_buffer
, out_size
, ret_size
, completion
);
2178 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2183 /***********************************************************************
2184 * WSCEnableNSProvider (ws2_32.@)
2186 int WINAPI
WSCEnableNSProvider( GUID
*provider
, BOOL enable
)
2188 FIXME( "(%s %d) Stub!\n", debugstr_guid(provider
), enable
);
2193 /***********************************************************************
2194 * WSCGetProviderInfo (ws2_32.@)
2196 int WINAPI
WSCGetProviderInfo( GUID
*provider
, WSC_PROVIDER_INFO_TYPE info_type
,
2197 BYTE
*info
, size_t *len
, DWORD flags
, int *errcode
)
2199 FIXME( "(%s %#x %p %p %#lx %p) Stub!\n",
2200 debugstr_guid(provider
), info_type
, info
, len
, flags
, errcode
);
2207 *errcode
= WSAEFAULT
;
2211 *errcode
= WSANO_RECOVERY
;
2216 /***********************************************************************
2217 * WSCGetProviderPath (ws2_32.@)
2219 int WINAPI
WSCGetProviderPath( GUID
*provider
, WCHAR
*path
, int *len
, int *errcode
)
2221 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider
), path
, len
, errcode
);
2223 if (!provider
|| !len
)
2226 *errcode
= WSAEFAULT
;
2233 *errcode
= WSAEINVAL
;
2241 /***********************************************************************
2242 * WSCInstallNameSpace (ws2_32.@)
2244 int WINAPI
WSCInstallNameSpace( WCHAR
*identifier
, WCHAR
*path
, DWORD
namespace,
2245 DWORD version
, GUID
*provider
)
2247 FIXME( "(%s %s %#lx %#lx %s) Stub!\n", debugstr_w(identifier
), debugstr_w(path
),
2248 namespace, version
, debugstr_guid(provider
) );
2253 /***********************************************************************
2254 * WSCUnInstallNameSpace (ws2_32.@)
2256 int WINAPI
WSCUnInstallNameSpace( GUID
*provider
)
2258 FIXME( "(%s) Stub!\n", debugstr_guid(provider
) );
2263 /***********************************************************************
2264 * WSCWriteProviderOrder (ws2_32.@)
2266 int WINAPI
WSCWriteProviderOrder( DWORD
*entry
, DWORD number
)
2268 FIXME( "(%p %#lx) Stub!\n", entry
, number
);
2273 /***********************************************************************
2274 * WSCInstallProvider (ws2_32.@)
2276 int WINAPI
WSCInstallProvider( GUID
*provider
, const WCHAR
*path
,
2277 WSAPROTOCOL_INFOW
*protocol_info
, DWORD count
, int *err
)
2279 FIXME( "(%s, %s, %p, %lu, %p): stub !\n", debugstr_guid(provider
),
2280 debugstr_w(path
), protocol_info
, count
, err
);
2286 /***********************************************************************
2287 * WSCDeinstallProvider (ws2_32.@)
2289 int WINAPI
WSCDeinstallProvider( GUID
*provider
, int *err
)
2291 FIXME( "(%s, %p): stub !\n", debugstr_guid(provider
), err
);
2297 /***********************************************************************
2298 * WSCSetApplicationCategory (ws2_32.@)
2300 int WINAPI
WSCSetApplicationCategory( const WCHAR
*path
, DWORD len
, const WCHAR
*extra
, DWORD extralen
,
2301 DWORD lspcat
, DWORD
*prev_lspcat
, int *err
)
2303 FIXME( "(%s %lu %s %lu %#lx %p) Stub!\n", debugstr_w(path
), len
, debugstr_w(extra
),
2304 extralen
, lspcat
, prev_lspcat
);
2309 /***********************************************************************
2310 * WSCEnumProtocols (ws2_32.@)
2312 int WINAPI
WSCEnumProtocols( int *protocols
, WSAPROTOCOL_INFOW
*info
, DWORD
*len
, int *err
)
2314 int ret
= WSAEnumProtocolsW( protocols
, info
, len
);
2316 if (ret
== SOCKET_ERROR
) *err
= WSAENOBUFS
;