Alexandre Julliard : ws2_32: Implement Wow64 entry points in the Unix library.

Alexandre Julliard julliard at winehq.org
Tue Dec 7 15:58:45 CST 2021


Module: wine
Branch: master
Commit: d3de3c584a440fe9e8b48194d3e3cd807f2e59c5
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=d3de3c584a440fe9e8b48194d3e3cd807f2e59c5

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Dec  7 16:15:05 2021 +0100

ws2_32: Implement Wow64 entry points in the Unix library.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ws2_32/unixlib.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 280 insertions(+)

diff --git a/dlls/ws2_32/unixlib.c b/dlls/ws2_32/unixlib.c
index 5726fc31e3e..f1f43fbdb30 100644
--- a/dlls/ws2_32/unixlib.c
+++ b/dlls/ws2_32/unixlib.c
@@ -983,3 +983,283 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
     unix_gethostname,
     unix_getnameinfo,
 };
+
+#ifdef _WIN64
+
+typedef ULONG PTR32;
+
+struct WS_addrinfo32
+{
+    int   ai_flags;
+    int   ai_family;
+    int   ai_socktype;
+    int   ai_protocol;
+    PTR32 ai_addrlen;
+    PTR32 ai_canonname;
+    PTR32 ai_addr;
+    PTR32 ai_next;
+};
+
+struct WS_hostent32
+{
+    PTR32 h_name;
+    PTR32 h_aliases;
+    short h_addrtype;
+    short h_length;
+    PTR32 h_addr_list;
+};
+
+static NTSTATUS put_addrinfo32( const struct WS_addrinfo *info, struct WS_addrinfo32 *info32,
+                                unsigned int *size )
+{
+    struct WS_addrinfo32 *dst = info32, *prev = NULL;
+    const struct WS_addrinfo *src;
+    unsigned int needed_size = 0;
+
+    for (src = info; src != NULL; src = src->ai_next)
+    {
+        needed_size += sizeof(struct WS_addrinfo32);
+        if (src->ai_canonname) needed_size += strlen( src->ai_canonname ) + 1;
+        needed_size += src->ai_addrlen;
+    }
+
+    if (*size < needed_size)
+    {
+        *size = needed_size;
+        return ERROR_INSUFFICIENT_BUFFER;
+    }
+
+    memset( info32, 0, needed_size );
+
+    for (src = info; src != NULL; src = src->ai_next)
+    {
+        char *next = (char *)(dst + 1);
+
+        dst->ai_flags = src->ai_flags;
+        dst->ai_family = src->ai_family;
+        dst->ai_socktype = src->ai_socktype;
+        dst->ai_protocol = src->ai_protocol;
+        if (src->ai_canonname)
+        {
+            dst->ai_canonname = PtrToUlong( next );
+            strcpy( next, src->ai_canonname );
+            next += strlen(next) + 1;
+        }
+        dst->ai_addrlen = src->ai_addrlen;
+        dst->ai_addr = PtrToUlong(next);
+        memcpy( next, src->ai_addr, dst->ai_addrlen );
+        next += dst->ai_addrlen;
+        if (prev) prev->ai_next = PtrToUlong(dst);
+        prev = dst;
+        dst = (struct WS_addrinfo32 *)next;
+    }
+    return STATUS_SUCCESS;
+}
+
+static NTSTATUS put_hostent32( const struct WS_hostent *host, struct WS_hostent32 *host32,
+                               unsigned int *size )
+{
+    unsigned int needed_size = sizeof( struct WS_hostent32 ), alias_count = 0, addr_count = 0, i;
+    char *p;
+    ULONG *aliases, *addr_list;
+
+    needed_size += strlen( host->h_name ) + 1;
+
+    for (alias_count = 0; host->h_aliases[alias_count] != NULL; ++alias_count)
+        needed_size += sizeof(ULONG) + strlen( host->h_aliases[alias_count] ) + 1;
+    needed_size += sizeof(ULONG); /* null terminator */
+
+    for (addr_count = 0; host->h_addr_list[addr_count] != NULL; ++addr_count)
+        needed_size += sizeof(ULONG) + host->h_length;
+    needed_size += sizeof(ULONG); /* null terminator */
+
+    if (*size < needed_size)
+    {
+        *size = needed_size;
+        return ERROR_INSUFFICIENT_BUFFER;
+    }
+
+    memset( host32, 0, needed_size );
+
+    /* arrange the memory in the same order as windows >= XP */
+
+    host32->h_addrtype = host->h_addrtype;
+    host32->h_length = host->h_length;
+
+    aliases = (ULONG *)(host32 + 1);
+    addr_list = aliases + alias_count + 1;
+    p = (char *)(addr_list + addr_count + 1);
+
+    host32->h_aliases = PtrToUlong( aliases );
+    host32->h_addr_list = PtrToUlong( addr_list );
+
+    for (i = 0; i < addr_count; ++i)
+    {
+        addr_list[i] = PtrToUlong( p );
+        memcpy( p, host->h_addr_list[i], host->h_length );
+        p += host->h_length;
+    }
+
+    for (i = 0; i < alias_count; ++i)
+    {
+        size_t len = strlen( host->h_aliases[i] ) + 1;
+
+        aliases[i] = PtrToUlong( p );
+        memcpy( p, host->h_aliases[i], len );
+        p += len;
+    }
+
+    host32->h_name = PtrToUlong( p );
+    strcpy( p, host->h_name );
+    return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS wow64_unix_getaddrinfo( void *args )
+{
+    struct
+    {
+        PTR32 node;
+        PTR32 service;
+        PTR32 hints;
+        PTR32 info;
+        PTR32 size;
+    } const *params32 = args;
+
+    NTSTATUS status;
+    struct WS_addrinfo hints;
+    struct getaddrinfo_params params =
+    {
+        ULongToPtr( params32->node ),
+        ULongToPtr( params32->service ),
+        NULL,
+        NULL,
+        ULongToPtr(params32->size)
+    };
+
+    if (params32->hints)
+    {
+        const struct WS_addrinfo32 *hints32 = ULongToPtr(params32->hints);
+        hints.ai_flags    = hints32->ai_flags;
+        hints.ai_family   = hints32->ai_family;
+        hints.ai_socktype = hints32->ai_socktype;
+        hints.ai_protocol = hints32->ai_protocol;
+        params.hints = &hints;
+    }
+
+    if (!(params.info = malloc( *params.size ))) return WSAENOBUFS;
+    status = unix_getaddrinfo( &params );
+    if (!status) put_addrinfo32( params.info, ULongToPtr(params32->info), ULongToPtr(params32->size) );
+    free( params.info );
+    return status;
+}
+
+
+static NTSTATUS wow64_unix_gethostbyaddr( void *args )
+{
+    struct
+    {
+        PTR32 addr;
+        int   len;
+        int   family;
+        PTR32 host;
+        PTR32 size;
+    } const *params32 = args;
+
+    NTSTATUS status;
+    struct gethostbyaddr_params params =
+    {
+        ULongToPtr( params32->addr ),
+        params32->len,
+        params32->family,
+        NULL,
+        ULongToPtr(params32->size)
+    };
+
+    if (!(params.host = malloc( *params.size ))) return WSAENOBUFS;
+    status = unix_gethostbyaddr( &params );
+    if (!status)
+        status = put_hostent32( params.host, ULongToPtr(params32->host), ULongToPtr(params32->size) );
+    free( params.host );
+    return status;
+}
+
+
+static NTSTATUS wow64_unix_gethostbyname( void *args )
+{
+    struct
+    {
+        PTR32 name;
+        PTR32 host;
+        PTR32 size;
+    } const *params32 = args;
+
+    NTSTATUS status;
+    struct gethostbyname_params params =
+    {
+        ULongToPtr( params32->name ),
+        NULL,
+        ULongToPtr(params32->size)
+    };
+
+    if (!(params.host = malloc( *params.size ))) return WSAENOBUFS;
+    status = unix_gethostbyname( &params );
+    if (!status)
+        status = put_hostent32( params.host, ULongToPtr(params32->host), ULongToPtr(params32->size) );
+    free( params.host );
+    return status;
+}
+
+
+static NTSTATUS wow64_unix_gethostname( void *args )
+{
+    struct
+    {
+        PTR32 name;
+        unsigned int size;
+    } const *params32 = args;
+
+    struct gethostname_params params = { ULongToPtr(params32->name), params32->size };
+
+    if (!unix_gethostname( &params )) return 0;
+    return errno_from_unix( errno );
+}
+
+
+static NTSTATUS wow64_unix_getnameinfo( void *args )
+{
+    struct
+    {
+        PTR32 addr;
+        int addr_len;
+        PTR32 host;
+        DWORD host_len;
+        PTR32 serv;
+        DWORD serv_len;
+        unsigned int flags;
+    } const *params32 = args;
+
+    struct getnameinfo_params params =
+    {
+        ULongToPtr( params32->addr ),
+        params32->addr_len,
+        ULongToPtr( params32->host ),
+        params32->host_len,
+        ULongToPtr( params32->serv ),
+        params32->serv_len,
+        params32->flags
+    };
+
+    return unix_getnameinfo( &params );
+}
+
+const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
+{
+    wow64_unix_getaddrinfo,
+    wow64_unix_gethostbyaddr,
+    wow64_unix_gethostbyname,
+    wow64_unix_gethostname,
+    wow64_unix_getnameinfo,
+};
+
+#endif  /* _WIN64 */




More information about the wine-cvs mailing list