mfmediaengine: Handle Play() when called before topology is set.
[wine.git] / dlls / ws2_32 / protocol.c
blob15616fdaf34055f579aa372f2c051154d400f001
1 /*
2 * Protocol-level socket functions
4 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
5 * Copyright (C) 2001 Stefan Leichter
6 * Copyright (C) 2004 Hans Leidekker
7 * Copyright (C) 2005 Marcus Meissner
8 * Copyright (C) 2006-2008 Kai Blin
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
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 ),
41 #ifdef AI_NUMERICSERV
42 MAP_OPTION( AI_NUMERICSERV ),
43 #endif
44 #ifdef AI_V4MAPPED
45 MAP_OPTION( AI_V4MAPPED ),
46 #endif
47 MAP_OPTION( AI_ALL ),
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. */
60 #ifdef EAI_NODATA
61 MAP_OPTION( EAI_NODATA ),
62 #endif
63 #ifdef EAI_NONAME
64 { WS_EAI_NODATA, EAI_NONAME },
65 #endif
66 MAP_OPTION( EAI_SERVICE ),
67 MAP_OPTION( EAI_SOCKTYPE ),
68 { 0, 0 }
71 static const int ws_af_map[][2] =
73 MAP_OPTION( AF_UNSPEC ),
74 MAP_OPTION( AF_INET ),
75 MAP_OPTION( AF_INET6 ),
76 #ifdef HAS_IPX
77 MAP_OPTION( AF_IPX ),
78 #endif
79 #ifdef AF_IRDA
80 MAP_OPTION( AF_IRDA ),
81 #endif
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 )
102 unsigned int i;
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 );
110 return -1;
113 static int convert_af_u2w( int family )
115 unsigned int i;
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 );
123 return -1;
126 static int convert_proto_w2u( int protocol )
128 unsigned int i;
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))
137 return protocol;
139 FIXME( "unhandled Windows socket protocol %d\n", protocol );
140 return -1;
143 static int convert_proto_u2w( int protocol )
145 unsigned int i;
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))
156 return protocol;
158 FIXME("unhandled UNIX socket protocol %d\n", protocol);
159 return -1;
162 static int convert_aiflag_w2u( int winflags )
164 unsigned int i;
165 int unixflags = 0;
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];
175 if (winflags)
176 FIXME( "Unhandled windows AI_xxx flags 0x%x\n", winflags );
177 return unixflags;
180 static int convert_aiflag_u2w( int unixflags )
182 unsigned int i;
183 int winflags = 0;
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];
193 if (unixflags)
194 WARN( "Unhandled UNIX AI_xxx flags 0x%x\n", unixflags );
195 return winflags;
198 int convert_eai_u2w( int unixret )
200 int i;
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);
216 return unixret;
219 static char *get_fqdn(void)
221 char *ret;
222 DWORD size = 0;
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 );
230 return NULL;
232 return ret;
235 static BOOL addrinfo_in_list( const struct WS_addrinfo *list, const struct WS_addrinfo *ai )
237 const struct WS_addrinfo *cursor = list;
238 while (cursor)
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)))
249 return TRUE;
251 cursor = cursor->ai_next;
253 return FALSE;
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;
265 int result;
266 struct addrinfo unixhints, *punixhints = NULL;
267 char *nodev6 = NULL, *fqdn = NULL;
268 const char *node;
270 *res = NULL;
271 if (!nodename && !servname)
273 SetLastError(WSAHOST_NOT_FOUND);
274 return WSAHOST_NOT_FOUND;
277 if (!nodename)
278 node = NULL;
279 else if (!nodename[0])
281 if (!(fqdn = get_fqdn())) return WSA_NOT_ENOUGH_MEMORY;
282 node = fqdn;
284 else
286 node = nodename;
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)
291 char *close_bracket;
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 );
298 node = nodev6;
303 /* servname tweak required by OSX and BSD kernels */
304 if (servname && !servname[0]) servname = "0";
306 if (hints)
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 );
326 return -1;
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
357 * is invalid */
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 );
363 result = EAI_NONAME;
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 );
371 if (!result)
373 struct addrinfo *xuai = unixaires;
374 struct WS_addrinfo **xai = res;
376 *xai = NULL;
377 while (xuai)
379 struct WS_addrinfo *ai = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct WS_addrinfo) );
380 SIZE_T len;
382 if (!ai)
383 goto outofmem;
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 */
388 if (hints)
390 ai->ai_socktype = hints->ai_socktype;
391 ai->ai_protocol = hints->ai_protocol;
393 else
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)
403 goto outofmem;
404 strcpy( ai->ai_canonname, xuai->ai_canonname );
406 len = xuai->ai_addrlen;
407 ai->ai_addr = HeapAlloc( GetProcessHeap(), 0, len );
408 if (!ai->ai_addr)
409 goto outofmem;
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;
418 break;
420 len *= 2;
421 ai->ai_addr = HeapReAlloc( GetProcessHeap(), 0, ai->ai_addr, len );
422 if (!ai->ai_addr)
423 goto outofmem;
424 ai->ai_addrlen = len;
425 } while (1);
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 );
433 else
435 *xai = ai;
436 xai = &ai->ai_next;
438 xuai = xuai->ai_next;
440 freeaddrinfo( unixaires );
442 if (TRACE_ON(winsock))
444 struct WS_addrinfo *ai = *res;
445 while (ai)
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) );
450 ai = ai->ai_next;
454 else
455 result = convert_eai_u2w( result );
457 SetLastError( result );
458 return result;
460 outofmem:
461 if (*res) WS_freeaddrinfo( *res );
462 if (unixaires) freeaddrinfo( unixaires );
463 return WSA_NOT_ENOUGH_MEMORY;
464 #else
465 FIXME( "getaddrinfo() failed, not found during build time.\n" );
466 return EAI_FAIL;
467 #endif
471 static ADDRINFOEXW *addrinfo_AtoW( const struct WS_addrinfo *ai )
473 ADDRINFOEXW *ret;
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;
482 ret->ai_addr = NULL;
483 ret->ai_blob = NULL;
484 ret->ai_bloblen = 0;
485 ret->ai_provider = NULL;
486 ret->ai_next = 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 );
493 return NULL;
495 MultiByteToWideChar( CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len );
497 if (ai->ai_addr)
499 if (!(ret->ai_addr = HeapAlloc( GetProcessHeap(), 0, ai->ai_addrlen )))
501 HeapFree( GetProcessHeap(), 0, ret->ai_canonname );
502 HeapFree( GetProcessHeap(), 0, ret );
503 return NULL;
505 memcpy( ret->ai_addr, ai->ai_addr, ai->ai_addrlen );
507 return ret;
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 );
520 return NULL;
522 infoW = infoW->ai_next;
523 info = info->ai_next;
525 return ret;
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;
539 ret->ai_addr = NULL;
540 ret->ai_next = 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 );
547 return NULL;
549 WideCharToMultiByte( CP_ACP, 0, ai->ai_canonname, -1, ret->ai_canonname, len, NULL, NULL );
551 if (ai->ai_addr)
553 if (!(ret->ai_addr = HeapAlloc( GetProcessHeap(), 0, sizeof(struct WS_sockaddr) )))
555 HeapFree( GetProcessHeap(), 0, ret->ai_canonname );
556 HeapFree( GetProcessHeap(), 0, ret );
557 return NULL;
559 memcpy( ret->ai_addr, ai->ai_addr, sizeof(struct WS_sockaddr) );
561 return ret;
564 struct getaddrinfo_args
566 OVERLAPPED *overlapped;
567 LPLOOKUPSERVICE_COMPLETION_ROUTINE completion_routine;
568 ADDRINFOEXW **result;
569 char *nodename;
570 char *servname;
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;
581 int ret;
583 ret = WS_getaddrinfo( args->nodename, args->servname, args->hints, &res );
584 if (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;
609 *res = NULL;
610 if (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')
618 break;
620 if (nodename[i])
622 if (hints && (hints->ai_flags & WS_AI_DISABLE_IDN_ENCODING))
624 /* Name requires conversion but it was disabled */
625 ret = WSAHOST_NOT_FOUND;
626 SetLastError( ret );
627 goto end;
630 len = IdnToAscii( 0, nodename, -1, NULL, 0 );
631 if (!len)
633 ERR("Failed to convert %s to punycode\n", debugstr_w(nodename));
634 ret = EAI_FAIL;
635 goto end;
637 if (!(local_nodenameW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) goto end;
638 IdnToAscii( 0, nodename, -1, local_nodenameW, len );
641 if (local_nodenameW)
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 );
647 if (servname)
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 );
654 if (overlapped)
656 struct getaddrinfo_args *args;
658 if (overlapped->hEvent && completion_routine)
660 ret = WSAEINVAL;
661 goto end;
664 if (!(args = HeapAlloc( GetProcessHeap(), 0, sizeof(*args) + sizeof(*args->hints) ))) goto end;
665 args->overlapped = overlapped;
666 args->completion_routine = completion_routine;
667 args->result = res;
668 args->nodename = nodenameA;
669 args->servname = servnameA;
670 if (hints)
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();
685 goto end;
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 );
695 if (!ret)
697 *res = addrinfo_list_AtoW( resA );
698 WS_freeaddrinfo( resA );
701 end:
702 if (local_nodenameW != nodename)
703 HeapFree( GetProcessHeap(), 0, local_nodenameW );
704 HeapFree( GetProcessHeap(), 0, nodenameA );
705 HeapFree( GetProcessHeap(), 0, servnameA );
706 return ret;
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 )
718 int ret;
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 );
725 if (namespace_id)
726 FIXME( "Unsupported namespace_id %s\n", debugstr_guid(namespace_id) );
727 if (timeout)
728 FIXME( "Unsupported timeout\n" );
729 if (handle)
730 FIXME( "Unsupported cancel handle\n" );
732 ret = WS_getaddrinfoW( name, servname, (struct WS_addrinfo *)hints, result, overlapped, completion_routine );
733 if (ret) return ret;
734 if (handle) *handle = (HANDLE)0xdeadbeef;
735 return 0;
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;
765 ADDRINFOEXW *resex;
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 );
771 *res = NULL;
772 if (hints) hintsA = addrinfo_WtoA( hints );
773 ret = WS_getaddrinfoW( nodename, servname, hintsA, &resex, NULL, NULL );
774 WS_freeaddrinfo( hintsA );
775 if (ret) return ret;
777 if (resex)
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;
786 } while (resex);
788 return 0;
792 /***********************************************************************
793 * freeaddrinfo (ws2_32.@)
795 void WINAPI WS_freeaddrinfo( struct WS_addrinfo *res )
797 while (res)
799 struct WS_addrinfo *next;
801 HeapFree( GetProcessHeap(), 0, res->ai_canonname );
802 HeapFree( GetProcessHeap(), 0, res->ai_addr );
803 next = res->ai_next;
804 HeapFree( GetProcessHeap(), 0, res );
805 res = next;
810 /***********************************************************************
811 * FreeAddrInfoW (ws2_32.@)
813 void WINAPI FreeAddrInfoW( ADDRINFOW *ai )
815 while (ai)
817 ADDRINFOW *next;
818 HeapFree( GetProcessHeap(), 0, ai->ai_canonname );
819 HeapFree( GetProcessHeap(), 0, ai->ai_addr );
820 next = ai->ai_next;
821 HeapFree( GetProcessHeap(), 0, ai );
822 ai = next;
827 /***********************************************************************
828 * FreeAddrInfoEx (ws2_32.@)
830 void WINAPI FreeAddrInfoEx( ADDRINFOEXA *ai )
832 TRACE( "(%p)\n", ai );
834 while (ai)
836 ADDRINFOEXA *next;
837 HeapFree( GetProcessHeap(), 0, ai->ai_canonname );
838 HeapFree( GetProcessHeap(), 0, ai->ai_addr );
839 next = ai->ai_next;
840 HeapFree( GetProcessHeap(), 0, ai );
841 ai = next;
846 /***********************************************************************
847 * FreeAddrInfoExW (ws2_32.@)
849 void WINAPI FreeAddrInfoExW( ADDRINFOEXW *ai )
851 TRACE( "(%p)\n", ai );
853 while (ai)
855 ADDRINFOEXW *next;
856 HeapFree( GetProcessHeap(), 0, ai->ai_canonname );
857 HeapFree( GetProcessHeap(), 0, ai->ai_addr );
858 next = ai->ai_next;
859 HeapFree( GetProcessHeap(), 0, ai );
860 ai = next;
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 )
876 unsigned int i;
877 int unixflags = 0;
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];
887 if (winflags)
888 FIXME("Unhandled windows NI_xxx flags 0x%x\n", winflags);
889 return unixflags;
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
900 int ret;
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 );
908 if (!uaddr_len)
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 );
915 #else
916 FIXME( "getnameinfo() failed, not found during buildtime.\n" );
917 return EAI_FAIL;
918 #endif
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 )
928 int ret;
929 char *hostA = NULL, *servA = NULL;
931 if (host && (!(hostA = HeapAlloc( GetProcessHeap(), 0, host_len ))))
932 return EAI_MEMORY;
933 if (serv && (!(servA = HeapAlloc( GetProcessHeap(), 0, serv_len ))))
935 HeapFree( GetProcessHeap(), 0, hostA );
936 return EAI_MEMORY;
939 ret = WS_getnameinfo( addr, addr_len, hostA, host_len, servA, serv_len, flags );
940 if (!ret)
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 );
948 return ret;
952 static UINT host_errno_from_unix( int err )
954 WARN( "%d\n", err );
956 switch (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;
963 case 0: return 0;
964 default:
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();
973 if (data->he_buffer)
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;
998 char *p;
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).
1029 p += aliases_size;
1031 p_to->h_name = p;
1032 strcpy( p, name );
1034 return p_to;
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;
1041 char *p;
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])
1046 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] );
1062 p += strlen(p) + 1;
1065 return p_to;
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
1080 char *extrabuf;
1081 int ebufsize = 1024;
1082 struct hostent hostentry;
1083 int locerr = ENOBUFS;
1084 #endif
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
1094 host = NULL;
1095 extrabuf = HeapAlloc( GetProcessHeap(), 0, ebufsize );
1096 while (extrabuf)
1098 int res = gethostbyaddr_r( paddr, len, unixtype, &hostentry, extrabuf, ebufsize, &host, &locerr );
1099 if (res != ERANGE) break;
1100 ebufsize *= 2;
1101 extrabuf = HeapReAlloc( GetProcessHeap(), 0, extrabuf, ebufsize );
1103 if (host)
1104 retval = hostent_from_unix( host );
1105 else
1106 SetLastError( (locerr < 0) ? sock_get_error( errno ) : host_errno_from_unix( locerr ) );
1107 HeapFree( GetProcessHeap(), 0, extrabuf );
1108 #else
1109 EnterCriticalSection( &csWSgetXXXbyYYY );
1110 host = gethostbyaddr( paddr, len, unixtype );
1111 if (host)
1112 retval = hostent_from_unix( host );
1113 else
1114 SetLastError( (h_errno < 0) ? sock_get_error( errno ) : host_errno_from_unix( h_errno ) );
1115 LeaveCriticalSection( &csWSgetXXXbyYYY );
1116 #endif
1118 TRACE( "ptr %p, len %d, type %d ret %p\n", addr, len, type, retval );
1119 return retval;
1123 struct route
1125 struct in_addr addr;
1126 IF_INDEX interface;
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)
1136 return -1;
1137 if (b->default_route && !a->default_route)
1138 return 1;
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)
1162 return NULL;
1163 if (GetIpForwardTable( NULL, &route_size, FALSE ) != ERROR_INSUFFICIENT_BUFFER)
1164 return NULL;
1166 adapters = HeapAlloc( GetProcessHeap(), 0, adap_size );
1167 routes = HeapAlloc( GetProcessHeap(), 0, route_size );
1168 if (!adapters || !routes)
1169 goto cleanup;
1171 /* Obtain the adapter list and the full routing table */
1172 if (GetAdaptersInfo( adapters, &adap_size ) != NO_ERROR)
1173 goto cleanup;
1174 if (GetIpForwardTable( routes, &route_size, FALSE ) != NO_ERROR)
1175 goto cleanup;
1177 /* Store the interface associated with each route */
1178 for (n = 0; n < routes->dwNumEntries; n++)
1180 IF_INDEX ifindex;
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)
1188 continue;
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;
1198 exists = TRUE;
1201 if (exists)
1202 continue;
1203 route_addrs = heap_realloc( route_addrs, (numroutes + 1) * sizeof(struct route) );
1204 if (!route_addrs)
1205 goto cleanup;
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 );
1213 numroutes++;
1215 if (numroutes == 0)
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)
1235 goto cleanup;
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).
1245 if (numroutes > 1)
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;
1251 cleanup:
1252 HeapFree( GetProcessHeap(), 0, route_addrs );
1253 HeapFree( GetProcessHeap(), 0, adapters );
1254 HeapFree( GetProcessHeap(), 0, routes );
1255 return hostlist;
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
1267 char *extrabuf;
1268 int ebufsize = 1024;
1269 struct hostent hostentry;
1270 int locerr = ENOBUFS;
1271 #endif
1272 char hostname[100];
1274 if (!num_startup)
1276 SetLastError( WSANOTINITIALISED );
1277 return NULL;
1280 if (gethostname( hostname, 100 ) == -1)
1282 SetLastError( WSAENOBUFS );
1283 return retval;
1286 if (!name || !name[0])
1287 name = hostname;
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 */
1296 if (!retval)
1298 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
1299 host = NULL;
1300 extrabuf = HeapAlloc( GetProcessHeap(), 0, ebufsize );
1301 while (extrabuf)
1303 int res = gethostbyname_r( name, &hostentry, extrabuf, ebufsize, &host, &locerr );
1304 if (res != ERANGE) break;
1305 ebufsize *= 2;
1306 extrabuf = HeapReAlloc( GetProcessHeap(), 0, extrabuf, ebufsize );
1308 if (!host) SetLastError( (locerr < 0) ? sock_get_error( errno ) : host_errno_from_unix( locerr ) );
1309 #else
1310 EnterCriticalSection( &csWSgetXXXbyYYY );
1311 host = gethostbyname( name );
1312 if (!host) SetLastError( (h_errno < 0) ? sock_get_error( errno ) : host_errno_from_unix( h_errno ) );
1313 #endif
1314 if (host) retval = hostent_from_unix( host );
1315 #ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
1316 HeapFree( GetProcessHeap(), 0, extrabuf );
1317 #else
1318 LeaveCriticalSection( &csWSgetXXXbyYYY );
1319 #endif
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 );
1330 return retval;
1334 /***********************************************************************
1335 * gethostname (ws2_32.57)
1337 int WINAPI WS_gethostname( char *name, int namelen )
1339 char buf[256];
1340 int len;
1342 TRACE( "name %p, len %d\n", name, namelen );
1344 if (!name)
1346 SetLastError( WSAEFAULT );
1347 return -1;
1350 if (gethostname( buf, sizeof(buf) ) != 0)
1352 SetLastError( sock_get_error( errno ) );
1353 return -1;
1356 TRACE( "<- %s\n", debugstr_a(buf) );
1357 len = strlen( buf );
1358 if (len > 15)
1359 WARN( "Windows supports NetBIOS name length up to 15 bytes!\n" );
1360 if (namelen <= len)
1362 SetLastError( WSAEFAULT );
1363 return -1;
1365 strcpy( name, buf );
1366 return 0;
1370 /***********************************************************************
1371 * GetHostNameW (ws2_32.@)
1373 int WINAPI GetHostNameW( WCHAR *name, int namelen )
1375 char buf[256];
1377 TRACE( "name %p, len %d\n", name, namelen );
1379 if (!name)
1381 SetLastError( WSAEFAULT );
1382 return -1;
1385 if (gethostname( buf, sizeof(buf) ))
1387 SetLastError( sock_get_error( errno ) );
1388 return -1;
1391 if (MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 ) > namelen)
1393 SetLastError( WSAEFAULT );
1394 return -1;
1396 MultiByteToWideChar( CP_ACP, 0, buf, -1, name, namelen );
1397 return 0;
1401 static int list_size( char **list, int item_size )
1403 int i, size = 0;
1404 if (list)
1406 for (i = 0; list[i]; i++)
1407 size += (item_size ? item_size : strlen(list[i]) + 1);
1408 size += (i + 1) * sizeof(char *);
1410 return size;
1413 static int list_dup( char **src, char **dst, int item_size )
1415 char *p;
1416 int i;
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 );
1426 dst[i] = p;
1427 p += count;
1429 dst[i] = NULL;
1430 return p - (char *)dst;
1433 static const struct
1435 int prot;
1436 const char *names[3];
1438 protocols[] =
1440 { 0, {"ip", "IP"}},
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"}},
1454 {51, {"ah", "AH"}},
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 );
1487 return ret;
1491 /***********************************************************************
1492 * getprotobyname (ws2_32.53)
1494 struct WS_protoent * WINAPI WS_getprotobyname( const char *name )
1496 struct WS_protoent *retval = NULL;
1497 unsigned int i;
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 );
1505 break;
1508 if (!retval)
1510 WARN( "protocol %s not found\n", debugstr_a(name) );
1511 SetLastError( WSANO_DATA );
1513 TRACE( "%s ret %p\n", debugstr_a(name), retval );
1514 return retval;
1518 /***********************************************************************
1519 * getprotobynumber (ws2_32.54)
1521 struct WS_protoent * WINAPI WS_getprotobynumber( int number )
1523 struct WS_protoent *retval = NULL;
1524 unsigned int i;
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 );
1532 break;
1535 if (!retval)
1537 WARN( "protocol %d not found\n", number );
1538 SetLastError( WSANO_DATA );
1540 TRACE( "%d ret %p\n", number, retval );
1541 return retval;
1545 static char *strdup_lower( const char *str )
1547 char *ret = HeapAlloc( GetProcessHeap(), 0, strlen(str) + 1 );
1548 int i;
1550 if (ret)
1552 for (i = 0; str[i]; i++) ret[i] = tolower( str[i] );
1553 ret[i] = 0;
1555 else SetLastError( WSAENOBUFS );
1556 return ret;
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 )
1575 char *p;
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);
1587 p_to->s_name = p;
1588 strcpy( p, p_se->s_name );
1589 p += strlen(p) + 1;
1591 p_to->s_proto = p;
1592 strcpy( p, p_se->s_proto );
1593 p += strlen(p) + 1;
1595 p_to->s_aliases = (char **)p;
1596 list_dup( p_se->s_aliases, p_to->s_aliases, 0 );
1597 return p_to;
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;
1608 char *name_str;
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 );
1618 return NULL;
1622 EnterCriticalSection( &csWSgetXXXbyYYY );
1623 serv = getservbyname( name_str, proto_str );
1624 if (serv)
1625 retval = servent_from_unix( serv );
1626 else
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 );
1633 return 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 );
1655 else
1656 SetLastError( WSANO_DATA );
1657 LeaveCriticalSection( &csWSgetXXXbyYYY );
1659 HeapFree( GetProcessHeap(), 0, proto_str );
1660 #endif
1661 TRACE( "%d (i.e. port %d), %s ret %p\n", port, (int)ntohl(port), debugstr_a(proto), retval );
1662 return 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,
1678 long_ip & 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 )
1689 NTSTATUS status;
1690 ULONG size = min( len, (ULONG)-1 );
1692 TRACE( "family %d, addr %p, buffer %p, len %ld\n", family, addr, buffer, len );
1693 if (!buffer)
1695 SetLastError( STATUS_INVALID_PARAMETER );
1696 return NULL;
1699 switch (family)
1701 case WS_AF_INET:
1703 status = RtlIpv4AddressToStringExA( (IN_ADDR *)addr, 0, buffer, &size );
1704 break;
1706 case WS_AF_INET6:
1708 status = RtlIpv6AddressToStringExA( (IN6_ADDR *)addr, 0, 0, buffer, &size );
1709 break;
1711 default:
1712 SetLastError( WSAEAFNOSUPPORT );
1713 return NULL;
1716 if (status == STATUS_SUCCESS) return buffer;
1717 SetLastError( STATUS_INVALID_PARAMETER );
1718 return NULL;
1721 /***********************************************************************
1722 * inet_pton (ws2_32.@)
1724 int WINAPI WS_inet_pton( int family, const char *addr, void *buffer )
1726 NTSTATUS status;
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 );
1734 return -1;
1737 switch (family)
1739 case WS_AF_INET:
1740 status = RtlIpv4StringToAddressA(addr, TRUE, &terminator, buffer);
1741 break;
1742 case WS_AF_INET6:
1743 status = RtlIpv6StringToAddressA(addr, &terminator, buffer);
1744 break;
1745 default:
1746 SetLastError( WSAEAFNOSUPPORT );
1747 return -1;
1750 return (status == STATUS_SUCCESS && *terminator == 0);
1753 /***********************************************************************
1754 * InetPtonW (ws2_32.@)
1756 int WINAPI InetPtonW( int family, const WCHAR *addr, void *buffer )
1758 char *addrA;
1759 int len;
1760 INT ret;
1762 TRACE( "family %d, addr %s, buffer %p\n", family, debugstr_w(addr), buffer );
1764 if (!addr)
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 );
1774 return -1;
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 );
1782 return ret;
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];
1791 PWSTR ret = NULL;
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 ))
1798 ret = buffer;
1799 else
1800 SetLastError( ERROR_INVALID_PARAMETER );
1802 return ret;
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 )
1812 NTSTATUS status;
1814 TRACE( "string %s, family %u\n", debugstr_a(string), family );
1816 if (!addr || !addr_len) return -1;
1818 if (!string)
1820 SetLastError( WSAEINVAL );
1821 return -1;
1824 if (protocol_info)
1825 FIXME( "ignoring protocol_info\n" );
1827 switch (family)
1829 case WS_AF_INET:
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 );
1837 return -1;
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 );
1845 return -1;
1847 addr4->sin_family = WS_AF_INET;
1848 *addr_len = sizeof(struct WS_sockaddr_in);
1849 return 0;
1851 case WS_AF_INET6:
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 );
1859 return -1;
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 );
1867 return -1;
1869 addr6->sin6_family = WS_AF_INET6;
1870 *addr_len = sizeof(struct WS_sockaddr_in6);
1871 return 0;
1873 default:
1874 /* According to MSDN, only AF_INET and AF_INET6 are supported. */
1875 TRACE( "Unsupported address family specified: %d.\n", family );
1876 SetLastError( WSAEINVAL );
1877 return -1;
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;
1890 int sizeA, ret;
1891 char *stringA;
1893 TRACE( "string %s, family %u\n", debugstr_w(string), family );
1895 if (!addr || !addr_len) return -1;
1897 if (protocol_info)
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 );
1906 return -1;
1910 if (!string)
1912 SetLastError( WSAEINVAL );
1913 return -1;
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 );
1920 return -1;
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 );
1925 return ret;
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' */
1936 DWORD size;
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)
1945 case WS_AF_INET:
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 );
1949 char *p;
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,
1956 long_ip & 0xff,
1957 ntohs( addr4->sin_port ) );
1959 p = strchr( buffer, ':' );
1960 if (!addr4->sin_port) *p = 0;
1961 break;
1963 case WS_AF_INET6:
1965 struct WS_sockaddr_in6 *addr6 = (struct WS_sockaddr_in6 *)addr;
1966 size_t len;
1968 buffer[0] = 0;
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 );
1976 return -1;
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 ) );
1982 break;
1985 default:
1986 SetLastError( WSAEINVAL );
1987 return -1;
1990 size = strlen( buffer ) + 1;
1992 if (*string_len < size)
1994 *string_len = size;
1995 SetLastError( WSAEFAULT );
1996 return -1;
1999 TRACE( "=> %s, %u bytes\n", debugstr_a(buffer), size );
2000 *string_len = size;
2001 strcpy( string, buffer );
2002 return 0;
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 )
2012 INT ret;
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 );
2021 return 0;
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 /***********************************************************************
2036 * htonl (ws2_32.8)
2038 WS_u_long WINAPI WS_htonl( WS_u_long hostlong )
2040 return htonl( hostlong );
2044 /***********************************************************************
2045 * htons (ws2_32.9)
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 )
2058 if (netlong)
2060 *netlong = htonl( hostlong );
2061 return 0;
2063 SetLastError( WSAEFAULT );
2064 return -1;
2068 /***********************************************************************
2069 * WSAHtons (ws2_32.@)
2071 int WINAPI WSAHtons( SOCKET s, WS_u_short hostshort, WS_u_short *netshort )
2073 if (netshort)
2075 *netshort = htons( hostshort );
2076 return 0;
2078 SetLastError( WSAEFAULT );
2079 return -1;
2083 /***********************************************************************
2084 * ntohl (ws2_32.14)
2086 WS_u_long WINAPI WS_ntohl( WS_u_long netlong )
2088 return ntohl( netlong );
2092 /***********************************************************************
2093 * ntohs (ws2_32.15)
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 );
2109 return 0;
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 );
2121 return 0;
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 );
2132 return -1;
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 );
2143 return -1;
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 );
2154 return -1;
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 );
2166 return -1;
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 );
2178 return -1;
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 );
2189 return -1;
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 );
2200 return -1;
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 );
2211 return -1;
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 );
2222 return -1;
2226 /***********************************************************************
2227 * WSALookupServiceEnd (ws2_32.@)
2229 int WINAPI WSALookupServiceEnd( HANDLE lookup )
2231 FIXME("(%p) Stub!\n", lookup );
2232 return 0;
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 );
2243 return -1;
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 );
2254 return -1;
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 );
2264 return 0;
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 );
2274 return 0;
2278 /***********************************************************************
2279 * WSAEnumNameSpaceProvidersA (ws2_32.@)
2281 int WINAPI WSAEnumNameSpaceProvidersA( DWORD *len, WSANAMESPACE_INFOA *buffer )
2283 FIXME( "(%p %p) Stub!\n", len, buffer );
2284 return 0;
2288 /***********************************************************************
2289 * WSAEnumNameSpaceProvidersW (ws2_32.@)
2291 int WINAPI WSAEnumNameSpaceProvidersW( DWORD *len, WSANAMESPACE_INFOW *buffer )
2293 FIXME( "(%p %p) Stub!\n", len, buffer );
2294 return 0;
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 );
2305 return -1;
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 );
2319 return -1;
2323 /***********************************************************************
2324 * WSCEnableNSProvider (ws2_32.@)
2326 int WINAPI WSCEnableNSProvider( GUID *provider, BOOL enable )
2328 FIXME( "(%s 0x%08x) Stub!\n", debugstr_guid(provider), enable );
2329 return 0;
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 );
2342 if (!errcode)
2343 return -1;
2345 if (!provider)
2347 *errcode = WSAEFAULT;
2348 return -1;
2351 *errcode = WSANO_RECOVERY;
2352 return -1;
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)
2365 if (errcode)
2366 *errcode = WSAEFAULT;
2367 return -1;
2370 if (*len <= 0)
2372 if (errcode)
2373 *errcode = WSAEINVAL;
2374 return -1;
2377 return 0;
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) );
2389 return 0;
2393 /***********************************************************************
2394 * WSCUnInstallNameSpace (ws2_32.@)
2396 int WINAPI WSCUnInstallNameSpace( GUID *provider )
2398 FIXME( "(%s) Stub!\n", debugstr_guid(provider) );
2399 return NO_ERROR;
2403 /***********************************************************************
2404 * WSCWriteProviderOrder (ws2_32.@)
2406 int WINAPI WSCWriteProviderOrder( DWORD *entry, DWORD number )
2408 FIXME( "(%p 0x%08x) Stub!\n", entry, number );
2409 return 0;
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 );
2421 *err = 0;
2422 return 0;
2426 /***********************************************************************
2427 * WSCDeinstallProvider (ws2_32.@)
2429 int WINAPI WSCDeinstallProvider( GUID *provider, int *err )
2431 FIXME( "(%s, %p): stub !\n", debugstr_guid(provider), err );
2432 *err = 0;
2433 return 0;
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 );
2445 return 0;
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;
2458 return ret;