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
27 #include "ws2_32_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(winsock
);
30 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
32 DECLARE_CRITICAL_SECTION(csWSgetXXXbyYYY
);
34 #define MAP_OPTION(opt) { WS_##opt, opt }
36 static const int ws_aiflag_map
[][2] =
38 MAP_OPTION( AI_PASSIVE
),
39 MAP_OPTION( AI_CANONNAME
),
40 MAP_OPTION( AI_NUMERICHOST
),
42 MAP_OPTION( AI_NUMERICSERV
),
45 MAP_OPTION( AI_V4MAPPED
),
48 MAP_OPTION( AI_ADDRCONFIG
),
51 static const int ws_eai_map
[][2] =
53 MAP_OPTION( EAI_AGAIN
),
54 MAP_OPTION( EAI_BADFLAGS
),
55 MAP_OPTION( EAI_FAIL
),
56 MAP_OPTION( EAI_FAMILY
),
57 MAP_OPTION( EAI_MEMORY
),
58 /* Note: EAI_NODATA is deprecated, but still used by Windows and Linux. We map
59 * the newer EAI_NONAME to EAI_NODATA for now until Windows changes too. */
61 MAP_OPTION( EAI_NODATA
),
64 { WS_EAI_NODATA
, EAI_NONAME
},
66 MAP_OPTION( EAI_SERVICE
),
67 MAP_OPTION( EAI_SOCKTYPE
),
71 static const int ws_af_map
[][2] =
73 MAP_OPTION( AF_UNSPEC
),
74 MAP_OPTION( AF_INET
),
75 MAP_OPTION( AF_INET6
),
80 MAP_OPTION( AF_IRDA
),
82 {FROM_PROTOCOL_INFO
, FROM_PROTOCOL_INFO
},
85 static const int ws_proto_map
[][2] =
87 MAP_OPTION( IPPROTO_IP
),
88 MAP_OPTION( IPPROTO_TCP
),
89 MAP_OPTION( IPPROTO_UDP
),
90 MAP_OPTION( IPPROTO_IPV6
),
91 MAP_OPTION( IPPROTO_ICMP
),
92 MAP_OPTION( IPPROTO_IGMP
),
93 MAP_OPTION( IPPROTO_RAW
),
94 {WS_IPPROTO_IPV4
, IPPROTO_IPIP
},
95 {FROM_PROTOCOL_INFO
, FROM_PROTOCOL_INFO
},
98 #define IS_IPX_PROTO(X) ((X) >= WS_NSPROTO_IPX && (X) <= WS_NSPROTO_IPX + 255)
100 static int convert_af_w2u( int family
)
104 for (i
= 0; i
< ARRAY_SIZE(ws_af_map
); i
++)
106 if (ws_af_map
[i
][0] == family
)
107 return ws_af_map
[i
][1];
109 FIXME( "unhandled Windows address family %d\n", family
);
113 static int convert_af_u2w( int family
)
117 for (i
= 0; i
< ARRAY_SIZE(ws_af_map
); i
++)
119 if (ws_af_map
[i
][1] == family
)
120 return ws_af_map
[i
][0];
122 FIXME( "unhandled UNIX address family %d\n", family
);
126 static int convert_proto_w2u( int protocol
)
130 for (i
= 0; i
< ARRAY_SIZE(ws_proto_map
); i
++)
132 if (ws_proto_map
[i
][0] == protocol
)
133 return ws_proto_map
[i
][1];
136 if (IS_IPX_PROTO(protocol
))
139 FIXME( "unhandled Windows socket protocol %d\n", protocol
);
143 static int convert_proto_u2w( int protocol
)
147 for (i
= 0; i
< ARRAY_SIZE(ws_proto_map
); i
++)
149 if (ws_proto_map
[i
][1] == protocol
)
150 return ws_proto_map
[i
][0];
153 /* if value is inside IPX range just return it - the kernel simply
154 * echoes the value used in the socket() function */
155 if (IS_IPX_PROTO(protocol
))
158 FIXME("unhandled UNIX socket protocol %d\n", protocol
);
162 static int convert_aiflag_w2u( int winflags
)
167 for (i
= 0; i
< ARRAY_SIZE(ws_aiflag_map
); i
++)
169 if (ws_aiflag_map
[i
][0] & winflags
)
171 unixflags
|= ws_aiflag_map
[i
][1];
172 winflags
&= ~ws_aiflag_map
[i
][0];
176 FIXME( "Unhandled windows AI_xxx flags 0x%x\n", winflags
);
180 static int convert_aiflag_u2w( int unixflags
)
185 for (i
= 0; i
< ARRAY_SIZE(ws_aiflag_map
); i
++)
187 if (ws_aiflag_map
[i
][1] & unixflags
)
189 winflags
|= ws_aiflag_map
[i
][0];
190 unixflags
&= ~ws_aiflag_map
[i
][1];
194 WARN( "Unhandled UNIX AI_xxx flags 0x%x\n", unixflags
);
198 int convert_eai_u2w( int unixret
)
202 if (!unixret
) return 0;
204 for (i
= 0; ws_eai_map
[i
][0]; i
++)
206 if (ws_eai_map
[i
][1] == unixret
)
207 return ws_eai_map
[i
][0];
210 if (unixret
== EAI_SYSTEM
)
211 /* There are broken versions of glibc which return EAI_SYSTEM
212 * and set errno to 0 instead of returning EAI_NONAME. */
213 return errno
? sock_get_error( errno
) : WS_EAI_NONAME
;
215 FIXME("Unhandled unix EAI_xxx ret %d\n", unixret
);
219 static char *get_fqdn(void)
224 GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified
, NULL
, &size
);
225 if (GetLastError() != ERROR_MORE_DATA
) return NULL
;
226 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, size
))) return NULL
;
227 if (!GetComputerNameExA( ComputerNamePhysicalDnsFullyQualified
, ret
, &size
))
229 HeapFree( GetProcessHeap(), 0, ret
);
235 static BOOL
addrinfo_in_list( const struct WS_addrinfo
*list
, const struct WS_addrinfo
*ai
)
237 const struct WS_addrinfo
*cursor
= list
;
240 if (ai
->ai_flags
== cursor
->ai_flags
&&
241 ai
->ai_family
== cursor
->ai_family
&&
242 ai
->ai_socktype
== cursor
->ai_socktype
&&
243 ai
->ai_protocol
== cursor
->ai_protocol
&&
244 ai
->ai_addrlen
== cursor
->ai_addrlen
&&
245 !memcmp(ai
->ai_addr
, cursor
->ai_addr
, ai
->ai_addrlen
) &&
246 ((ai
->ai_canonname
&& cursor
->ai_canonname
&& !strcmp(ai
->ai_canonname
, cursor
->ai_canonname
))
247 || (!ai
->ai_canonname
&& !cursor
->ai_canonname
)))
251 cursor
= cursor
->ai_next
;
257 /***********************************************************************
258 * getaddrinfo (ws2_32.@)
260 int WINAPI
WS_getaddrinfo( const char *nodename
, const char *servname
,
261 const struct WS_addrinfo
*hints
, struct WS_addrinfo
**res
)
263 #ifdef HAVE_GETADDRINFO
264 struct addrinfo
*unixaires
= NULL
;
266 struct addrinfo unixhints
, *punixhints
= NULL
;
267 char *nodev6
= NULL
, *fqdn
= NULL
;
271 if (!nodename
&& !servname
)
273 SetLastError(WSAHOST_NOT_FOUND
);
274 return WSAHOST_NOT_FOUND
;
279 else if (!nodename
[0])
281 if (!(fqdn
= get_fqdn())) return WSA_NOT_ENOUGH_MEMORY
;
288 /* Check for [ipv6] or [ipv6]:portnumber, which are supported by Windows */
289 if (!hints
|| hints
->ai_family
== WS_AF_UNSPEC
|| hints
->ai_family
== WS_AF_INET6
)
293 if (node
[0] == '[' && (close_bracket
= strchr(node
+ 1, ']')))
295 nodev6
= HeapAlloc( GetProcessHeap(), 0, close_bracket
- node
);
296 if (!nodev6
) return WSA_NOT_ENOUGH_MEMORY
;
297 lstrcpynA( nodev6
, node
+ 1, close_bracket
- node
);
303 /* servname tweak required by OSX and BSD kernels */
304 if (servname
&& !servname
[0]) servname
= "0";
308 punixhints
= &unixhints
;
310 memset( &unixhints
, 0, sizeof(unixhints
) );
311 punixhints
->ai_flags
= convert_aiflag_w2u( hints
->ai_flags
);
313 /* zero is a wildcard, no need to convert */
314 if (hints
->ai_family
)
315 punixhints
->ai_family
= convert_af_w2u( hints
->ai_family
);
316 if (hints
->ai_socktype
)
317 punixhints
->ai_socktype
= convert_socktype_w2u( hints
->ai_socktype
);
318 if (hints
->ai_protocol
)
319 punixhints
->ai_protocol
= max( convert_proto_w2u( hints
->ai_protocol
), 0 );
321 if (punixhints
->ai_socktype
< 0)
323 SetLastError( WSAESOCKTNOSUPPORT
);
324 HeapFree( GetProcessHeap(), 0, fqdn
);
325 HeapFree( GetProcessHeap(), 0, nodev6
);
329 /* windows allows invalid combinations of socket type and protocol, unix does not.
330 * fix the parameters here to make getaddrinfo call always work */
331 if (punixhints
->ai_protocol
== IPPROTO_TCP
332 && punixhints
->ai_socktype
!= SOCK_STREAM
333 && punixhints
->ai_socktype
!= SOCK_SEQPACKET
)
334 punixhints
->ai_socktype
= 0;
335 else if (punixhints
->ai_protocol
== IPPROTO_UDP
&& punixhints
->ai_socktype
!= SOCK_DGRAM
)
336 punixhints
->ai_socktype
= 0;
337 else if (IS_IPX_PROTO(punixhints
->ai_protocol
) && punixhints
->ai_socktype
!= SOCK_DGRAM
)
338 punixhints
->ai_socktype
= 0;
339 else if (punixhints
->ai_protocol
== IPPROTO_IPV6
)
340 punixhints
->ai_protocol
= 0;
343 /* getaddrinfo(3) is thread safe, no need to wrap in CS */
344 result
= getaddrinfo( node
, servname
, punixhints
, &unixaires
);
346 if (result
&& (!hints
|| !(hints
->ai_flags
& WS_AI_NUMERICHOST
)) && node
)
348 if (!fqdn
&& !(fqdn
= get_fqdn()))
350 HeapFree( GetProcessHeap(), 0, nodev6
);
351 return WSA_NOT_ENOUGH_MEMORY
;
353 if (!strcmp( fqdn
, node
) || (!strncmp( fqdn
, node
, strlen( node
) ) && fqdn
[strlen( node
)] == '.'))
355 /* If it didn't work it means the host name IP is not in /etc/hosts, try again
356 * by sending a NULL host and avoid sending a NULL servname too because that
358 ERR_(winediag
)( "Failed to resolve your host name IP\n" );
359 result
= getaddrinfo( NULL
, servname
? servname
: "0", punixhints
, &unixaires
);
360 if (!result
&& punixhints
&& (punixhints
->ai_flags
& AI_CANONNAME
) && unixaires
&& !unixaires
->ai_canonname
)
362 freeaddrinfo( unixaires
);
367 TRACE( "%s, %s %p -> %p %d\n", debugstr_a(nodename
), debugstr_a(servname
), hints
, res
, result
);
368 HeapFree( GetProcessHeap(), 0, fqdn
);
369 HeapFree( GetProcessHeap(), 0, nodev6
);
373 struct addrinfo
*xuai
= unixaires
;
374 struct WS_addrinfo
**xai
= res
;
379 struct WS_addrinfo
*ai
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(struct WS_addrinfo
) );
385 ai
->ai_flags
= convert_aiflag_u2w( xuai
->ai_flags
);
386 ai
->ai_family
= convert_af_u2w( xuai
->ai_family
);
387 /* copy whatever was sent in the hints */
390 ai
->ai_socktype
= hints
->ai_socktype
;
391 ai
->ai_protocol
= hints
->ai_protocol
;
395 ai
->ai_socktype
= convert_socktype_u2w( xuai
->ai_socktype
);
396 ai
->ai_protocol
= convert_proto_u2w( xuai
->ai_protocol
);
398 if (xuai
->ai_canonname
)
400 TRACE( "canon name - %s\n", debugstr_a(xuai
->ai_canonname
) );
401 ai
->ai_canonname
= HeapAlloc( GetProcessHeap(), 0, strlen( xuai
->ai_canonname
) + 1 );
402 if (!ai
->ai_canonname
)
404 strcpy( ai
->ai_canonname
, xuai
->ai_canonname
);
406 len
= xuai
->ai_addrlen
;
407 ai
->ai_addr
= HeapAlloc( GetProcessHeap(), 0, len
);
410 ai
->ai_addrlen
= len
;
413 int winlen
= ai
->ai_addrlen
;
415 if (!ws_sockaddr_u2ws( xuai
->ai_addr
, ai
->ai_addr
, &winlen
))
417 ai
->ai_addrlen
= winlen
;
421 ai
->ai_addr
= HeapReAlloc( GetProcessHeap(), 0, ai
->ai_addr
, len
);
424 ai
->ai_addrlen
= len
;
427 if (addrinfo_in_list( *res
, ai
))
429 HeapFree( GetProcessHeap(), 0, ai
->ai_canonname
);
430 HeapFree( GetProcessHeap(), 0, ai
->ai_addr
);
431 HeapFree( GetProcessHeap(), 0, ai
);
438 xuai
= xuai
->ai_next
;
440 freeaddrinfo( unixaires
);
442 if (TRACE_ON(winsock
))
444 struct WS_addrinfo
*ai
= *res
;
447 TRACE( "=> %p, flags %#x, family %d, type %d, protocol %d, len %ld, name %s, addr %s\n",
448 ai
, ai
->ai_flags
, ai
->ai_family
, ai
->ai_socktype
, ai
->ai_protocol
, ai
->ai_addrlen
,
449 ai
->ai_canonname
, debugstr_sockaddr(ai
->ai_addr
) );
455 result
= convert_eai_u2w( result
);
457 SetLastError( result
);
461 if (*res
) WS_freeaddrinfo( *res
);
462 if (unixaires
) freeaddrinfo( unixaires
);
463 return WSA_NOT_ENOUGH_MEMORY
;
465 FIXME( "getaddrinfo() failed, not found during build time.\n" );
471 static ADDRINFOEXW
*addrinfo_AtoW( const struct WS_addrinfo
*ai
)
475 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, sizeof(ADDRINFOEXW
) ))) return NULL
;
476 ret
->ai_flags
= ai
->ai_flags
;
477 ret
->ai_family
= ai
->ai_family
;
478 ret
->ai_socktype
= ai
->ai_socktype
;
479 ret
->ai_protocol
= ai
->ai_protocol
;
480 ret
->ai_addrlen
= ai
->ai_addrlen
;
481 ret
->ai_canonname
= NULL
;
485 ret
->ai_provider
= NULL
;
487 if (ai
->ai_canonname
)
489 int len
= MultiByteToWideChar( CP_ACP
, 0, ai
->ai_canonname
, -1, NULL
, 0 );
490 if (!(ret
->ai_canonname
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
492 HeapFree( GetProcessHeap(), 0, ret
);
495 MultiByteToWideChar( CP_ACP
, 0, ai
->ai_canonname
, -1, ret
->ai_canonname
, len
);
499 if (!(ret
->ai_addr
= HeapAlloc( GetProcessHeap(), 0, ai
->ai_addrlen
)))
501 HeapFree( GetProcessHeap(), 0, ret
->ai_canonname
);
502 HeapFree( GetProcessHeap(), 0, ret
);
505 memcpy( ret
->ai_addr
, ai
->ai_addr
, ai
->ai_addrlen
);
510 static ADDRINFOEXW
*addrinfo_list_AtoW( const struct WS_addrinfo
*info
)
512 ADDRINFOEXW
*ret
, *infoW
;
514 if (!(ret
= infoW
= addrinfo_AtoW( info
))) return NULL
;
515 while (info
->ai_next
)
517 if (!(infoW
->ai_next
= addrinfo_AtoW( info
->ai_next
)))
519 FreeAddrInfoExW( ret
);
522 infoW
= infoW
->ai_next
;
523 info
= info
->ai_next
;
528 static struct WS_addrinfo
*addrinfo_WtoA( const struct WS_addrinfoW
*ai
)
530 struct WS_addrinfo
*ret
;
532 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, sizeof(struct WS_addrinfo
) ))) return NULL
;
533 ret
->ai_flags
= ai
->ai_flags
;
534 ret
->ai_family
= ai
->ai_family
;
535 ret
->ai_socktype
= ai
->ai_socktype
;
536 ret
->ai_protocol
= ai
->ai_protocol
;
537 ret
->ai_addrlen
= ai
->ai_addrlen
;
538 ret
->ai_canonname
= NULL
;
541 if (ai
->ai_canonname
)
543 int len
= WideCharToMultiByte( CP_ACP
, 0, ai
->ai_canonname
, -1, NULL
, 0, NULL
, NULL
);
544 if (!(ret
->ai_canonname
= HeapAlloc( GetProcessHeap(), 0, len
)))
546 HeapFree( GetProcessHeap(), 0, ret
);
549 WideCharToMultiByte( CP_ACP
, 0, ai
->ai_canonname
, -1, ret
->ai_canonname
, len
, NULL
, NULL
);
553 if (!(ret
->ai_addr
= HeapAlloc( GetProcessHeap(), 0, sizeof(struct WS_sockaddr
) )))
555 HeapFree( GetProcessHeap(), 0, ret
->ai_canonname
);
556 HeapFree( GetProcessHeap(), 0, ret
);
559 memcpy( ret
->ai_addr
, ai
->ai_addr
, sizeof(struct WS_sockaddr
) );
564 struct getaddrinfo_args
566 OVERLAPPED
*overlapped
;
567 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine
;
568 ADDRINFOEXW
**result
;
571 struct WS_addrinfo
*hints
;
574 static void WINAPI
getaddrinfo_callback(TP_CALLBACK_INSTANCE
*instance
, void *context
)
576 struct getaddrinfo_args
*args
= context
;
577 OVERLAPPED
*overlapped
= args
->overlapped
;
578 HANDLE event
= overlapped
->hEvent
;
579 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine
= args
->completion_routine
;
580 struct WS_addrinfo
*res
;
583 ret
= WS_getaddrinfo( args
->nodename
, args
->servname
, args
->hints
, &res
);
586 *args
->result
= addrinfo_list_AtoW(res
);
587 overlapped
->u
.Pointer
= args
->result
;
588 WS_freeaddrinfo(res
);
591 HeapFree( GetProcessHeap(), 0, args
->nodename
);
592 HeapFree( GetProcessHeap(), 0, args
->servname
);
593 HeapFree( GetProcessHeap(), 0, args
);
595 overlapped
->Internal
= ret
;
596 if (completion_routine
) completion_routine( ret
, 0, overlapped
);
597 if (event
) SetEvent( event
);
600 static int WS_getaddrinfoW( const WCHAR
*nodename
, const WCHAR
*servname
,
601 const struct WS_addrinfo
*hints
, ADDRINFOEXW
**res
, OVERLAPPED
*overlapped
,
602 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine
)
604 int ret
= EAI_MEMORY
, len
, i
;
605 char *nodenameA
= NULL
, *servnameA
= NULL
;
606 struct WS_addrinfo
*resA
;
607 WCHAR
*local_nodenameW
= (WCHAR
*)nodename
;
612 /* Is this an IDN? Most likely if any char is above the Ascii table, this
613 * is the simplest validation possible, further validation will be done by
614 * the native getaddrinfo() */
615 for (i
= 0; nodename
[i
]; i
++)
617 if (nodename
[i
] > 'z')
622 if (hints
&& (hints
->ai_flags
& WS_AI_DISABLE_IDN_ENCODING
))
624 /* Name requires conversion but it was disabled */
625 ret
= WSAHOST_NOT_FOUND
;
630 len
= IdnToAscii( 0, nodename
, -1, NULL
, 0 );
633 ERR("Failed to convert %s to punycode\n", debugstr_w(nodename
));
637 if (!(local_nodenameW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) ))) goto end
;
638 IdnToAscii( 0, nodename
, -1, local_nodenameW
, len
);
643 len
= WideCharToMultiByte( CP_ACP
, 0, local_nodenameW
, -1, NULL
, 0, NULL
, NULL
);
644 if (!(nodenameA
= HeapAlloc( GetProcessHeap(), 0, len
))) goto end
;
645 WideCharToMultiByte( CP_ACP
, 0, local_nodenameW
, -1, nodenameA
, len
, NULL
, NULL
);
649 len
= WideCharToMultiByte( CP_ACP
, 0, servname
, -1, NULL
, 0, NULL
, NULL
);
650 if (!(servnameA
= HeapAlloc( GetProcessHeap(), 0, len
))) goto end
;
651 WideCharToMultiByte( CP_ACP
, 0, servname
, -1, servnameA
, len
, NULL
, NULL
);
656 struct getaddrinfo_args
*args
;
658 if (overlapped
->hEvent
&& completion_routine
)
664 if (!(args
= HeapAlloc( GetProcessHeap(), 0, sizeof(*args
) + sizeof(*args
->hints
) ))) goto end
;
665 args
->overlapped
= overlapped
;
666 args
->completion_routine
= completion_routine
;
668 args
->nodename
= nodenameA
;
669 args
->servname
= servnameA
;
672 args
->hints
= (struct WS_addrinfo
*)(args
+ 1);
673 args
->hints
->ai_flags
= hints
->ai_flags
;
674 args
->hints
->ai_family
= hints
->ai_family
;
675 args
->hints
->ai_socktype
= hints
->ai_socktype
;
676 args
->hints
->ai_protocol
= hints
->ai_protocol
;
678 else args
->hints
= NULL
;
680 overlapped
->Internal
= WSAEINPROGRESS
;
681 if (!TrySubmitThreadpoolCallback( getaddrinfo_callback
, args
, NULL
))
683 HeapFree( GetProcessHeap(), 0, args
);
684 ret
= GetLastError();
688 if (local_nodenameW
!= nodename
)
689 HeapFree( GetProcessHeap(), 0, local_nodenameW
);
690 SetLastError( ERROR_IO_PENDING
);
691 return ERROR_IO_PENDING
;
694 ret
= WS_getaddrinfo( nodenameA
, servnameA
, hints
, &resA
);
697 *res
= addrinfo_list_AtoW( resA
);
698 WS_freeaddrinfo( resA
);
702 if (local_nodenameW
!= nodename
)
703 HeapFree( GetProcessHeap(), 0, local_nodenameW
);
704 HeapFree( GetProcessHeap(), 0, nodenameA
);
705 HeapFree( GetProcessHeap(), 0, servnameA
);
710 /***********************************************************************
711 * GetAddrInfoExW (ws2_32.@)
713 int WINAPI
GetAddrInfoExW( const WCHAR
*name
, const WCHAR
*servname
, DWORD
namespace,
714 GUID
*namespace_id
, const ADDRINFOEXW
*hints
, ADDRINFOEXW
**result
,
715 struct WS_timeval
*timeout
, OVERLAPPED
*overlapped
,
716 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine
, HANDLE
*handle
)
720 TRACE( "name %s, servname %s, namespace %u, namespace_id %s)\n",
721 debugstr_w(name
), debugstr_w(servname
), namespace, debugstr_guid(namespace_id
) );
723 if (namespace != NS_DNS
)
724 FIXME( "Unsupported namespace %u\n", namespace );
726 FIXME( "Unsupported namespace_id %s\n", debugstr_guid(namespace_id
) );
728 FIXME( "Unsupported timeout\n" );
730 FIXME( "Unsupported cancel handle\n" );
732 ret
= WS_getaddrinfoW( name
, servname
, (struct WS_addrinfo
*)hints
, result
, overlapped
, completion_routine
);
734 if (handle
) *handle
= (HANDLE
)0xdeadbeef;
739 /***********************************************************************
740 * GetAddrInfoExOverlappedResult (ws2_32.@)
742 int WINAPI
GetAddrInfoExOverlappedResult( OVERLAPPED
*overlapped
)
744 TRACE( "(%p)\n", overlapped
);
745 return overlapped
->Internal
;
749 /***********************************************************************
750 * GetAddrInfoExCancel (ws2_32.@)
752 int WINAPI
GetAddrInfoExCancel( HANDLE
*handle
)
754 FIXME( "(%p)\n", handle
);
755 return WSA_INVALID_HANDLE
;
759 /***********************************************************************
760 * GetAddrInfoW (ws2_32.@)
762 int WINAPI
GetAddrInfoW(const WCHAR
*nodename
, const WCHAR
*servname
, const ADDRINFOW
*hints
, ADDRINFOW
**res
)
764 struct WS_addrinfo
*hintsA
= NULL
;
766 int ret
= EAI_MEMORY
;
768 TRACE( "nodename %s, servname %s, hints %p, result %p\n",
769 debugstr_w(nodename
), debugstr_w(servname
), hints
, res
);
772 if (hints
) hintsA
= addrinfo_WtoA( hints
);
773 ret
= WS_getaddrinfoW( nodename
, servname
, hintsA
, &resex
, NULL
, NULL
);
774 WS_freeaddrinfo( hintsA
);
779 /* ADDRINFOEXW has a layout compatible with ADDRINFOW except for the
780 * ai_next field, so we may convert it in place */
781 *res
= (ADDRINFOW
*)resex
;
784 ((ADDRINFOW
*)resex
)->ai_next
= (ADDRINFOW
*)resex
->ai_next
;
785 resex
= resex
->ai_next
;
792 /***********************************************************************
793 * freeaddrinfo (ws2_32.@)
795 void WINAPI
WS_freeaddrinfo( struct WS_addrinfo
*res
)
799 struct WS_addrinfo
*next
;
801 HeapFree( GetProcessHeap(), 0, res
->ai_canonname
);
802 HeapFree( GetProcessHeap(), 0, res
->ai_addr
);
804 HeapFree( GetProcessHeap(), 0, res
);
810 /***********************************************************************
811 * FreeAddrInfoW (ws2_32.@)
813 void WINAPI
FreeAddrInfoW( ADDRINFOW
*ai
)
818 HeapFree( GetProcessHeap(), 0, ai
->ai_canonname
);
819 HeapFree( GetProcessHeap(), 0, ai
->ai_addr
);
821 HeapFree( GetProcessHeap(), 0, ai
);
827 /***********************************************************************
828 * FreeAddrInfoEx (ws2_32.@)
830 void WINAPI
FreeAddrInfoEx( ADDRINFOEXA
*ai
)
832 TRACE( "(%p)\n", ai
);
837 HeapFree( GetProcessHeap(), 0, ai
->ai_canonname
);
838 HeapFree( GetProcessHeap(), 0, ai
->ai_addr
);
840 HeapFree( GetProcessHeap(), 0, ai
);
846 /***********************************************************************
847 * FreeAddrInfoExW (ws2_32.@)
849 void WINAPI
FreeAddrInfoExW( ADDRINFOEXW
*ai
)
851 TRACE( "(%p)\n", ai
);
856 HeapFree( GetProcessHeap(), 0, ai
->ai_canonname
);
857 HeapFree( GetProcessHeap(), 0, ai
->ai_addr
);
859 HeapFree( GetProcessHeap(), 0, ai
);
865 static const int ws_niflag_map
[][2] =
867 MAP_OPTION( NI_NOFQDN
),
868 MAP_OPTION( NI_NUMERICHOST
),
869 MAP_OPTION( NI_NAMEREQD
),
870 MAP_OPTION( NI_NUMERICSERV
),
871 MAP_OPTION( NI_DGRAM
),
874 static int convert_niflag_w2u( int winflags
)
879 for (i
= 0; i
< ARRAY_SIZE(ws_niflag_map
); i
++)
881 if (ws_niflag_map
[i
][0] & winflags
)
883 unixflags
|= ws_niflag_map
[i
][1];
884 winflags
&= ~ws_niflag_map
[i
][0];
888 FIXME("Unhandled windows NI_xxx flags 0x%x\n", winflags
);
893 /***********************************************************************
894 * getnameinfo (ws2_32.@)
896 int WINAPI
WS_getnameinfo( const SOCKADDR
*addr
, WS_socklen_t addr_len
, char *host
,
897 DWORD host_len
, char *serv
, DWORD serv_len
, int flags
)
899 #ifdef HAVE_GETNAMEINFO
901 union generic_unix_sockaddr uaddr
;
902 unsigned int uaddr_len
;
904 TRACE( "addr %s, addr_len %d, host %p, host_len %u, serv %p, serv_len %d, flags %#x\n",
905 debugstr_sockaddr(addr
), addr_len
, host
, host_len
, serv
, serv_len
, flags
);
907 uaddr_len
= ws_sockaddr_ws2u( addr
, addr_len
, &uaddr
);
910 SetLastError( WSAEFAULT
);
911 return WSA_NOT_ENOUGH_MEMORY
;
913 ret
= getnameinfo( &uaddr
.addr
, uaddr_len
, host
, host_len
, serv
, serv_len
, convert_niflag_w2u(flags
) );
914 return convert_eai_u2w( ret
);
916 FIXME( "getnameinfo() failed, not found during buildtime.\n" );
922 /***********************************************************************
923 * GetNameInfoW (ws2_32.@)
925 int WINAPI
GetNameInfoW( const SOCKADDR
*addr
, WS_socklen_t addr_len
, WCHAR
*host
,
926 DWORD host_len
, WCHAR
*serv
, DWORD serv_len
, int flags
)
929 char *hostA
= NULL
, *servA
= NULL
;
931 if (host
&& (!(hostA
= HeapAlloc( GetProcessHeap(), 0, host_len
))))
933 if (serv
&& (!(servA
= HeapAlloc( GetProcessHeap(), 0, serv_len
))))
935 HeapFree( GetProcessHeap(), 0, hostA
);
939 ret
= WS_getnameinfo( addr
, addr_len
, hostA
, host_len
, servA
, serv_len
, flags
);
942 if (host
) MultiByteToWideChar( CP_ACP
, 0, hostA
, -1, host
, host_len
);
943 if (serv
) MultiByteToWideChar( CP_ACP
, 0, servA
, -1, serv
, serv_len
);
946 HeapFree( GetProcessHeap(), 0, hostA
);
947 HeapFree( GetProcessHeap(), 0, servA
);
952 static UINT
host_errno_from_unix( int err
)
958 case HOST_NOT_FOUND
: return WSAHOST_NOT_FOUND
;
959 case TRY_AGAIN
: return WSATRY_AGAIN
;
960 case NO_RECOVERY
: return WSANO_RECOVERY
;
961 case NO_DATA
: return WSANO_DATA
;
962 case ENOBUFS
: return WSAENOBUFS
;
965 WARN( "Unknown h_errno %d!\n", err
);
966 return WSAEOPNOTSUPP
;
970 static struct WS_hostent
*get_hostent_buffer( unsigned int size
)
972 struct per_thread_data
*data
= get_per_thread_data();
975 if (data
->he_len
>= size
) return data
->he_buffer
;
976 HeapFree( GetProcessHeap(), 0, data
->he_buffer
);
978 data
->he_buffer
= HeapAlloc( GetProcessHeap(), 0, (data
->he_len
= size
) );
979 if (!data
->he_buffer
) SetLastError(WSAENOBUFS
);
980 return data
->he_buffer
;
983 /* create a hostent entry
985 * Creates the entry with enough memory for the name, aliases
986 * addresses, and the address pointers. Also copies the name
987 * and sets up all the pointers.
989 * NOTE: The alias and address lists must be allocated with room
990 * for the NULL item terminating the list. This is true even if
991 * the list has no items ("aliases" and "addresses" must be
992 * at least "1", a truly empty list is invalid).
994 static struct WS_hostent
*create_hostent( char *name
, int alias_count
, int aliases_size
,
995 int address_count
, int address_length
)
997 struct WS_hostent
*p_to
;
999 unsigned int size
= sizeof(struct WS_hostent
), i
;
1001 size
+= strlen(name
) + 1;
1002 size
+= alias_count
* sizeof(char *);
1003 size
+= aliases_size
;
1004 size
+= address_count
* sizeof(char *);
1005 size
+= (address_count
- 1) * address_length
;
1007 if (!(p_to
= get_hostent_buffer( size
))) return NULL
;
1008 memset( p_to
, 0, size
);
1010 /* Use the memory in the same way winsock does.
1011 * First set the pointer for aliases, second set the pointers for addresses.
1012 * Third fill the addresses indexes, fourth jump aliases names size.
1013 * Fifth fill the hostname.
1014 * NOTE: This method is valid for OS versions >= XP.
1016 p
= (char *)(p_to
+ 1);
1017 p_to
->h_aliases
= (char **)p
;
1018 p
+= alias_count
* sizeof(char *);
1020 p_to
->h_addr_list
= (char **)p
;
1021 p
+= address_count
* sizeof(char *);
1023 for (i
= 0, address_count
--; i
< address_count
; i
++, p
+= address_length
)
1024 p_to
->h_addr_list
[i
] = p
;
1026 /* h_aliases must be filled in manually because we don't know each string
1027 * size. Leave these pointers NULL (already set to NULL by memset earlier).
1037 static struct WS_hostent
*hostent_from_unix( const struct hostent
*p_he
)
1039 int i
, addresses
= 0, alias_size
= 0;
1040 struct WS_hostent
*p_to
;
1043 for (i
= 0; p_he
->h_aliases
[i
]; i
++)
1044 alias_size
+= strlen( p_he
->h_aliases
[i
] ) + 1;
1045 while (p_he
->h_addr_list
[addresses
])
1048 p_to
= create_hostent( p_he
->h_name
, i
+ 1, alias_size
, addresses
+ 1, p_he
->h_length
);
1050 if (!p_to
) return NULL
;
1051 p_to
->h_addrtype
= convert_af_u2w( p_he
->h_addrtype
);
1052 p_to
->h_length
= p_he
->h_length
;
1054 for (i
= 0, p
= p_to
->h_addr_list
[0]; p_he
->h_addr_list
[i
]; i
++, p
+= p_to
->h_length
)
1055 memcpy( p
, p_he
->h_addr_list
[i
], p_to
->h_length
);
1057 /* Fill the aliases after the IP data */
1058 for (i
= 0; p_he
->h_aliases
[i
]; i
++)
1060 p_to
->h_aliases
[i
] = p
;
1061 strcpy( p
, p_he
->h_aliases
[i
] );
1069 /***********************************************************************
1070 * gethostbyaddr (ws2_32.51)
1072 struct WS_hostent
* WINAPI
WS_gethostbyaddr( const char *addr
, int len
, int type
)
1074 struct WS_hostent
*retval
= NULL
;
1075 struct hostent
*host
;
1076 int unixtype
= convert_af_w2u(type
);
1077 const char *paddr
= addr
;
1078 unsigned long loopback
;
1079 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
1081 int ebufsize
= 1024;
1082 struct hostent hostentry
;
1083 int locerr
= ENOBUFS
;
1086 /* convert back the magic loopback address if necessary */
1087 if (unixtype
== AF_INET
&& len
== 4 && !memcmp( addr
, magic_loopback_addr
, 4 ))
1089 loopback
= htonl( INADDR_LOOPBACK
);
1090 paddr
= (char *)&loopback
;
1093 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
1095 extrabuf
= HeapAlloc( GetProcessHeap(), 0, ebufsize
);
1098 int res
= gethostbyaddr_r( paddr
, len
, unixtype
, &hostentry
, extrabuf
, ebufsize
, &host
, &locerr
);
1099 if (res
!= ERANGE
) break;
1101 extrabuf
= HeapReAlloc( GetProcessHeap(), 0, extrabuf
, ebufsize
);
1104 retval
= hostent_from_unix( host
);
1106 SetLastError( (locerr
< 0) ? sock_get_error( errno
) : host_errno_from_unix( locerr
) );
1107 HeapFree( GetProcessHeap(), 0, extrabuf
);
1109 EnterCriticalSection( &csWSgetXXXbyYYY
);
1110 host
= gethostbyaddr( paddr
, len
, unixtype
);
1112 retval
= hostent_from_unix( host
);
1114 SetLastError( (h_errno
< 0) ? sock_get_error( errno
) : host_errno_from_unix( h_errno
) );
1115 LeaveCriticalSection( &csWSgetXXXbyYYY
);
1118 TRACE( "ptr %p, len %d, type %d ret %p\n", addr
, len
, type
, retval
);
1125 struct in_addr addr
;
1127 DWORD metric
, default_route
;
1130 static int compare_routes_by_metric_asc( const void *left
, const void *right
)
1132 const struct route
*a
= left
, *b
= right
;
1133 if (a
->default_route
&& b
->default_route
)
1134 return a
->default_route
- b
->default_route
;
1135 if (a
->default_route
&& !b
->default_route
)
1137 if (b
->default_route
&& !a
->default_route
)
1139 return a
->metric
- b
->metric
;
1142 /* Returns the list of local IP addresses by going through the network
1143 * adapters and using the local routing table to sort the addresses
1144 * from highest routing priority to lowest routing priority. This
1145 * functionality is inferred from the description for obtaining local
1146 * IP addresses given in the Knowledge Base Article Q160215.
1148 * Please note that the returned hostent is only freed when the thread
1149 * closes and is replaced if another hostent is requested.
1151 static struct WS_hostent
*get_local_ips( char *hostname
)
1153 int numroutes
= 0, i
, j
, default_routes
= 0;
1154 IP_ADAPTER_INFO
*adapters
= NULL
, *k
;
1155 struct WS_hostent
*hostlist
= NULL
;
1156 MIB_IPFORWARDTABLE
*routes
= NULL
;
1157 struct route
*route_addrs
= NULL
;
1158 DWORD adap_size
, route_size
, n
;
1160 /* Obtain the size of the adapter list and routing table, also allocate memory */
1161 if (GetAdaptersInfo( NULL
, &adap_size
) != ERROR_BUFFER_OVERFLOW
)
1163 if (GetIpForwardTable( NULL
, &route_size
, FALSE
) != ERROR_INSUFFICIENT_BUFFER
)
1166 adapters
= HeapAlloc( GetProcessHeap(), 0, adap_size
);
1167 routes
= HeapAlloc( GetProcessHeap(), 0, route_size
);
1168 if (!adapters
|| !routes
)
1171 /* Obtain the adapter list and the full routing table */
1172 if (GetAdaptersInfo( adapters
, &adap_size
) != NO_ERROR
)
1174 if (GetIpForwardTable( routes
, &route_size
, FALSE
) != NO_ERROR
)
1177 /* Store the interface associated with each route */
1178 for (n
= 0; n
< routes
->dwNumEntries
; n
++)
1181 DWORD ifmetric
, ifdefault
= 0;
1182 BOOL exists
= FALSE
;
1184 /* Check if this is a default route (there may be more than one) */
1185 if (!routes
->table
[n
].dwForwardDest
)
1186 ifdefault
= ++default_routes
;
1187 else if (routes
->table
[n
].u1
.ForwardType
!= MIB_IPROUTE_TYPE_DIRECT
)
1189 ifindex
= routes
->table
[n
].dwForwardIfIndex
;
1190 ifmetric
= routes
->table
[n
].dwForwardMetric1
;
1191 /* Only store the lowest valued metric for an interface */
1192 for (j
= 0; j
< numroutes
; j
++)
1194 if (route_addrs
[j
].interface
== ifindex
)
1196 if (route_addrs
[j
].metric
> ifmetric
)
1197 route_addrs
[j
].metric
= ifmetric
;
1203 route_addrs
= heap_realloc( route_addrs
, (numroutes
+ 1) * sizeof(struct route
) );
1206 route_addrs
[numroutes
].interface
= ifindex
;
1207 route_addrs
[numroutes
].metric
= ifmetric
;
1208 route_addrs
[numroutes
].default_route
= ifdefault
;
1209 /* If no IP is found in the next step (for whatever reason)
1210 * then fall back to the magic loopback address.
1212 memcpy( &route_addrs
[numroutes
].addr
.s_addr
, magic_loopback_addr
, 4 );
1216 goto cleanup
; /* No routes, fall back to the Magic IP */
1218 /* Find the IP address associated with each found interface */
1219 for (i
= 0; i
< numroutes
; i
++)
1221 for (k
= adapters
; k
!= NULL
; k
= k
->Next
)
1223 char *ip
= k
->IpAddressList
.IpAddress
.String
;
1225 if (route_addrs
[i
].interface
== k
->Index
)
1226 route_addrs
[i
].addr
.s_addr
= inet_addr(ip
);
1230 /* Allocate a hostent and enough memory for all the IPs,
1231 * including the NULL at the end of the list.
1233 hostlist
= create_hostent( hostname
, 1, 0, numroutes
+1, sizeof(struct in_addr
) );
1234 if (hostlist
== NULL
)
1236 hostlist
->h_addr_list
[numroutes
] = NULL
;
1237 hostlist
->h_aliases
[0] = NULL
;
1238 hostlist
->h_addrtype
= AF_INET
;
1239 hostlist
->h_length
= sizeof(struct in_addr
);
1241 /* Reorder the entries before placing them in the host list. Windows expects
1242 * the IP list in order from highest priority to lowest (the critical thing
1243 * is that most applications expect the first IP to be the default route).
1246 qsort( route_addrs
, numroutes
, sizeof(struct route
), compare_routes_by_metric_asc
);
1248 for (i
= 0; i
< numroutes
; i
++)
1249 *(struct in_addr
*)hostlist
->h_addr_list
[i
] = route_addrs
[i
].addr
;
1252 HeapFree( GetProcessHeap(), 0, route_addrs
);
1253 HeapFree( GetProcessHeap(), 0, adapters
);
1254 HeapFree( GetProcessHeap(), 0, routes
);
1259 /***********************************************************************
1260 * gethostbyname (ws2_32.52)
1262 struct WS_hostent
* WINAPI
WS_gethostbyname( const char *name
)
1264 struct WS_hostent
*retval
= NULL
;
1265 struct hostent
*host
;
1266 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
1268 int ebufsize
= 1024;
1269 struct hostent hostentry
;
1270 int locerr
= ENOBUFS
;
1276 SetLastError( WSANOTINITIALISED
);
1280 if (gethostname( hostname
, 100 ) == -1)
1282 SetLastError( WSAENOBUFS
);
1286 if (!name
|| !name
[0])
1289 /* If the hostname of the local machine is requested then return the
1290 * complete list of local IP addresses */
1291 if (!strcmp( name
, hostname
))
1292 retval
= get_local_ips( hostname
);
1294 /* If any other hostname was requested (or the routing table lookup failed)
1295 * then return the IP found by the host OS */
1298 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
1300 extrabuf
= HeapAlloc( GetProcessHeap(), 0, ebufsize
);
1303 int res
= gethostbyname_r( name
, &hostentry
, extrabuf
, ebufsize
, &host
, &locerr
);
1304 if (res
!= ERANGE
) break;
1306 extrabuf
= HeapReAlloc( GetProcessHeap(), 0, extrabuf
, ebufsize
);
1308 if (!host
) SetLastError( (locerr
< 0) ? sock_get_error( errno
) : host_errno_from_unix( locerr
) );
1310 EnterCriticalSection( &csWSgetXXXbyYYY
);
1311 host
= gethostbyname( name
);
1312 if (!host
) SetLastError( (h_errno
< 0) ? sock_get_error( errno
) : host_errno_from_unix( h_errno
) );
1314 if (host
) retval
= hostent_from_unix( host
);
1315 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
1316 HeapFree( GetProcessHeap(), 0, extrabuf
);
1318 LeaveCriticalSection( &csWSgetXXXbyYYY
);
1322 if (retval
&& retval
->h_addr_list
[0][0] == 127 && strcmp( name
, "localhost" ))
1324 /* hostname != "localhost" but has loopback address. replace by our
1325 * special address.*/
1326 memcpy( retval
->h_addr_list
[0], magic_loopback_addr
, 4 );
1329 TRACE( "%s ret %p\n", debugstr_a(name
), retval
);
1334 /***********************************************************************
1335 * gethostname (ws2_32.57)
1337 int WINAPI
WS_gethostname( char *name
, int namelen
)
1342 TRACE( "name %p, len %d\n", name
, namelen
);
1346 SetLastError( WSAEFAULT
);
1350 if (gethostname( buf
, sizeof(buf
) ) != 0)
1352 SetLastError( sock_get_error( errno
) );
1356 TRACE( "<- %s\n", debugstr_a(buf
) );
1357 len
= strlen( buf
);
1359 WARN( "Windows supports NetBIOS name length up to 15 bytes!\n" );
1362 SetLastError( WSAEFAULT
);
1365 strcpy( name
, buf
);
1370 /***********************************************************************
1371 * GetHostNameW (ws2_32.@)
1373 int WINAPI
GetHostNameW( WCHAR
*name
, int namelen
)
1377 TRACE( "name %p, len %d\n", name
, namelen
);
1381 SetLastError( WSAEFAULT
);
1385 if (gethostname( buf
, sizeof(buf
) ))
1387 SetLastError( sock_get_error( errno
) );
1391 if (MultiByteToWideChar( CP_ACP
, 0, buf
, -1, NULL
, 0 ) > namelen
)
1393 SetLastError( WSAEFAULT
);
1396 MultiByteToWideChar( CP_ACP
, 0, buf
, -1, name
, namelen
);
1401 static int list_size( char **list
, int item_size
)
1406 for (i
= 0; list
[i
]; i
++)
1407 size
+= (item_size
? item_size
: strlen(list
[i
]) + 1);
1408 size
+= (i
+ 1) * sizeof(char *);
1413 static int list_dup( char **src
, char **dst
, int item_size
)
1418 for (i
= 0; src
[i
]; i
++)
1420 p
= (char *)(dst
+ i
+ 1);
1422 for (i
= 0; src
[i
]; i
++)
1424 int count
= item_size
? item_size
: strlen(src
[i
]) + 1;
1425 memcpy( p
, src
[i
], count
);
1430 return p
- (char *)dst
;
1436 const char *names
[3];
1441 { 1, {"icmp", "ICMP"}},
1442 { 3, {"ggp", "GGP"}},
1443 { 6, {"tcp", "TCP"}},
1444 { 8, {"egp", "EGP"}},
1445 {12, {"pup", "PUP"}},
1446 {17, {"udp", "UDP"}},
1447 {20, {"hmp", "HMP"}},
1448 {22, {"xns-idp", "XNS-IDP"}},
1449 {27, {"rdp", "RDP"}},
1450 {41, {"ipv6", "IPv6"}},
1451 {43, {"ipv6-route", "IPv6-Route"}},
1452 {44, {"ipv6-frag", "IPv6-Frag"}},
1453 {50, {"esp", "ESP"}},
1455 {58, {"ipv6-icmp", "IPv6-ICMP"}},
1456 {59, {"ipv6-nonxt", "IPv6-NoNxt"}},
1457 {60, {"ipv6-opts", "IPv6-Opts"}},
1458 {66, {"rvd", "RVD"}},
1461 static struct WS_protoent
*get_protoent_buffer( unsigned int size
)
1463 struct per_thread_data
*data
= get_per_thread_data();
1465 if (data
->pe_buffer
)
1467 if (data
->pe_len
>= size
) return data
->pe_buffer
;
1468 HeapFree( GetProcessHeap(), 0, data
->pe_buffer
);
1470 data
->pe_len
= size
;
1471 data
->pe_buffer
= HeapAlloc( GetProcessHeap(), 0, size
);
1472 if (!data
->pe_buffer
) SetLastError( WSAENOBUFS
);
1473 return data
->pe_buffer
;
1476 static struct WS_protoent
*create_protoent( const char *name
, char **aliases
, int prot
)
1478 struct WS_protoent
*ret
;
1479 unsigned int size
= sizeof(*ret
) + strlen( name
) + sizeof(char *) + list_size( aliases
, 0 );
1481 if (!(ret
= get_protoent_buffer( size
))) return NULL
;
1482 ret
->p_proto
= prot
;
1483 ret
->p_name
= (char *)(ret
+ 1);
1484 strcpy( ret
->p_name
, name
);
1485 ret
->p_aliases
= (char **)ret
->p_name
+ strlen( name
) / sizeof(char *) + 1;
1486 list_dup( aliases
, ret
->p_aliases
, 0 );
1491 /***********************************************************************
1492 * getprotobyname (ws2_32.53)
1494 struct WS_protoent
* WINAPI
WS_getprotobyname( const char *name
)
1496 struct WS_protoent
*retval
= NULL
;
1499 for (i
= 0; i
< ARRAY_SIZE(protocols
); i
++)
1501 if (!_strnicmp( protocols
[i
].names
[0], name
, -1 ))
1503 retval
= create_protoent( protocols
[i
].names
[0], (char **)protocols
[i
].names
+ 1,
1504 protocols
[i
].prot
);
1510 WARN( "protocol %s not found\n", debugstr_a(name
) );
1511 SetLastError( WSANO_DATA
);
1513 TRACE( "%s ret %p\n", debugstr_a(name
), retval
);
1518 /***********************************************************************
1519 * getprotobynumber (ws2_32.54)
1521 struct WS_protoent
* WINAPI
WS_getprotobynumber( int number
)
1523 struct WS_protoent
*retval
= NULL
;
1526 for (i
= 0; i
< ARRAY_SIZE(protocols
); i
++)
1528 if (protocols
[i
].prot
== number
)
1530 retval
= create_protoent( protocols
[i
].names
[0], (char **)protocols
[i
].names
+ 1,
1531 protocols
[i
].prot
);
1537 WARN( "protocol %d not found\n", number
);
1538 SetLastError( WSANO_DATA
);
1540 TRACE( "%d ret %p\n", number
, retval
);
1545 static char *strdup_lower( const char *str
)
1547 char *ret
= HeapAlloc( GetProcessHeap(), 0, strlen(str
) + 1 );
1552 for (i
= 0; str
[i
]; i
++) ret
[i
] = tolower( str
[i
] );
1555 else SetLastError( WSAENOBUFS
);
1559 static struct WS_servent
*get_servent_buffer( int size
)
1561 struct per_thread_data
*data
= get_per_thread_data();
1562 if (data
->se_buffer
)
1564 if (data
->se_len
>= size
) return data
->se_buffer
;
1565 HeapFree( GetProcessHeap(), 0, data
->se_buffer
);
1567 data
->se_len
= size
;
1568 data
->se_buffer
= HeapAlloc( GetProcessHeap(), 0, size
);
1569 if (!data
->se_buffer
) SetLastError( WSAENOBUFS
);
1570 return data
->se_buffer
;
1573 static struct WS_servent
*servent_from_unix( const struct servent
*p_se
)
1576 struct WS_servent
*p_to
;
1578 int size
= (sizeof(*p_se
) +
1579 strlen(p_se
->s_proto
) + 1 +
1580 strlen(p_se
->s_name
) + 1 +
1581 list_size(p_se
->s_aliases
, 0));
1583 if (!(p_to
= get_servent_buffer( size
))) return NULL
;
1584 p_to
->s_port
= p_se
->s_port
;
1586 p
= (char *)(p_to
+ 1);
1588 strcpy( p
, p_se
->s_name
);
1592 strcpy( p
, p_se
->s_proto
);
1595 p_to
->s_aliases
= (char **)p
;
1596 list_dup( p_se
->s_aliases
, p_to
->s_aliases
, 0 );
1601 /***********************************************************************
1602 * getservbyname (ws2_32.55)
1604 struct WS_servent
* WINAPI
WS_getservbyname( const char *name
, const char *proto
)
1606 struct WS_servent
*retval
= NULL
;
1607 struct servent
*serv
;
1609 char *proto_str
= NULL
;
1611 if (!(name_str
= strdup_lower( name
))) return NULL
;
1613 if (proto
&& *proto
)
1615 if (!(proto_str
= strdup_lower( proto
)))
1617 HeapFree( GetProcessHeap(), 0, name_str
);
1622 EnterCriticalSection( &csWSgetXXXbyYYY
);
1623 serv
= getservbyname( name_str
, proto_str
);
1625 retval
= servent_from_unix( serv
);
1627 SetLastError( WSANO_DATA
);
1628 LeaveCriticalSection( &csWSgetXXXbyYYY
);
1630 HeapFree( GetProcessHeap(), 0, proto_str
);
1631 HeapFree( GetProcessHeap(), 0, name_str
);
1632 TRACE( "%s, %s ret %p\n", debugstr_a(name
), debugstr_a(proto
), retval
);
1637 /***********************************************************************
1638 * getservbyport (ws2_32.56)
1640 struct WS_servent
* WINAPI
WS_getservbyport( int port
, const char *proto
)
1642 struct WS_servent
*retval
= NULL
;
1643 #ifdef HAVE_GETSERVBYPORT
1644 struct servent
*serv
;
1645 char *proto_str
= NULL
;
1647 if (proto
&& *proto
)
1649 if (!(proto_str
= strdup_lower( proto
))) return NULL
;
1652 EnterCriticalSection( &csWSgetXXXbyYYY
);
1653 if ((serv
= getservbyport( port
, proto_str
)))
1654 retval
= servent_from_unix( serv
);
1656 SetLastError( WSANO_DATA
);
1657 LeaveCriticalSection( &csWSgetXXXbyYYY
);
1659 HeapFree( GetProcessHeap(), 0, proto_str
);
1661 TRACE( "%d (i.e. port %d), %s ret %p\n", port
, (int)ntohl(port
), debugstr_a(proto
), retval
);
1666 /***********************************************************************
1667 * inet_ntoa (ws2_32.12)
1669 char * WINAPI
WS_inet_ntoa( struct WS_in_addr in
)
1671 unsigned int long_ip
= ntohl( in
.WS_s_addr
);
1672 struct per_thread_data
*data
= get_per_thread_data();
1674 sprintf( data
->ntoa_buffer
, "%u.%u.%u.%u",
1675 (long_ip
>> 24) & 0xff,
1676 (long_ip
>> 16) & 0xff,
1677 (long_ip
>> 8) & 0xff,
1680 return data
->ntoa_buffer
;
1684 /***********************************************************************
1685 * inet_ntop (ws2_32.@)
1687 const char * WINAPI
WS_inet_ntop( int family
, void *addr
, char *buffer
, SIZE_T len
)
1690 ULONG size
= min( len
, (ULONG
)-1 );
1692 TRACE( "family %d, addr %p, buffer %p, len %ld\n", family
, addr
, buffer
, len
);
1695 SetLastError( STATUS_INVALID_PARAMETER
);
1703 status
= RtlIpv4AddressToStringExA( (IN_ADDR
*)addr
, 0, buffer
, &size
);
1708 status
= RtlIpv6AddressToStringExA( (IN6_ADDR
*)addr
, 0, 0, buffer
, &size
);
1712 SetLastError( WSAEAFNOSUPPORT
);
1716 if (status
== STATUS_SUCCESS
) return buffer
;
1717 SetLastError( STATUS_INVALID_PARAMETER
);
1721 /***********************************************************************
1722 * inet_pton (ws2_32.@)
1724 int WINAPI
WS_inet_pton( int family
, const char *addr
, void *buffer
)
1727 const char *terminator
;
1729 TRACE( "family %d, addr %s, buffer %p\n", family
, debugstr_a(addr
), buffer
);
1731 if (!addr
|| !buffer
)
1733 SetLastError( WSAEFAULT
);
1740 status
= RtlIpv4StringToAddressA(addr
, TRUE
, &terminator
, buffer
);
1743 status
= RtlIpv6StringToAddressA(addr
, &terminator
, buffer
);
1746 SetLastError( WSAEAFNOSUPPORT
);
1750 return (status
== STATUS_SUCCESS
&& *terminator
== 0);
1753 /***********************************************************************
1754 * InetPtonW (ws2_32.@)
1756 int WINAPI
InetPtonW( int family
, const WCHAR
*addr
, void *buffer
)
1762 TRACE( "family %d, addr %s, buffer %p\n", family
, debugstr_w(addr
), buffer
);
1766 SetLastError(WSAEFAULT
);
1767 return SOCKET_ERROR
;
1770 len
= WideCharToMultiByte( CP_ACP
, 0, addr
, -1, NULL
, 0, NULL
, NULL
);
1771 if (!(addrA
= HeapAlloc( GetProcessHeap(), 0, len
)))
1773 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
1776 WideCharToMultiByte( CP_ACP
, 0, addr
, -1, addrA
, len
, NULL
, NULL
);
1778 ret
= WS_inet_pton( family
, addrA
, buffer
);
1779 if (!ret
) SetLastError( WSAEINVAL
);
1781 HeapFree( GetProcessHeap(), 0, addrA
);
1785 /***********************************************************************
1786 * InetNtopW (ws2_32.@)
1788 const WCHAR
* WINAPI
InetNtopW( int family
, void *addr
, WCHAR
*buffer
, SIZE_T len
)
1790 char bufferA
[WS_INET6_ADDRSTRLEN
];
1793 TRACE( "family %d, addr %p, buffer %p, len %ld\n", family
, addr
, buffer
, len
);
1795 if (WS_inet_ntop( family
, addr
, bufferA
, sizeof(bufferA
) ))
1797 if (MultiByteToWideChar( CP_ACP
, 0, bufferA
, -1, buffer
, len
))
1800 SetLastError( ERROR_INVALID_PARAMETER
);
1806 /***********************************************************************
1807 * WSAStringToAddressA (ws2_32.@)
1809 int WINAPI
WSAStringToAddressA( char *string
, int family
, WSAPROTOCOL_INFOA
*protocol_info
,
1810 struct WS_sockaddr
*addr
, int *addr_len
)
1814 TRACE( "string %s, family %u\n", debugstr_a(string
), family
);
1816 if (!addr
|| !addr_len
) return -1;
1820 SetLastError( WSAEINVAL
);
1825 FIXME( "ignoring protocol_info\n" );
1831 struct WS_sockaddr_in
*addr4
= (struct WS_sockaddr_in
*)addr
;
1833 if (*addr_len
< sizeof(struct WS_sockaddr_in
))
1835 *addr_len
= sizeof(struct WS_sockaddr_in
);
1836 SetLastError( WSAEFAULT
);
1839 memset( addr
, 0, sizeof(struct WS_sockaddr_in
) );
1841 status
= RtlIpv4StringToAddressExA( string
, FALSE
, &addr4
->sin_addr
, &addr4
->sin_port
);
1842 if (status
!= STATUS_SUCCESS
)
1844 SetLastError( WSAEINVAL
);
1847 addr4
->sin_family
= WS_AF_INET
;
1848 *addr_len
= sizeof(struct WS_sockaddr_in
);
1853 struct WS_sockaddr_in6
*addr6
= (struct WS_sockaddr_in6
*)addr
;
1855 if (*addr_len
< sizeof(struct WS_sockaddr_in6
))
1857 *addr_len
= sizeof(struct WS_sockaddr_in6
);
1858 SetLastError( WSAEFAULT
);
1861 memset( addr
, 0, sizeof(struct WS_sockaddr_in6
) );
1863 status
= RtlIpv6StringToAddressExA( string
, &addr6
->sin6_addr
, &addr6
->sin6_scope_id
, &addr6
->sin6_port
);
1864 if (status
!= STATUS_SUCCESS
)
1866 SetLastError( WSAEINVAL
);
1869 addr6
->sin6_family
= WS_AF_INET6
;
1870 *addr_len
= sizeof(struct WS_sockaddr_in6
);
1874 /* According to MSDN, only AF_INET and AF_INET6 are supported. */
1875 TRACE( "Unsupported address family specified: %d.\n", family
);
1876 SetLastError( WSAEINVAL
);
1882 /***********************************************************************
1883 * WSAStringToAddressW (ws2_32.@)
1885 int WINAPI
WSAStringToAddressW( WCHAR
*string
, int family
, WSAPROTOCOL_INFOW
*protocol_info
,
1886 struct WS_sockaddr
*addr
, int *addr_len
)
1888 WSAPROTOCOL_INFOA infoA
;
1889 WSAPROTOCOL_INFOA
*protocol_infoA
= NULL
;
1893 TRACE( "string %s, family %u\n", debugstr_w(string
), family
);
1895 if (!addr
|| !addr_len
) return -1;
1899 protocol_infoA
= &infoA
;
1900 memcpy( protocol_infoA
, protocol_info
, FIELD_OFFSET( WSAPROTOCOL_INFOA
, szProtocol
) );
1902 if (!WideCharToMultiByte( CP_ACP
, 0, protocol_info
->szProtocol
, -1, protocol_infoA
->szProtocol
,
1903 sizeof(protocol_infoA
->szProtocol
), NULL
, NULL
))
1905 SetLastError( WSAEINVAL
);
1912 SetLastError( WSAEINVAL
);
1916 sizeA
= WideCharToMultiByte( CP_ACP
, 0, string
, -1, NULL
, 0, NULL
, NULL
);
1917 if (!(stringA
= HeapAlloc( GetProcessHeap(), 0, sizeA
)))
1919 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
1922 WideCharToMultiByte( CP_ACP
, 0, string
, -1, stringA
, sizeA
, NULL
, NULL
);
1923 ret
= WSAStringToAddressA( stringA
, family
, protocol_infoA
, addr
, addr_len
);
1924 HeapFree( GetProcessHeap(), 0, stringA
);
1929 /***********************************************************************
1930 * WSAAddressToStringA (ws2_32.@)
1932 int WINAPI
WSAAddressToStringA( struct WS_sockaddr
*addr
, DWORD addr_len
,
1933 WSAPROTOCOL_INFOA
*info
, char *string
, DWORD
*string_len
)
1935 char buffer
[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
1938 TRACE( "addr %s\n", debugstr_sockaddr(addr
) );
1940 if (!addr
) return SOCKET_ERROR
;
1941 if (!string
|| !string_len
) return SOCKET_ERROR
;
1943 switch (addr
->sa_family
)
1947 const struct WS_sockaddr_in
*addr4
= (const struct WS_sockaddr_in
*)addr
;
1948 unsigned int long_ip
= ntohl( addr4
->sin_addr
.WS_s_addr
);
1951 if (addr_len
< sizeof(struct WS_sockaddr_in
)) return -1;
1952 sprintf( buffer
, "%u.%u.%u.%u:%u",
1953 (long_ip
>> 24) & 0xff,
1954 (long_ip
>> 16) & 0xff,
1955 (long_ip
>> 8) & 0xff,
1957 ntohs( addr4
->sin_port
) );
1959 p
= strchr( buffer
, ':' );
1960 if (!addr4
->sin_port
) *p
= 0;
1965 struct WS_sockaddr_in6
*addr6
= (struct WS_sockaddr_in6
*)addr
;
1969 if (addr_len
< sizeof(struct WS_sockaddr_in6
)) return -1;
1970 if (addr6
->sin6_port
)
1971 strcpy( buffer
, "[" );
1972 len
= strlen( buffer
);
1973 if (!WS_inet_ntop( WS_AF_INET6
, &addr6
->sin6_addr
, &buffer
[len
], sizeof(buffer
) - len
))
1975 SetLastError( WSAEINVAL
);
1978 if (addr6
->sin6_scope_id
)
1979 sprintf( buffer
+ strlen( buffer
), "%%%u", addr6
->sin6_scope_id
);
1980 if (addr6
->sin6_port
)
1981 sprintf( buffer
+ strlen( buffer
), "]:%u", ntohs( addr6
->sin6_port
) );
1986 SetLastError( WSAEINVAL
);
1990 size
= strlen( buffer
) + 1;
1992 if (*string_len
< size
)
1995 SetLastError( WSAEFAULT
);
1999 TRACE( "=> %s, %u bytes\n", debugstr_a(buffer
), size
);
2001 strcpy( string
, buffer
);
2006 /***********************************************************************
2007 * WSAAddressToStringW (ws2_32.@)
2009 int WINAPI
WSAAddressToStringW( struct WS_sockaddr
*addr
, DWORD addr_len
,
2010 WSAPROTOCOL_INFOW
*info
, WCHAR
*string
, DWORD
*string_len
)
2013 char buf
[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
2015 TRACE( "(%p, %d, %p, %p, %p)\n", addr
, addr_len
, info
, string
, string_len
);
2017 if ((ret
= WSAAddressToStringA( addr
, addr_len
, NULL
, buf
, string_len
))) return ret
;
2019 MultiByteToWideChar( CP_ACP
, 0, buf
, *string_len
, string
, *string_len
);
2020 TRACE( "=> %s, %u chars\n", debugstr_w(string
), *string_len
);
2025 /***********************************************************************
2026 * inet_addr (ws2_32.11)
2028 WS_u_long WINAPI
WS_inet_addr( const char *cp
)
2030 if (!cp
) return INADDR_NONE
;
2031 return inet_addr( cp
);
2035 /***********************************************************************
2038 WS_u_long WINAPI
WS_htonl( WS_u_long hostlong
)
2040 return htonl( hostlong
);
2044 /***********************************************************************
2047 WS_u_short WINAPI
WS_htons( WS_u_short hostshort
)
2049 return htons( hostshort
);
2053 /***********************************************************************
2054 * WSAHtonl (ws2_32.@)
2056 int WINAPI
WSAHtonl( SOCKET s
, WS_u_long hostlong
, WS_u_long
*netlong
)
2060 *netlong
= htonl( hostlong
);
2063 SetLastError( WSAEFAULT
);
2068 /***********************************************************************
2069 * WSAHtons (ws2_32.@)
2071 int WINAPI
WSAHtons( SOCKET s
, WS_u_short hostshort
, WS_u_short
*netshort
)
2075 *netshort
= htons( hostshort
);
2078 SetLastError( WSAEFAULT
);
2083 /***********************************************************************
2086 WS_u_long WINAPI
WS_ntohl( WS_u_long netlong
)
2088 return ntohl( netlong
);
2092 /***********************************************************************
2095 WS_u_short WINAPI
WS_ntohs( WS_u_short netshort
)
2097 return ntohs( netshort
);
2101 /***********************************************************************
2102 * WSANtohl (ws2_32.@)
2104 int WINAPI
WSANtohl( SOCKET s
, WS_u_long netlong
, WS_u_long
*hostlong
)
2106 if (!hostlong
) return WSAEFAULT
;
2108 *hostlong
= ntohl( netlong
);
2113 /***********************************************************************
2114 * WSANtohs (ws2_32.@)
2116 int WINAPI
WSANtohs( SOCKET s
, WS_u_short netshort
, WS_u_short
*hostshort
)
2118 if (!hostshort
) return WSAEFAULT
;
2120 *hostshort
= ntohs( netshort
);
2125 /***********************************************************************
2126 * WSAInstallServiceClassA (ws2_32.@)
2128 int WINAPI
WSAInstallServiceClassA( WSASERVICECLASSINFOA
*info
)
2130 FIXME( "Request to install service %s\n", debugstr_a(info
->lpszServiceClassName
) );
2131 SetLastError( WSAEACCES
);
2136 /***********************************************************************
2137 * WSAInstallServiceClassW (ws2_32.@)
2139 int WINAPI
WSAInstallServiceClassW( WSASERVICECLASSINFOW
*info
)
2141 FIXME( "Request to install service %s\n", debugstr_w(info
->lpszServiceClassName
) );
2142 SetLastError( WSAEACCES
);
2147 /***********************************************************************
2148 * WSARemoveServiceClass (ws2_32.@)
2150 int WINAPI
WSARemoveServiceClass( GUID
*info
)
2152 FIXME( "Request to remove service %s\n", debugstr_guid(info
) );
2153 SetLastError( WSATYPE_NOT_FOUND
);
2158 /***********************************************************************
2159 * WSAGetServiceClassInfoA (ws2_32.@)
2161 int WINAPI
WSAGetServiceClassInfoA( GUID
*provider
, GUID
*service
, DWORD
*len
,
2162 WSASERVICECLASSINFOA
*info
)
2164 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider
), debugstr_guid(service
), len
, info
);
2165 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2170 /***********************************************************************
2171 * WSAGetServiceClassInfoW (ws2_32.@)
2173 int WINAPI
WSAGetServiceClassInfoW( GUID
*provider
, GUID
*service
, DWORD
*len
,
2174 WSASERVICECLASSINFOW
*info
)
2176 FIXME( "(%s %s %p %p) Stub!\n", debugstr_guid(provider
), debugstr_guid(service
), len
, info
);
2177 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2182 /***********************************************************************
2183 * WSAGetServiceClassNameByClassIdA (ws2_32.@)
2185 int WINAPI
WSAGetServiceClassNameByClassIdA( GUID
*class, char *service
, DWORD
*len
)
2187 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service
, len
);
2188 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2193 /***********************************************************************
2194 * WSAGetServiceClassNameByClassIdW (ws2_32.@)
2196 int WINAPI
WSAGetServiceClassNameByClassIdW( GUID
*class, WCHAR
*service
, DWORD
*len
)
2198 FIXME( "(%s %p %p) Stub!\n", debugstr_guid(class), service
, len
);
2199 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2204 /***********************************************************************
2205 * WSALookupServiceBeginA (ws2_32.@)
2207 int WINAPI
WSALookupServiceBeginA( WSAQUERYSETA
*query
, DWORD flags
, HANDLE
*lookup
)
2209 FIXME( "(%p 0x%08x %p) Stub!\n", query
, flags
, lookup
);
2210 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2215 /***********************************************************************
2216 * WSALookupServiceBeginW (ws2_32.@)
2218 int WINAPI
WSALookupServiceBeginW( WSAQUERYSETW
*query
, DWORD flags
, HANDLE
*lookup
)
2220 FIXME( "(%p 0x%08x %p) Stub!\n", query
, flags
, lookup
);
2221 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2226 /***********************************************************************
2227 * WSALookupServiceEnd (ws2_32.@)
2229 int WINAPI
WSALookupServiceEnd( HANDLE lookup
)
2231 FIXME("(%p) Stub!\n", lookup
);
2236 /***********************************************************************
2237 * WSALookupServiceNextA (ws2_32.@)
2239 int WINAPI
WSALookupServiceNextA( HANDLE lookup
, DWORD flags
, DWORD
*len
, WSAQUERYSETA
*results
)
2241 FIXME( "(%p 0x%08x %p %p) Stub!\n", lookup
, flags
, len
, results
);
2242 SetLastError( WSA_E_NO_MORE
);
2247 /***********************************************************************
2248 * WSALookupServiceNextW (ws2_32.@)
2250 int WINAPI
WSALookupServiceNextW( HANDLE lookup
, DWORD flags
, DWORD
*len
, WSAQUERYSETW
*results
)
2252 FIXME( "(%p 0x%08x %p %p) Stub!\n", lookup
, flags
, len
, results
);
2253 SetLastError( WSA_E_NO_MORE
);
2258 /***********************************************************************
2259 * WSASetServiceA (ws2_32.@)
2261 int WINAPI
WSASetServiceA( WSAQUERYSETA
*query
, WSAESETSERVICEOP operation
, DWORD flags
)
2263 FIXME( "(%p 0x%08x 0x%08x) Stub!\n", query
, operation
, flags
);
2268 /***********************************************************************
2269 * WSASetServiceW (ws2_32.@)
2271 int WINAPI
WSASetServiceW( WSAQUERYSETW
*query
, WSAESETSERVICEOP operation
, DWORD flags
)
2273 FIXME( "(%p 0x%08x 0x%08x) Stub!\n", query
, operation
, flags
);
2278 /***********************************************************************
2279 * WSAEnumNameSpaceProvidersA (ws2_32.@)
2281 int WINAPI
WSAEnumNameSpaceProvidersA( DWORD
*len
, WSANAMESPACE_INFOA
*buffer
)
2283 FIXME( "(%p %p) Stub!\n", len
, buffer
);
2288 /***********************************************************************
2289 * WSAEnumNameSpaceProvidersW (ws2_32.@)
2291 int WINAPI
WSAEnumNameSpaceProvidersW( DWORD
*len
, WSANAMESPACE_INFOW
*buffer
)
2293 FIXME( "(%p %p) Stub!\n", len
, buffer
);
2298 /***********************************************************************
2299 * WSAProviderConfigChange (ws2_32.@)
2301 int WINAPI
WSAProviderConfigChange( HANDLE
*handle
, OVERLAPPED
*overlapped
,
2302 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion
)
2304 FIXME( "(%p %p %p) Stub!\n", handle
, overlapped
, completion
);
2309 /***********************************************************************
2310 * WSANSPIoctl (ws2_32.@)
2312 int WINAPI
WSANSPIoctl( HANDLE lookup
, DWORD code
, void *in_buffer
,
2313 DWORD in_size
, void *out_buffer
, DWORD out_size
,
2314 DWORD
*ret_size
, WSACOMPLETION
*completion
)
2316 FIXME( "(%p, 0x%08x, %p, 0x%08x, %p, 0x%08x, %p, %p) Stub!\n", lookup
, code
,
2317 in_buffer
, in_size
, out_buffer
, out_size
, ret_size
, completion
);
2318 SetLastError( WSA_NOT_ENOUGH_MEMORY
);
2323 /***********************************************************************
2324 * WSCEnableNSProvider (ws2_32.@)
2326 int WINAPI
WSCEnableNSProvider( GUID
*provider
, BOOL enable
)
2328 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider
), enable
);
2333 /***********************************************************************
2334 * WSCGetProviderInfo (ws2_32.@)
2336 int WINAPI
WSCGetProviderInfo( GUID
*provider
, WSC_PROVIDER_INFO_TYPE info_type
,
2337 BYTE
*info
, size_t *len
, DWORD flags
, int *errcode
)
2339 FIXME( "(%s 0x%08x %p %p 0x%08x %p) Stub!\n",
2340 debugstr_guid(provider
), info_type
, info
, len
, flags
, errcode
);
2347 *errcode
= WSAEFAULT
;
2351 *errcode
= WSANO_RECOVERY
;
2356 /***********************************************************************
2357 * WSCGetProviderPath (ws2_32.@)
2359 int WINAPI
WSCGetProviderPath( GUID
*provider
, WCHAR
*path
, int *len
, int *errcode
)
2361 FIXME( "(%s %p %p %p) Stub!\n", debugstr_guid(provider
), path
, len
, errcode
);
2363 if (!provider
|| !len
)
2366 *errcode
= WSAEFAULT
;
2373 *errcode
= WSAEINVAL
;
2381 /***********************************************************************
2382 * WSCInstallNameSpace (ws2_32.@)
2384 int WINAPI
WSCInstallNameSpace( WCHAR
*identifier
, WCHAR
*path
, DWORD
namespace,
2385 DWORD version
, GUID
*provider
)
2387 FIXME( "(%s %s 0x%08x 0x%08x %s) Stub!\n", debugstr_w(identifier
), debugstr_w(path
),
2388 namespace, version
, debugstr_guid(provider
) );
2393 /***********************************************************************
2394 * WSCUnInstallNameSpace (ws2_32.@)
2396 int WINAPI
WSCUnInstallNameSpace( GUID
*provider
)
2398 FIXME( "(%s) Stub!\n", debugstr_guid(provider
) );
2403 /***********************************************************************
2404 * WSCWriteProviderOrder (ws2_32.@)
2406 int WINAPI
WSCWriteProviderOrder( DWORD
*entry
, DWORD number
)
2408 FIXME( "(%p 0x%08x) Stub!\n", entry
, number
);
2413 /***********************************************************************
2414 * WSCInstallProvider (ws2_32.@)
2416 int WINAPI
WSCInstallProvider( GUID
*provider
, const WCHAR
*path
,
2417 WSAPROTOCOL_INFOW
*protocol_info
, DWORD count
, int *err
)
2419 FIXME( "(%s, %s, %p, %d, %p): stub !\n", debugstr_guid(provider
),
2420 debugstr_w(path
), protocol_info
, count
, err
);
2426 /***********************************************************************
2427 * WSCDeinstallProvider (ws2_32.@)
2429 int WINAPI
WSCDeinstallProvider( GUID
*provider
, int *err
)
2431 FIXME( "(%s, %p): stub !\n", debugstr_guid(provider
), err
);
2437 /***********************************************************************
2438 * WSCSetApplicationCategory (ws2_32.@)
2440 int WINAPI
WSCSetApplicationCategory( const WCHAR
*path
, DWORD len
, const WCHAR
*extra
, DWORD extralen
,
2441 DWORD lspcat
, DWORD
*prev_lspcat
, int *err
)
2443 FIXME( "(%s %d %s %d %d %p) Stub!\n", debugstr_w(path
), len
, debugstr_w(extra
),
2444 extralen
, lspcat
, prev_lspcat
);
2449 /***********************************************************************
2450 * WSCEnumProtocols (ws2_32.@)
2452 int WINAPI
WSCEnumProtocols( int *protocols
, WSAPROTOCOL_INFOW
*info
, DWORD
*len
, int *err
)
2454 int ret
= WSAEnumProtocolsW( protocols
, info
, len
);
2456 if (ret
== SOCKET_ERROR
) *err
= WSAENOBUFS
;