ws2_32: Convert the Unix library to the __wine_unix_call interface.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-08-11 20:40:23 +02:00
parent 948e791928
commit d327527cec
5 changed files with 127 additions and 84 deletions

View File

@ -1,7 +1,7 @@
MODULE = ws2_32.dll
IMPORTLIB = ws2_32
DELAYIMPORTS = advapi32 iphlpapi user32
EXTRALIBS = $(POLL_LIBS)
EXTRALIBS = $(POLL_LIBS) -Wl,--subsystem,unixlib
EXTRADLLFLAGS = -mno-cygwin

View File

@ -27,6 +27,10 @@
WINE_DEFAULT_DEBUG_CHANNEL(winsock);
WINE_DECLARE_DEBUG_CHANNEL(winediag);
unixlib_handle_t ws_unix_handle = 0;
#define WS_CALL(func, params) __wine_unix_call( ws_unix_handle, ws_unix_ ## func, params )
static char *get_fqdn(void)
{
char *ret;
@ -47,28 +51,22 @@ static char *get_fqdn(void)
static int do_getaddrinfo( const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **info )
{
struct addrinfo *buffer, *new_buffer;
unsigned int size = 1024;
struct getaddrinfo_params params = { node, service, hints, NULL, &size };
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)
for (;;)
{
if (!(new_buffer = HeapReAlloc( GetProcessHeap(), 0, buffer, size )))
{
HeapFree( GetProcessHeap(), 0, buffer );
if (!(params.info = HeapAlloc( GetProcessHeap(), 0, size )))
return WSA_NOT_ENOUGH_MEMORY;
if (!(ret = WS_CALL( getaddrinfo, &params )))
{
*info = params.info;
return ret;
}
buffer = new_buffer;
HeapFree( GetProcessHeap(), 0, params.info );
if (ret != ERROR_INSUFFICIENT_BUFFER) return ret;
}
if (!ret)
*info = buffer;
else
HeapFree( GetProcessHeap(), 0, buffer );
return ret;
}
@ -551,10 +549,12 @@ void WINAPI FreeAddrInfoExW( ADDRINFOEXW *ai )
int WINAPI getnameinfo( const SOCKADDR *addr, socklen_t addr_len, char *host,
DWORD host_len, char *serv, DWORD serv_len, int flags )
{
struct getnameinfo_params params = { addr, addr_len, host, host_len, serv, serv_len, flags };
TRACE( "addr %s, addr_len %d, host %p, host_len %u, serv %p, serv_len %d, flags %#x\n",
debugstr_sockaddr(addr), addr_len, host, host_len, serv, serv_len, flags );
return unix_funcs->getnameinfo( addr, addr_len, host, host_len, serv, serv_len, flags );
return WS_CALL( getnameinfo, &params );
}
@ -662,20 +662,20 @@ static struct hostent *create_hostent( char *name, int alias_count, int aliases_
struct hostent * WINAPI gethostbyaddr( const char *addr, int len, int family )
{
unsigned int size = 1024;
struct hostent *host;
struct gethostbyaddr_params params = { addr, len, family, NULL, &size };
int ret;
if (!(host = get_hostent_buffer( size )))
return NULL;
while ((ret = unix_funcs->gethostbyaddr( addr, len, family, host, &size )) == ERROR_INSUFFICIENT_BUFFER)
for (;;)
{
if (!(host = get_hostent_buffer( size )))
if (!(params.host = get_hostent_buffer( size )))
return NULL;
if ((ret = WS_CALL( gethostbyaddr, &params )) != ERROR_INSUFFICIENT_BUFFER)
break;
}
SetLastError( ret );
return ret ? NULL : host;
return ret ? NULL : params.host;
}
@ -822,6 +822,7 @@ struct hostent * WINAPI gethostbyname( const char *name )
{
struct hostent *host = NULL;
char hostname[100];
struct gethostname_params params = { hostname, sizeof(hostname) };
int ret;
TRACE( "%s\n", debugstr_a(name) );
@ -832,7 +833,7 @@ struct hostent * WINAPI gethostbyname( const char *name )
return NULL;
}
if ((ret = unix_funcs->gethostname( hostname, 100 )))
if ((ret = WS_CALL( gethostname, &params )))
{
SetLastError( ret );
return NULL;
@ -851,19 +852,20 @@ struct hostent * WINAPI gethostbyname( const char *name )
if (!host)
{
unsigned int size = 1024;
struct gethostbyname_params params = { name, NULL, &size };
int ret;
if (!(host = get_hostent_buffer( size )))
return NULL;
while ((ret = unix_funcs->gethostbyname( name, host, &size )) == ERROR_INSUFFICIENT_BUFFER)
for (;;)
{
if (!(host = get_hostent_buffer( size )))
if (!(params.host = get_hostent_buffer( size )))
return NULL;
if ((ret = WS_CALL( gethostbyname, &params )) != ERROR_INSUFFICIENT_BUFFER)
break;
}
SetLastError( ret );
return ret ? NULL : host;
return ret ? NULL : params.host;
}
if (host && host->h_addr_list[0][0] == 127 && strcmp( name, "localhost" ))
@ -883,6 +885,7 @@ struct hostent * WINAPI gethostbyname( const char *name )
int WINAPI gethostname( char *name, int namelen )
{
char buf[256];
struct gethostname_params params = { buf, sizeof(buf) };
int len, ret;
TRACE( "name %p, len %d\n", name, namelen );
@ -893,7 +896,7 @@ int WINAPI gethostname( char *name, int namelen )
return -1;
}
if ((ret = unix_funcs->gethostname( buf, sizeof(buf) )))
if ((ret = WS_CALL( gethostname, &params )))
{
SetLastError( ret );
return -1;
@ -919,6 +922,7 @@ int WINAPI gethostname( char *name, int namelen )
int WINAPI GetHostNameW( WCHAR *name, int namelen )
{
char buf[256];
struct gethostname_params params = { buf, sizeof(buf) };
int ret;
TRACE( "name %p, len %d\n", name, namelen );
@ -929,7 +933,7 @@ int WINAPI GetHostNameW( WCHAR *name, int namelen )
return -1;
}
if ((ret = unix_funcs->gethostname( buf, sizeof(buf) )))
if ((ret = WS_CALL( gethostname, &params )))
{
SetLastError( ret );
return -1;

View File

@ -35,8 +35,6 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
#define TIMEOUT_INFINITE _I64_MAX
const struct unix_funcs *unix_funcs = NULL;
static const WSAPROTOCOL_INFOW supported_protocols[] =
{
{
@ -552,7 +550,8 @@ BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, void *reserved )
switch (reason)
{
case DLL_PROCESS_ATTACH:
return !__wine_init_unix_lib( instance, reason, NULL, &unix_funcs );
return !NtQueryVirtualMemory( GetCurrentProcess(), instance, MemoryWineUnixFuncs,
&ws_unix_handle, sizeof(ws_unix_handle), NULL );
case DLL_THREAD_DETACH:
free_per_thread_data();

View File

@ -652,10 +652,12 @@ 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, unsigned int *size )
static NTSTATUS unix_getaddrinfo( void *args )
{
#ifdef HAVE_GETADDRINFO
struct getaddrinfo_params *params = args;
const char *service = params->service;
const struct WS_addrinfo *hints = params->hints;
struct addrinfo unix_hints = {0};
struct addrinfo *unix_info, *src;
struct WS_addrinfo *dst, *prev = NULL;
@ -707,7 +709,7 @@ static int CDECL unix_getaddrinfo( const char *node, const char *service, const
}
}
ret = getaddrinfo( node, service, hints ? &unix_hints : NULL, &unix_info );
ret = getaddrinfo( params->node, service, hints ? &unix_hints : NULL, &unix_info );
if (ret)
return addrinfo_err_from_unix( ret );
@ -719,16 +721,16 @@ static int CDECL unix_getaddrinfo( const char *node, const char *service, const
needed_size += sockaddr_from_unix( (const union unix_sockaddr *)src->ai_addr, NULL, 0 );
}
if (*size < needed_size)
if (*params->size < needed_size)
{
*size = needed_size;
*params->size = needed_size;
freeaddrinfo( unix_info );
return ERROR_INSUFFICIENT_BUFFER;
}
dst = info;
dst = params->info;
memset( info, 0, needed_size );
memset( params->info, 0, needed_size );
for (src = unix_info; src != NULL; src = src->ai_next)
{
@ -760,7 +762,7 @@ static int CDECL unix_getaddrinfo( const char *node, const char *service, const
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 (dst == info || !addrinfo_in_list( info, dst ))
if (dst == params->info || !addrinfo_in_list( params->info, dst ))
{
if (prev)
prev->ai_next = dst;
@ -837,15 +839,16 @@ static int hostent_from_unix( const struct hostent *unix_host, struct WS_hostent
}
static int CDECL unix_gethostbyaddr( const void *addr, int len, int family,
struct WS_hostent *const host, unsigned int *size )
static NTSTATUS unix_gethostbyaddr( void *args )
{
struct gethostbyaddr_params *params = args;
const void *addr = params->addr;
const struct in_addr loopback = { htonl( INADDR_LOOPBACK ) };
int unix_family = family_to_unix( family );
int unix_family = family_to_unix( params->family );
struct hostent *unix_host;
int ret;
if (family == WS_AF_INET && len == 4 && !memcmp( addr, magic_loopback_addr, 4 ))
if (params->family == WS_AF_INET && params->len == 4 && !memcmp( addr, magic_loopback_addr, 4 ))
addr = &loopback;
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
@ -858,7 +861,7 @@ static int CDECL unix_gethostbyaddr( const void *addr, int len, int family,
if (!(unix_buffer = malloc( unix_size )))
return WSAENOBUFS;
while (gethostbyaddr_r( addr, len, unix_family, &stack_host, unix_buffer,
while (gethostbyaddr_r( addr, params->len, unix_family, &stack_host, unix_buffer,
unix_size, &unix_host, &locerr ) == ERANGE)
{
unix_size *= 2;
@ -873,7 +876,7 @@ static int CDECL unix_gethostbyaddr( const void *addr, int len, int family,
if (!unix_host)
return (locerr < 0 ? errno_from_unix( errno ) : host_errno_from_unix( locerr ));
ret = hostent_from_unix( unix_host, host, size );
ret = hostent_from_unix( unix_host, params->host, params->size );
free( unix_buffer );
return ret;
@ -881,14 +884,14 @@ static int CDECL unix_gethostbyaddr( const void *addr, int len, int family,
#else
pthread_mutex_lock( &host_mutex );
if (!(unix_host = gethostbyaddr( addr, len, unix_family )))
if (!(unix_host = gethostbyaddr( addr, params->len, unix_family )))
{
ret = (h_errno < 0 ? errno_from_unix( errno ) : host_errno_from_unix( h_errno ));
pthread_mutex_unlock( &host_mutex );
return ret;
}
ret = hostent_from_unix( unix_host, host, size );
ret = hostent_from_unix( unix_host, params->host, params->size );
pthread_mutex_unlock( &host_mutex );
return ret;
@ -897,8 +900,9 @@ static int CDECL unix_gethostbyaddr( const void *addr, int len, int family,
#ifdef HAVE_LINUX_GETHOSTBYNAME_R_6
static int CDECL unix_gethostbyname( const char *name, struct WS_hostent *const host, unsigned int *size )
static NTSTATUS unix_gethostbyname( void *args )
{
struct gethostbyname_params *params = args;
struct hostent stack_host, *unix_host;
char *unix_buffer, *new_buffer;
int unix_size = 1024;
@ -908,7 +912,7 @@ static int CDECL unix_gethostbyname( const char *name, struct WS_hostent *const
if (!(unix_buffer = malloc( unix_size )))
return WSAENOBUFS;
while (gethostbyname_r( name, &stack_host, unix_buffer, unix_size, &unix_host, &locerr ) == ERANGE)
while (gethostbyname_r( params->name, &stack_host, unix_buffer, unix_size, &unix_host, &locerr ) == ERANGE)
{
unix_size *= 2;
if (!(new_buffer = realloc( unix_buffer, unix_size )))
@ -922,27 +926,28 @@ static int CDECL unix_gethostbyname( const char *name, struct WS_hostent *const
if (!unix_host)
return (locerr < 0 ? errno_from_unix( errno ) : host_errno_from_unix( locerr ));
ret = hostent_from_unix( unix_host, host, size );
ret = hostent_from_unix( unix_host, params->host, params->size );
free( unix_buffer );
return ret;
}
#else
static int CDECL unix_gethostbyname( const char *name, struct WS_hostent *const host, unsigned int *size )
static NTSTATUS unix_gethostbyname( void *args )
{
struct gethostbyname_params *params = args;
struct hostent *unix_host;
int ret;
pthread_mutex_lock( &host_mutex );
if (!(unix_host = gethostbyname( name )))
if (!(unix_host = gethostbyname( params->name )))
{
ret = (h_errno < 0 ? errno_from_unix( errno ) : host_errno_from_unix( h_errno ));
pthread_mutex_unlock( &host_mutex );
return ret;
}
ret = hostent_from_unix( unix_host, host, size );
ret = hostent_from_unix( unix_host, params->host, params->size );
pthread_mutex_unlock( &host_mutex );
return ret;
@ -950,28 +955,31 @@ static int CDECL unix_gethostbyname( const char *name, struct WS_hostent *const
#endif
static int CDECL unix_gethostname( char *name, int len )
static NTSTATUS unix_gethostname( void *args )
{
if (!gethostname( name, len ))
struct gethostname_params *params = args;
if (!gethostname( params->name, params->size ))
return 0;
return errno_from_unix( errno );
}
static int CDECL unix_getnameinfo( const struct WS(sockaddr) *addr, int addr_len, char *host,
DWORD host_len, char *serv, DWORD serv_len, int flags )
static NTSTATUS unix_getnameinfo( void *args )
{
struct getnameinfo_params *params = args;
union unix_sockaddr unix_addr;
socklen_t unix_addr_len;
unix_addr_len = sockaddr_to_unix( addr, addr_len, &unix_addr );
unix_addr_len = sockaddr_to_unix( params->addr, params->addr_len, &unix_addr );
return addrinfo_err_from_unix( getnameinfo( &unix_addr.addr, unix_addr_len, host, host_len,
serv, serv_len, nameinfo_flags_to_unix( flags ) ) );
return addrinfo_err_from_unix( getnameinfo( &unix_addr.addr, unix_addr_len, params->host, params->host_len,
params->serv, params->serv_len,
nameinfo_flags_to_unix( params->flags ) ) );
}
static const struct unix_funcs funcs =
const unixlib_entry_t __wine_unix_call_funcs[] =
{
unix_getaddrinfo,
unix_gethostbyaddr,
@ -979,11 +987,3 @@ static const struct unix_funcs funcs =
unix_gethostname,
unix_getnameinfo,
};
NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
{
if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS;
*(const struct unix_funcs **)ptr_out = &funcs;
return STATUS_SUCCESS;
}

View File

@ -51,6 +51,7 @@
#include "wine/debug.h"
#include "wine/exception.h"
#include "wine/heap.h"
#include "wine/unixlib.h"
#define DECLARE_CRITICAL_SECTION(cs) \
static CRITICAL_SECTION cs; \
@ -80,18 +81,57 @@ extern int num_startup;
struct per_thread_data *get_per_thread_data(void) DECLSPEC_HIDDEN;
struct unix_funcs
struct getaddrinfo_params
{
int (CDECL *getaddrinfo)( const char *node, const char *service, const struct WS(addrinfo) *hints,
struct WS(addrinfo) *info, unsigned int *size );
int (CDECL *gethostbyaddr)( const void *addr, int len, int family,
struct WS(hostent) *host, unsigned int *size );
int (CDECL *gethostbyname)( const char *name, struct WS(hostent) *host, unsigned int *size );
int (CDECL *gethostname)( char *name, int len );
int (CDECL *getnameinfo)( const struct WS(sockaddr) *addr, int addr_len, char *host,
DWORD host_len, char *serv, DWORD serv_len, int flags );
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;
struct gethostbyaddr_params
{
const void *addr;
int len;
int family;
struct WS(hostent) *host;
unsigned int *size;
};
struct gethostbyname_params
{
const char *name;
struct WS(hostent) *host;
unsigned int *size;
};
struct gethostname_params
{
char *name;
unsigned int size;
};
struct getnameinfo_params
{
const struct WS(sockaddr) *addr;
int addr_len;
char *host;
DWORD host_len;
char *serv;
DWORD serv_len;
int flags;
};
enum ws_unix_funcs
{
ws_unix_getaddrinfo,
ws_unix_gethostbyaddr,
ws_unix_gethostbyname,
ws_unix_gethostname,
ws_unix_getnameinfo,
};
extern unixlib_handle_t ws_unix_handle DECLSPEC_HIDDEN;
#endif