ws2_32: Allocate the addrinfo buffer on the PE side.
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e58405000c
commit
d6555b966e
|
@ -130,6 +130,33 @@ static char *get_fqdn(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* call Unix getaddrinfo, allocating a large enough buffer */
|
||||
static int do_getaddrinfo( const char *node, const char *service,
|
||||
const struct WS_addrinfo *hints, struct WS_addrinfo **info )
|
||||
{
|
||||
struct WS_addrinfo *buffer, *new_buffer;
|
||||
unsigned int size = 1024;
|
||||
int ret;
|
||||
|
||||
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, size )))
|
||||
return WSA_NOT_ENOUGH_MEMORY;
|
||||
|
||||
while ((ret = unix_funcs->getaddrinfo( node, service, hints, buffer, &size )) == ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
if (!(new_buffer = HeapReAlloc( GetProcessHeap(), 0, buffer, size )))
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, buffer );
|
||||
return WSA_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
buffer = new_buffer;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
*info = buffer;
|
||||
else
|
||||
HeapFree( GetProcessHeap(), 0, buffer );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -173,7 +200,7 @@ int WINAPI WS_getaddrinfo( const char *node, const char *service,
|
|||
}
|
||||
}
|
||||
|
||||
ret = unix_funcs->getaddrinfo( node, service, hints, info );
|
||||
ret = do_getaddrinfo( node, service, hints, info );
|
||||
|
||||
if (ret && (!hints || !(hints->ai_flags & WS_AI_NUMERICHOST)) && node)
|
||||
{
|
||||
|
@ -188,7 +215,7 @@ int WINAPI WS_getaddrinfo( const char *node, const char *service,
|
|||
* by sending a NULL host and avoid sending a NULL servname too because that
|
||||
* is invalid */
|
||||
ERR_(winediag)( "Failed to resolve your host name IP\n" );
|
||||
ret = unix_funcs->getaddrinfo( NULL, service, hints, info );
|
||||
ret = do_getaddrinfo( NULL, service, hints, info );
|
||||
if (!ret && hints && (hints->ai_flags & WS_AI_CANONNAME) && *info && !(*info)->ai_canonname)
|
||||
{
|
||||
WS_freeaddrinfo( *info );
|
||||
|
@ -542,18 +569,11 @@ int WINAPI GetAddrInfoW(const WCHAR *nodename, const WCHAR *servname, const ADDR
|
|||
/***********************************************************************
|
||||
* freeaddrinfo (ws2_32.@)
|
||||
*/
|
||||
void WINAPI WS_freeaddrinfo( struct WS_addrinfo *res )
|
||||
void WINAPI WS_freeaddrinfo( struct WS_addrinfo *info )
|
||||
{
|
||||
while (res)
|
||||
{
|
||||
struct WS_addrinfo *next;
|
||||
TRACE( "%p\n", info );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, res->ai_canonname );
|
||||
HeapFree( GetProcessHeap(), 0, res->ai_addr );
|
||||
next = res->ai_next;
|
||||
HeapFree( GetProcessHeap(), 0, res );
|
||||
res = next;
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, info );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -468,17 +468,16 @@ static BOOL addrinfo_in_list( const struct WS_addrinfo *list, const struct WS_ad
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static int CDECL unix_getaddrinfo( const char *node, const char *service,
|
||||
const struct WS_addrinfo *hints, struct WS_addrinfo **info )
|
||||
static int CDECL unix_getaddrinfo( const char *node, const char *service, const struct WS_addrinfo *hints,
|
||||
struct WS_addrinfo *info, unsigned int *size )
|
||||
{
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
struct addrinfo unix_hints = {0};
|
||||
struct addrinfo *unix_info, *src;
|
||||
struct WS_addrinfo *dst, *prev = NULL;
|
||||
unsigned int needed_size = 0;
|
||||
int ret;
|
||||
|
||||
*info = NULL;
|
||||
|
||||
/* servname tweak required by OSX and BSD kernels */
|
||||
if (service && !service[0]) service = "0";
|
||||
|
||||
|
@ -528,12 +527,28 @@ static int CDECL unix_getaddrinfo( const char *node, const char *service,
|
|||
if (ret)
|
||||
return addrinfo_err_from_unix( ret );
|
||||
|
||||
*info = NULL;
|
||||
for (src = unix_info; src != NULL; src = src->ai_next)
|
||||
{
|
||||
needed_size += sizeof(struct WS_addrinfo);
|
||||
if (src->ai_canonname)
|
||||
needed_size += strlen( src->ai_canonname ) + 1;
|
||||
needed_size += sockaddr_from_unix( (const union unix_sockaddr *)src->ai_addr, NULL, 0 );
|
||||
}
|
||||
|
||||
if (*size < needed_size)
|
||||
{
|
||||
*size = needed_size;
|
||||
freeaddrinfo( unix_info );
|
||||
return ERROR_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
|
||||
dst = info;
|
||||
|
||||
memset( info, 0, needed_size );
|
||||
|
||||
for (src = unix_info; src != NULL; src = src->ai_next)
|
||||
{
|
||||
if (!(dst = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dst) )))
|
||||
goto fail;
|
||||
void *next = dst + 1;
|
||||
|
||||
dst->ai_flags = addrinfo_flags_from_unix( src->ai_flags );
|
||||
dst->ai_family = family_from_unix( src->ai_family );
|
||||
|
@ -549,55 +564,31 @@ static int CDECL unix_getaddrinfo( const char *node, const char *service,
|
|||
}
|
||||
if (src->ai_canonname)
|
||||
{
|
||||
if (!(dst->ai_canonname = RtlAllocateHeap( GetProcessHeap(), 0, strlen( src->ai_canonname ) + 1 )))
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, dst );
|
||||
goto fail;
|
||||
}
|
||||
strcpy( dst->ai_canonname, src->ai_canonname );
|
||||
size_t len = strlen( src->ai_canonname ) + 1;
|
||||
|
||||
dst->ai_canonname = next;
|
||||
memcpy( dst->ai_canonname, src->ai_canonname, len );
|
||||
next = dst->ai_canonname + len;
|
||||
}
|
||||
|
||||
dst->ai_addrlen = sockaddr_from_unix( (const union unix_sockaddr *)src->ai_addr, NULL, 0 );
|
||||
if (!(dst->ai_addr = RtlAllocateHeap( GetProcessHeap(), 0, dst->ai_addrlen )))
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, dst->ai_canonname );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, dst );
|
||||
goto fail;
|
||||
}
|
||||
dst->ai_addr = next;
|
||||
sockaddr_from_unix( (const union unix_sockaddr *)src->ai_addr, dst->ai_addr, dst->ai_addrlen );
|
||||
next = (char *)dst->ai_addr + dst->ai_addrlen;
|
||||
|
||||
if (addrinfo_in_list( *info, dst ))
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, dst->ai_canonname );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, dst->ai_addr );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, dst );
|
||||
}
|
||||
else
|
||||
if (dst == info || !addrinfo_in_list( info, dst ))
|
||||
{
|
||||
if (prev)
|
||||
prev->ai_next = dst;
|
||||
else
|
||||
*info = dst;
|
||||
prev = dst;
|
||||
dst = next;
|
||||
}
|
||||
}
|
||||
|
||||
dst->ai_next = NULL;
|
||||
|
||||
freeaddrinfo( unix_info );
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
dst = *info;
|
||||
while (dst)
|
||||
{
|
||||
struct WS_addrinfo *next;
|
||||
|
||||
RtlFreeHeap( GetProcessHeap(), 0, dst->ai_canonname );
|
||||
RtlFreeHeap( GetProcessHeap(), 0, dst->ai_addr );
|
||||
next = dst->ai_next;
|
||||
RtlFreeHeap( GetProcessHeap(), 0, dst );
|
||||
dst = next;
|
||||
}
|
||||
return WS_EAI_MEMORY;
|
||||
#else
|
||||
FIXME( "getaddrinfo() not found during build time\n" );
|
||||
return WS_EAI_FAIL;
|
||||
|
|
|
@ -198,8 +198,8 @@ struct per_thread_data *get_per_thread_data(void) DECLSPEC_HIDDEN;
|
|||
|
||||
struct unix_funcs
|
||||
{
|
||||
int (CDECL *getaddrinfo)( const char *node, const char *service,
|
||||
const struct WS(addrinfo) *hints, struct WS(addrinfo) **info );
|
||||
int (CDECL *getaddrinfo)( const char *node, const char *service, const struct WS(addrinfo) *hints,
|
||||
struct WS(addrinfo) *info, unsigned int *size );
|
||||
};
|
||||
|
||||
extern const struct unix_funcs *unix_funcs;
|
||||
|
|
Loading…
Reference in New Issue