[WS2_32_WINETEST] Disable test_address_list_query() as the ioctl is not supported...
[reactos.git] / rostests / winetests / ws2_32 / sock.c
index 2a62537..6211cb6 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600
+
 #include <ntstatus.h>
 #define WIN32_NO_STATUS
+#include <wine/test.h>
 #include <winsock2.h>
-#include <windows.h>
+#include <wine/winternl.h>
 #include <ws2tcpip.h>
+#include <wsipx.h>
+#include <wsnwlink.h>
 #include <mswsock.h>
 #include <mstcpip.h>
+#include <iphlpapi.h>
 #include <stdio.h>
-#include "wine/test.h"
-#include <ndk/umtypes.h>
+
 
 // ReactOS: Wine has this in mstcpip.h, but it doesn't belong there
 #define WSA_CMSG_ALIGN(len)     (((len) + sizeof(SIZE_T) - 1) & ~(sizeof(SIZE_T) - 1))
@@ -68,6 +74,19 @@ static int   (WINAPI *pgetaddrinfo)(LPCSTR,LPCSTR,const struct addrinfo *,struct
 static void  (WINAPI *pFreeAddrInfoW)(PADDRINFOW);
 static int   (WINAPI *pGetAddrInfoW)(LPCWSTR,LPCWSTR,const ADDRINFOW *,PADDRINFOW *);
 static PCSTR (WINAPI *pInetNtop)(INT,LPVOID,LPSTR,ULONG);
+static PCWSTR(WINAPI *pInetNtopW)(INT,LPVOID,LPWSTR,ULONG);
+static int   (WINAPI *pInetPtonA)(INT,LPCSTR,LPVOID);
+static int   (WINAPI *pInetPtonW)(INT,LPWSTR,LPVOID);
+static int   (WINAPI *pWSALookupServiceBeginW)(LPWSAQUERYSETW,DWORD,LPHANDLE);
+static int   (WINAPI *pWSALookupServiceEnd)(HANDLE);
+static int   (WINAPI *pWSALookupServiceNextW)(HANDLE,DWORD,LPDWORD,LPWSAQUERYSETW);
+static int   (WINAPI *pWSAEnumNameSpaceProvidersA)(LPDWORD,LPWSANAMESPACE_INFOA);
+static int   (WINAPI *pWSAEnumNameSpaceProvidersW)(LPDWORD,LPWSANAMESPACE_INFOW);
+static int   (WINAPI *pWSAPoll)(WSAPOLLFD *,ULONG,INT);
+
+/* Function pointers from iphlpapi */
+static DWORD (WINAPI *pGetAdaptersInfo)(PIP_ADAPTER_INFO,PULONG);
+static DWORD (WINAPI *pGetIpForwardTable)(PMIB_IPFORWARDTABLE,PULONG,BOOL);
 
 /**************** Structs and typedefs ***************/
 
@@ -150,6 +169,46 @@ typedef struct select_thread_params
     BOOL ReadKilled;
 } select_thread_params;
 
+/* Tests used in both getaddrinfo and GetAddrInfoW */
+static const struct addr_hint_tests
+{
+    int family, socktype, protocol;
+    DWORD error;
+} hinttests[] = {
+    {AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0 },
+    {AF_UNSPEC, SOCK_STREAM, IPPROTO_UDP, 0 },
+    {AF_UNSPEC, SOCK_STREAM, IPPROTO_IPV6,0 },
+    {AF_UNSPEC, SOCK_DGRAM,  IPPROTO_TCP, 0 },
+    {AF_UNSPEC, SOCK_DGRAM,  IPPROTO_UDP, 0 },
+    {AF_UNSPEC, SOCK_DGRAM,  IPPROTO_IPV6,0 },
+    {AF_INET,   SOCK_STREAM, IPPROTO_TCP, 0 },
+    {AF_INET,   SOCK_STREAM, IPPROTO_UDP, 0 },
+    {AF_INET,   SOCK_STREAM, IPPROTO_IPV6,0 },
+    {AF_INET,   SOCK_DGRAM,  IPPROTO_TCP, 0 },
+    {AF_INET,   SOCK_DGRAM,  IPPROTO_UDP, 0 },
+    {AF_INET,   SOCK_DGRAM,  IPPROTO_IPV6,0 },
+    {AF_UNSPEC, 0,           IPPROTO_TCP, 0 },
+    {AF_UNSPEC, 0,           IPPROTO_UDP, 0 },
+    {AF_UNSPEC, 0,           IPPROTO_IPV6,0 },
+    {AF_UNSPEC, SOCK_STREAM, 0,           0 },
+    {AF_UNSPEC, SOCK_DGRAM,  0,           0 },
+    {AF_INET,   0,           IPPROTO_TCP, 0 },
+    {AF_INET,   0,           IPPROTO_UDP, 0 },
+    {AF_INET,   0,           IPPROTO_IPV6,0 },
+    {AF_INET,   SOCK_STREAM, 0,           0 },
+    {AF_INET,   SOCK_DGRAM,  0,           0 },
+    {AF_UNSPEC, 999,         IPPROTO_TCP, WSAESOCKTNOSUPPORT },
+    {AF_UNSPEC, 999,         IPPROTO_UDP, WSAESOCKTNOSUPPORT },
+    {AF_UNSPEC, 999,         IPPROTO_IPV6,WSAESOCKTNOSUPPORT },
+    {AF_INET,   999,         IPPROTO_TCP, WSAESOCKTNOSUPPORT },
+    {AF_INET,   999,         IPPROTO_UDP, WSAESOCKTNOSUPPORT },
+    {AF_INET,   999,         IPPROTO_IPV6,WSAESOCKTNOSUPPORT },
+    {AF_UNSPEC, SOCK_STREAM, 999,         0 },
+    {AF_UNSPEC, SOCK_STREAM, 999,         0 },
+    {AF_INET,   SOCK_DGRAM,  999,         0 },
+    {AF_INET,   SOCK_DGRAM,  999,         0 },
+};
+
 /**************** Static variables ***************/
 
 static DWORD      tls;              /* Thread local storage index */
@@ -161,6 +220,9 @@ static int        client_id;
 
 /**************** General utility functions ***************/
 
+static SOCKET setup_server_socket(struct sockaddr_in *addr, int *len);
+static SOCKET setup_connector_socket(struct sockaddr_in *addr, int len, BOOL nonblock);
+
 static int tcp_socketpair(SOCKET *src, SOCKET *dst)
 {
     SOCKET server = INVALID_SOCKET;
@@ -171,11 +233,11 @@ static int tcp_socketpair(SOCKET *src, SOCKET *dst)
     *src = INVALID_SOCKET;
     *dst = INVALID_SOCKET;
 
-    *src = socket(AF_INET, SOCK_STREAM, 0);
+    *src = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     if (*src == INVALID_SOCKET)
         goto end;
 
-    server = socket(AF_INET, SOCK_STREAM, 0);
+    server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     if (server == INVALID_SOCKET)
         goto end;
 
@@ -263,42 +325,41 @@ static void read_zero_bytes ( SOCKET s )
     ok ( n <= 0, "garbage data received: %d bytes\n", n );
 }
 
-static int do_oob_send ( SOCKET s, char *buf, int buflen, int sendlen )
-{
-    char* last = buf + buflen, *p;
-    int n = 1;
-    for ( p = buf; n > 0 && p < last; p += n )
-        n = send ( s, p, min ( sendlen, last - p ), MSG_OOB );
-    wsa_ok ( n, 0 <=, "do_oob_send (%x): error %d\n" );
-    return p - buf;
-}
-
-static int do_synchronous_send ( SOCKET s, char *buf, int buflen, int sendlen )
+static int do_synchronous_send ( SOCKET s, char *buf, int buflen, int flags, int sendlen )
 {
     char* last = buf + buflen, *p;
     int n = 1;
-    for ( p = buf; n > 0 && p < last; p += n )
-        n = send ( s, p, min ( sendlen, last - p ), 0 );
+    for ( p = buf; n > 0 && p < last; )
+    {
+        n = send ( s, p, min ( sendlen, last - p ), flags );
+        if (n > 0) p += n;
+    }
     wsa_ok ( n, 0 <=, "do_synchronous_send (%x): error %d\n" );
     return p - buf;
 }
 
-static int do_synchronous_recv ( SOCKET s, char *buf, int buflen, int recvlen )
+static int do_synchronous_recv ( SOCKET s, char *buf, int buflen, int flags, int recvlen )
 {
     char* last = buf + buflen, *p;
     int n = 1;
-    for ( p = buf; n > 0 && p < last; p += n )
-        n = recv ( s, p, min ( recvlen, last - p ), 0 );
+    for ( p = buf; n > 0 && p < last; )
+    {
+        n = recv ( s, p, min ( recvlen, last - p ), flags );
+        if (n > 0) p += n;
+    }
     wsa_ok ( n, 0 <=, "do_synchronous_recv (%x): error %d:\n" );
     return p - buf;
 }
 
-static int do_synchronous_recvfrom ( SOCKET s, char *buf, int buflen,int flags,struct sockaddr *from, int *fromlen, int recvlen )
+static int do_synchronous_recvfrom ( SOCKET s, char *buf, int buflen, int flags, struct sockaddr *from, int *fromlen, int recvlen )
 {
     char* last = buf + buflen, *p;
     int n = 1;
-    for ( p = buf; n > 0 && p < last; p += n )
-      n = recvfrom ( s, p, min ( recvlen, last - p ), 0, from, fromlen );
+    for ( p = buf; n > 0 && p < last; )
+    {
+        n = recvfrom ( s, p, min ( recvlen, last - p ), flags, from, fromlen );
+        if (n > 0) p += n;
+    }
     wsa_ok ( n, 0 <=, "do_synchronous_recv (%x): error %d:\n" );
     return p - buf;
 }
@@ -315,6 +376,62 @@ static void check_so_opentype (void)
     ok ( tmp == 0, "check_so_opentype: wrong startup value of SO_OPENTYPE: %d\n", tmp );
 }
 
+static void compare_addrinfo (ADDRINFO *a, ADDRINFO *b)
+{
+    for (; a && b ; a = a->ai_next, b = b->ai_next)
+    {
+        ok(a->ai_flags == b->ai_flags,
+           "Wrong flags %d != %d\n", a->ai_flags, b->ai_flags);
+        ok(a->ai_family == b->ai_family,
+           "Wrong family %d != %d\n", a->ai_family, b->ai_family);
+        ok(a->ai_socktype == b->ai_socktype,
+           "Wrong socktype %d != %d\n", a->ai_socktype, b->ai_socktype);
+        ok(a->ai_protocol == b->ai_protocol,
+           "Wrong protocol %d != %d\n", a->ai_protocol, b->ai_protocol);
+        ok(a->ai_addrlen == b->ai_addrlen,
+           "Wrong addrlen %lu != %lu\n", a->ai_addrlen, b->ai_addrlen);
+        ok(!memcmp(a->ai_addr, b->ai_addr, min(a->ai_addrlen, b->ai_addrlen)),
+           "Wrong address data\n");
+        if (a->ai_canonname && b->ai_canonname)
+        {
+            ok(!strcmp(a->ai_canonname, b->ai_canonname), "Wrong canonical name '%s' != '%s'\n",
+               a->ai_canonname, b->ai_canonname);
+        }
+        else
+            ok(!a->ai_canonname && !b->ai_canonname, "Expected both names absent (%p != %p)\n",
+               a->ai_canonname, b->ai_canonname);
+    }
+    ok(!a && !b, "Expected both addresses null (%p != %p)\n", a, b);
+}
+
+static void compare_addrinfow (ADDRINFOW *a, ADDRINFOW *b)
+{
+    for (; a && b ; a = a->ai_next, b = b->ai_next)
+    {
+        ok(a->ai_flags == b->ai_flags,
+           "Wrong flags %d != %d\n", a->ai_flags, b->ai_flags);
+        ok(a->ai_family == b->ai_family,
+           "Wrong family %d != %d\n", a->ai_family, b->ai_family);
+        ok(a->ai_socktype == b->ai_socktype,
+           "Wrong socktype %d != %d\n", a->ai_socktype, b->ai_socktype);
+        ok(a->ai_protocol == b->ai_protocol,
+           "Wrong protocol %d != %d\n", a->ai_protocol, b->ai_protocol);
+        ok(a->ai_addrlen == b->ai_addrlen,
+           "Wrong addrlen %lu != %lu\n", a->ai_addrlen, b->ai_addrlen);
+        ok(!memcmp(a->ai_addr, b->ai_addr, min(a->ai_addrlen, b->ai_addrlen)),
+           "Wrong address data\n");
+        if (a->ai_canonname && b->ai_canonname)
+        {
+            ok(!lstrcmpW(a->ai_canonname, b->ai_canonname), "Wrong canonical name '%s' != '%s'\n",
+               wine_dbgstr_w(a->ai_canonname), wine_dbgstr_w(b->ai_canonname));
+        }
+        else
+            ok(!a->ai_canonname && !b->ai_canonname, "Expected both names absent (%p != %p)\n",
+               a->ai_canonname, b->ai_canonname);
+    }
+    ok(!a && !b, "Expected both addresses null (%p != %p)\n", a, b);
+}
+
 /**************** Server utility functions ***************/
 
 /*
@@ -454,14 +571,14 @@ static VOID WINAPI simple_server ( server_params *par )
              "simple_server (%x): strange peer address\n", id );
 
         /* Receive data & check it */
-        n_recvd = do_synchronous_recv ( mem->sock[0].s, mem->sock[0].buf, n_expected, par->buflen );
+        n_recvd = do_synchronous_recv ( mem->sock[0].s, mem->sock[0].buf, n_expected, 0, par->buflen );
         ok ( n_recvd == n_expected,
              "simple_server (%x): received less data than expected: %d of %d\n", id, n_recvd, n_expected );
         pos = test_buffer ( mem->sock[0].buf, gen->chunk_size, gen->n_chunks );
         ok ( pos == -1, "simple_server (%x): test pattern error: %d\n", id, pos);
 
         /* Echo data back */
-        n_sent = do_synchronous_send ( mem->sock[0].s, mem->sock[0].buf, n_expected, par->buflen );
+        n_sent = do_synchronous_send ( mem->sock[0].s, mem->sock[0].buf, n_expected, 0, par->buflen );
         ok ( n_sent == n_expected,
              "simple_server (%x): sent less data than expected: %d of %d\n", id, n_sent, n_expected );
 
@@ -483,7 +600,7 @@ static VOID WINAPI oob_server ( server_params *par )
     test_params *gen = par->general;
     server_memory *mem;
     u_long atmark = 0;
-    int pos, n_recvd, n_expected = gen->n_chunks * gen->chunk_size, tmp,
+    int pos, n_sent, n_recvd, n_expected = gen->n_chunks * gen->chunk_size, tmp,
         id = GetCurrentThreadId();
 
     trace ( "oob_server (%x) starting\n", id );
@@ -508,31 +625,37 @@ static VOID WINAPI oob_server ( server_params *par )
     ok ( mem->sock[0].peer.sin_addr.s_addr == inet_addr ( gen->inet_addr ),
          "oob_server (%x): strange peer address\n", id );
 
-    /* check atmark state */
+    /* check initial atmark state */
     ioctlsocket ( mem->sock[0].s, SIOCATMARK, &atmark );
     ok ( atmark == 1, "oob_server (%x): unexpectedly at the OOB mark: %i\n", id, atmark );
 
-    /* Receive normal data and check atmark state */
-    n_recvd = do_synchronous_recv ( mem->sock[0].s, mem->sock[0].buf, n_expected, par->buflen );
+    /* Receive normal data */
+    n_recvd = do_synchronous_recv ( mem->sock[0].s, mem->sock[0].buf, n_expected, 0, par->buflen );
     ok ( n_recvd == n_expected,
-         "simple_server (%x): received less data than expected: %d of %d\n", id, n_recvd, n_expected );
+         "oob_server (%x): received less data than expected: %d of %d\n", id, n_recvd, n_expected );
     pos = test_buffer ( mem->sock[0].buf, gen->chunk_size, gen->n_chunks );
-    ok ( pos == -1, "simple_server (%x): test pattern error: %d\n", id, pos);
+    ok ( pos == -1, "oob_server (%x): test pattern error: %d\n", id, pos);
 
+    /* check atmark state */
     ioctlsocket ( mem->sock[0].s, SIOCATMARK, &atmark );
     ok ( atmark == 1, "oob_server (%x): unexpectedly at the OOB mark: %i\n", id, atmark );
 
-    /* Receive a part of the out-of-band data and check atmark state */
-    n_recvd = do_synchronous_recv ( mem->sock[0].s, mem->sock[0].buf, 8, par->buflen );
+    /* Echo data back */
+    n_sent = do_synchronous_send ( mem->sock[0].s, mem->sock[0].buf, n_expected, 0, par->buflen );
+    ok ( n_sent == n_expected,
+         "oob_server (%x): sent less data than expected: %d of %d\n", id, n_sent, n_expected );
+
+    /* Receive a part of the out-of-band data and print atmark state */
+    n_recvd = do_synchronous_recv ( mem->sock[0].s, mem->sock[0].buf, 8, 0, par->buflen );
     ok ( n_recvd == 8,
          "oob_server (%x): received less data than expected: %d of %d\n", id, n_recvd, 8 );
     n_expected -= 8;
 
     ioctlsocket ( mem->sock[0].s, SIOCATMARK, &atmark );
-    todo_wine ok ( atmark == 0, "oob_server (%x): not at the OOB mark: %i\n", id, atmark );
+    trace( "oob_server (%x): %s the OOB mark: %i\n", id, atmark == 1 ? "not at" : "at", atmark );
 
     /* Receive the rest of the out-of-band data and check atmark state */
-    do_synchronous_recv ( mem->sock[0].s, mem->sock[0].buf, n_expected, par->buflen );
+    do_synchronous_recv ( mem->sock[0].s, mem->sock[0].buf, n_expected, 0, par->buflen );
 
     ioctlsocket ( mem->sock[0].s, SIOCATMARK, &atmark );
     todo_wine ok ( atmark == 0, "oob_server (%x): not at the OOB mark: %i\n", id, atmark );
@@ -705,7 +828,7 @@ static VOID WINAPI simple_client ( client_params *par )
     trace ( "simple_client (%x) connected\n", id );
 
     /* send data to server */
-    n_sent = do_synchronous_send ( mem->s, mem->send_buf, n_expected, par->buflen );
+    n_sent = do_synchronous_send ( mem->s, mem->send_buf, n_expected, 0, par->buflen );
     ok ( n_sent == n_expected,
          "simple_client (%x): sent less data than expected: %d of %d\n", id, n_sent, n_expected );
 
@@ -713,7 +836,7 @@ static VOID WINAPI simple_client ( client_params *par )
     wsa_ok ( shutdown ( mem->s, SD_SEND ), 0 ==, "simple_client (%x): shutdown failed: %d\n" );
 
     /* Receive data echoed back & check it */
-    n_recvd = do_synchronous_recv ( mem->s, mem->recv_buf, n_expected, par->buflen );
+    n_recvd = do_synchronous_recv ( mem->s, mem->recv_buf, n_expected, 0, par->buflen );
     ok ( n_recvd == n_expected,
          "simple_client (%x): received less data than expected: %d of %d\n", id, n_recvd, n_expected );
 
@@ -734,7 +857,7 @@ static VOID WINAPI oob_client ( client_params *par )
 {
     test_params *gen = par->general;
     client_memory *mem;
-    int n_sent, n_expected = gen->n_chunks * gen->chunk_size, id;
+    int pos, n_sent, n_recvd, n_expected = gen->n_chunks * gen->chunk_size, id;
 
     id = GetCurrentThreadId();
     trace ( "oob_client (%x): starting\n", id );
@@ -755,12 +878,19 @@ static VOID WINAPI oob_client ( client_params *par )
     trace ( "oob_client (%x) connected\n", id );
 
     /* send data to server */
-    n_sent = do_synchronous_send ( mem->s, mem->send_buf, n_expected, par->buflen );
+    n_sent = do_synchronous_send ( mem->s, mem->send_buf, n_expected, 0, par->buflen );
     ok ( n_sent == n_expected,
          "oob_client (%x): sent less data than expected: %d of %d\n", id, n_sent, n_expected );
 
+    /* Receive data echoed back & check it */
+    n_recvd = do_synchronous_recv ( mem->s, mem->recv_buf, n_expected, 0, par->buflen );
+    ok ( n_recvd == n_expected,
+         "simple_client (%x): received less data than expected: %d of %d\n", id, n_recvd, n_expected );
+    pos = test_buffer ( mem->recv_buf, gen->chunk_size, gen->n_chunks );
+    ok ( pos == -1, "simple_client (%x): test pattern error: %d\n", id, pos);
+
     /* send out-of-band data to server */
-    n_sent = do_oob_send ( mem->s, mem->send_buf, n_expected, par->buflen );
+    n_sent = do_synchronous_send ( mem->s, mem->send_buf, n_expected, MSG_OOB, par->buflen );
     ok ( n_sent == n_expected,
          "oob_client (%x): sent less data than expected: %d of %d\n", id, n_sent, n_expected );
 
@@ -803,7 +933,7 @@ static VOID WINAPI simple_mixed_client ( client_params *par )
     trace ( "simple_client (%x) connected\n", id );
 
     /* send data to server */
-    n_sent = do_synchronous_send ( mem->s, mem->send_buf, n_expected, par->buflen );
+    n_sent = do_synchronous_send ( mem->s, mem->send_buf, n_expected, 0, par->buflen );
     ok ( n_sent == n_expected,
          "simple_client (%x): sent less data than expected: %d of %d\n", id, n_sent, n_expected );
 
@@ -974,22 +1104,31 @@ out:
 /* Tests for WSAStartup */
 static void test_WithoutWSAStartup(void)
 {
-    LPVOID ptr;
+    DWORD err;
 
     WSASetLastError(0xdeadbeef);
-    ptr = gethostbyname("localhost");
+    ok(WSASocketA(0, 0, 0, NULL, 0, 0) == INVALID_SOCKET, "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSANOTINITIALISED, "Expected 10093, received %d\n", err);
 
-    ok(ptr == NULL, "gethostbyname() succeeded unexpectedly: %d\n", WSAGetLastError());
-    ok(WSAGetLastError() == WSANOTINITIALISED, "gethostbyname() failed with unexpected error: %d\n",
-                WSAGetLastError());
+    WSASetLastError(0xdeadbeef);
+    ok(gethostbyname("localhost") == NULL, "gethostbyname() succeeded unexpectedly\n");
+    err = WSAGetLastError();
+    ok(err == WSANOTINITIALISED, "Expected 10093, received %d\n", err);
 }
 
 static void test_WithWSAStartup(void)
 {
     WSADATA data;
     WORD version = MAKEWORD( 2, 2 );
-    INT res;
+    INT res, socks, i, j;
+    SOCKET sock;
     LPVOID ptr;
+    struct
+    {
+        SOCKET src, dst, dup_src, dup_dst;
+    } pairs[128];
+    DWORD error;
 
     res = WSAStartup( version, &data );
     ok(res == 0, "WSAStartup() failed unexpectedly: %d\n", res);
@@ -997,7 +1136,86 @@ static void test_WithWSAStartup(void)
     ptr = gethostbyname("localhost");
     ok(ptr != NULL, "gethostbyname() failed unexpectedly: %d\n", WSAGetLastError());
 
+    /* Alloc some sockets to check if they are destroyed on WSACleanup */
+    for (socks = 0; socks < sizeof(pairs) / sizeof(pairs[0]); socks++)
+    {
+        WSAPROTOCOL_INFOA info;
+        if (tcp_socketpair(&pairs[socks].src, &pairs[socks].dst)) break;
+
+        memset(&info, 0, sizeof(info));
+        ok(!WSADuplicateSocketA(pairs[socks].src, GetCurrentProcessId(), &info),
+           "WSADuplicateSocketA should have worked\n");
+        pairs[socks].dup_src = WSASocketA(0, 0, 0, &info, 0, 0);
+        ok(pairs[socks].dup_src != SOCKET_ERROR, "expected != -1\n");
+
+        memset(&info, 0, sizeof(info));
+        ok(!WSADuplicateSocketA(pairs[socks].dst, GetCurrentProcessId(), &info),
+           "WSADuplicateSocketA should have worked\n");
+        pairs[socks].dup_dst = WSASocketA(0, 0, 0, &info, 0, 0);
+        ok(pairs[socks].dup_dst != SOCKET_ERROR, "expected != -1\n");
+    }
+
+    res = send(pairs[0].src, "TEST", 4, 0);
+    ok(res == 4, "send failed with error %d\n", WSAGetLastError());
+
     WSACleanup();
+
+    res = WSAStartup( version, &data );
+    ok(res == 0, "WSAStartup() failed unexpectedly: %d\n", res);
+
+    /* show that sockets are destroyed automatically after WSACleanup */
+    SetLastError(0xdeadbeef);
+    res = send(pairs[0].src, "TEST", 4, 0);
+    error = WSAGetLastError();
+    ok(res == SOCKET_ERROR, "send should have failed\n");
+    todo_wine ok(error == WSAENOTSOCK, "expected 10038, got %d\n", error);
+
+    SetLastError(0xdeadbeef);
+    res = send(pairs[0].dst, "TEST", 4, 0);
+    error = WSAGetLastError();
+    ok(res == SOCKET_ERROR, "send should have failed\n");
+    todo_wine ok(error == WSAENOTSOCK, "expected 10038, got %d\n", error);
+
+    /* Check that all sockets were destroyed */
+    for (i = 0; i < socks; i++)
+    {
+        for (j = 0; j < 4; j++)
+        {
+            struct sockaddr_in saddr;
+            int size = sizeof(saddr);
+            switch(j)
+            {
+                case 0: sock = pairs[i].src; break;
+                case 1: sock = pairs[i].dup_src; break;
+                case 2: sock = pairs[i].dst; break;
+                case 3: sock = pairs[i].dup_dst; break;
+            }
+
+            SetLastError(0xdeadbeef);
+            res = getsockname(sock, (struct sockaddr *)&saddr, &size);
+            error = WSAGetLastError();
+            ok(res == SOCKET_ERROR, "Test[%d]: getsockname should have failed\n", i);
+            todo_wine ok(error == WSAENOTSOCK, "Test[%d]: expected 10038, got %d\n", i, error);
+        }
+    }
+
+    /* While wine is not fixed, close all sockets manually */
+    for (i = 0; i < socks; i++)
+    {
+        closesocket(pairs[i].src);
+        closesocket(pairs[i].dst);
+        closesocket(pairs[i].dup_src);
+        closesocket(pairs[i].dup_dst);
+    }
+
+    res = WSACleanup();
+    ok(res == 0, "expected 0, got %d\n", res);
+    WSASetLastError(0xdeadbeef);
+    res = WSACleanup();
+    error = WSAGetLastError();
+    ok ( (res == SOCKET_ERROR && error ==  WSANOTINITIALISED) ||
+         broken(res == 0),  /* WinME */
+            "WSACleanup returned %d WSAGetLastError is %d\n", res, error);
 }
 
 /**************** Main program utility functions ***************/
@@ -1006,13 +1224,29 @@ static void Init (void)
 {
     WORD ver = MAKEWORD (2, 2);
     WSADATA data;
-    HMODULE hws2_32 = GetModuleHandle("ws2_32.dll");
+    HMODULE hws2_32 = GetModuleHandleA("ws2_32.dll"), hiphlpapi;
 
     pfreeaddrinfo = (void *)GetProcAddress(hws2_32, "freeaddrinfo");
     pgetaddrinfo = (void *)GetProcAddress(hws2_32, "getaddrinfo");
     pFreeAddrInfoW = (void *)GetProcAddress(hws2_32, "FreeAddrInfoW");
     pGetAddrInfoW = (void *)GetProcAddress(hws2_32, "GetAddrInfoW");
     pInetNtop = (void *)GetProcAddress(hws2_32, "inet_ntop");
+    pInetNtopW = (void *)GetProcAddress(hws2_32, "InetNtopW");
+    pInetPtonA = (void *)GetProcAddress(hws2_32, "inet_pton");
+    pInetPtonW = (void *)GetProcAddress(hws2_32, "InetPtonW");
+    pWSALookupServiceBeginW = (void *)GetProcAddress(hws2_32, "WSALookupServiceBeginW");
+    pWSALookupServiceEnd = (void *)GetProcAddress(hws2_32, "WSALookupServiceEnd");
+    pWSALookupServiceNextW = (void *)GetProcAddress(hws2_32, "WSALookupServiceNextW");
+    pWSAEnumNameSpaceProvidersA = (void *)GetProcAddress(hws2_32, "WSAEnumNameSpaceProvidersA");
+    pWSAEnumNameSpaceProvidersW = (void *)GetProcAddress(hws2_32, "WSAEnumNameSpaceProvidersW");
+    pWSAPoll = (void *)GetProcAddress(hws2_32, "WSAPoll");
+
+    hiphlpapi = LoadLibraryA("iphlpapi.dll");
+    if (hiphlpapi)
+    {
+        pGetIpForwardTable = (void *)GetProcAddress(hiphlpapi, "GetIpForwardTable");
+        pGetAdaptersInfo = (void *)GetProcAddress(hiphlpapi, "GetAdaptersInfo");
+    }
 
     ok ( WSAStartup ( ver, &data ) == 0, "WSAStartup failed\n" );
     tls = TlsAlloc();
@@ -1025,11 +1259,6 @@ static void Exit (void)
     ret = WSACleanup();
     err = WSAGetLastError();
     ok ( ret == 0, "WSACleanup failed ret = %d GetLastError is %d\n", ret, err);
-    ret = WSACleanup();
-    err = WSAGetLastError();
-    ok ( (ret == SOCKET_ERROR && err ==  WSANOTINITIALISED) ||
-         broken(ret == 0),  /* WinME */
-            "WSACleanup returned %d GetLastError is %d\n", ret, err);
 }
 
 static void StartServer (LPTHREAD_START_ROUTINE routine,
@@ -1104,11 +1333,29 @@ static const LINGER linger_testvals[] = {
 
 static void test_set_getsockopt(void)
 {
-    SOCKET s;
+    SOCKET s, s2;
     int i, err, lasterr;
     int timeout;
     LINGER lingval;
     int size;
+    WSAPROTOCOL_INFOA infoA;
+    WSAPROTOCOL_INFOW infoW;
+    char providername[WSAPROTOCOL_LEN + 1];
+    DWORD value;
+    struct _prottest
+    {
+        int family, type, proto;
+    } prottest[] = {
+        {AF_INET, SOCK_STREAM, IPPROTO_TCP},
+        {AF_INET, SOCK_DGRAM, IPPROTO_UDP},
+        {AF_INET6, SOCK_STREAM, IPPROTO_TCP},
+        {AF_INET6, SOCK_DGRAM, IPPROTO_UDP}
+    };
+    union _csspace
+    {
+        CSADDR_INFO cs;
+        char space[128];
+    } csinfoA, csinfoB;
 
     s = socket(AF_INET, SOCK_STREAM, 0);
     ok(s!=INVALID_SOCKET, "socket() failed error: %d\n", WSAGetLastError());
@@ -1138,6 +1385,27 @@ static void test_set_getsockopt(void)
         err = getsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeout, &size); 
     ok( !err, "get/setsockopt(SO_SNDTIMEO) failed error: %d\n", WSAGetLastError());
     ok( timeout == SOCKTIMEOUT2, "getsockopt(SO_SNDTIMEO) returned wrong value %d\n", timeout);
+
+    /* SO_SNDBUF */
+    value = 4096;
+    size = sizeof(value);
+    err = setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&value, size);
+    ok( !err, "setsockopt(SO_SNDBUF) failed error: %u\n", WSAGetLastError() );
+    value = 0xdeadbeef;
+    err = getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&value, &size);
+    ok( !err, "getsockopt(SO_SNDBUF) failed error: %u\n", WSAGetLastError() );
+    ok( value == 4096, "expected 4096, got %u\n", value );
+
+    /* SO_RCVBUF */
+    value = 4096;
+    size = sizeof(value);
+    err = setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&value, size);
+    ok( !err, "setsockopt(SO_RCVBUF) failed error: %u\n", WSAGetLastError() );
+    value = 0xdeadbeef;
+    err = getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&value, &size);
+    ok( !err, "getsockopt(SO_RCVBUF) failed error: %u\n", WSAGetLastError() );
+    ok( value == 4096, "expected 4096, got %u\n", value );
+
     /* SO_LINGER */
     for( i = 0; i < sizeof(linger_testvals)/sizeof(LINGER);i++) {
         size =  sizeof(lingval);
@@ -1186,17 +1454,276 @@ static void test_set_getsockopt(void)
     SetLastError(0xdeadbeef);
     err = setsockopt(s, 0xffffffff, SO_RCVTIMEO, (char *) &timeout, size);
     ok( (err == SOCKET_ERROR) && (WSAGetLastError() == WSAEINVAL),
-        "got %d with %d (expected SOCKET_ERROR with WSAEINVAL\n",
+        "got %d with %d (expected SOCKET_ERROR with WSAEINVAL)\n",
         err, WSAGetLastError());
 
     timeout = SOCKTIMEOUT1;
     SetLastError(0xdeadbeef);
     err = setsockopt(s, 0x00008000, SO_RCVTIMEO, (char *) &timeout, size);
     ok( (err == SOCKET_ERROR) && (WSAGetLastError() == WSAEINVAL),
-        "got %d with %d (expected SOCKET_ERROR with WSAEINVAL\n",
+        "got %d with %d (expected SOCKET_ERROR with WSAEINVAL)\n",
+        err, WSAGetLastError());
+
+    /* Test SO_ERROR set/get */
+    SetLastError(0xdeadbeef);
+    i = 1234;
+    err = setsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &i, size);
+todo_wine
+    ok( !err && !WSAGetLastError(),
+        "got %d with %d (expected 0 with 0)\n",
+        err, WSAGetLastError());
+
+    SetLastError(0xdeadbeef);
+    i = 4321;
+    err = getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &i, &size);
+todo_wine
+    ok( !err && !WSAGetLastError(),
+        "got %d with %d (expected 0 with 0)\n",
+        err, WSAGetLastError());
+todo_wine
+    ok (i == 1234, "got %d (expected 1234)\n", i);
+
+    /* Test invalid optlen */
+    SetLastError(0xdeadbeef);
+    size = 1;
+    err = getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &i, &size);
+todo_wine
+    ok( (err == SOCKET_ERROR) && (WSAGetLastError() == WSAEFAULT),
+        "got %d with %d (expected SOCKET_ERROR with WSAEFAULT)\n",
+        err, WSAGetLastError());
+
+    closesocket(s);
+    /* Test with the closed socket */
+    SetLastError(0xdeadbeef);
+    size = sizeof(i);
+    i = 1234;
+    err = getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &i, &size);
+todo_wine
+    ok( (err == SOCKET_ERROR) && (WSAGetLastError() == WSAENOTSOCK),
+        "got %d with %d (expected SOCKET_ERROR with WSAENOTSOCK)\n",
         err, WSAGetLastError());
+    ok (i == 1234, "expected 1234, got %d\n", i);
+
+    /* Test WS_IP_MULTICAST_TTL with 8, 16, 24 and 32 bits values */
+    s = socket(AF_INET, SOCK_DGRAM, 0);
+    ok(s != INVALID_SOCKET, "Failed to create socket\n");
+    size = sizeof(i);
+    i = 0x0000000a;
+    err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &i, size);
+    if (!err)
+    {
+        for (i = 0; i < 4; i++)
+        {
+            int k, j;
+            const int tests[] = {0xffffff0a, 0xffff000b, 0xff00000c, 0x0000000d};
+            err = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &tests[i], i + 1);
+            ok(!err, "Test [%d] Expected 0, got %d\n", i, err);
+            err = getsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &k, &size);
+            ok(!err, "Test [%d] Expected 0, got %d\n", i, err);
+            j = i != 3 ? tests[i] & ((1 << (i + 1) * 8) - 1) : tests[i];
+            ok(k == j, "Test [%d] Expected 0x%x, got 0x%x\n", i, j, k);
+        }
+    }
+    else
+        win_skip("IP_MULTICAST_TTL is unsupported\n");
+    closesocket(s);
+
+    /* test SO_PROTOCOL_INFOA invalid parameters */
+    ok(getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_PROTOCOL_INFOA, NULL, NULL),
+       "getsockopt should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAENOTSOCK, "expected 10038, got %d instead\n", err);
+    size = sizeof(WSAPROTOCOL_INFOA);
+    ok(getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, &size),
+       "getsockopt should have failed\n");
+    ok(size == sizeof(WSAPROTOCOL_INFOA), "got size %d\n", size);
+    err = WSAGetLastError();
+    ok(err == WSAENOTSOCK, "expected 10038, got %d instead\n", err);
+    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    ok(getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, NULL, NULL),
+       "getsockopt should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
+    ok(getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, NULL),
+       "getsockopt should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
+    ok(getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, NULL, &size),
+       "getsockopt should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
+    size = sizeof(WSAPROTOCOL_INFOA) / 2;
+    ok(getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, &size),
+       "getsockopt should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
+    ok(size == sizeof(WSAPROTOCOL_INFOA), "got size %d\n", size);
+    size = sizeof(WSAPROTOCOL_INFOA) * 2;
+    err = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, &size);
+    ok(!err,"getsockopt failed with %d\n", WSAGetLastError());
+    ok(size == sizeof(WSAPROTOCOL_INFOA) * 2, "got size %d\n", size);
+
+    closesocket(s);
+
+    /* test SO_PROTOCOL_INFO structure returned for different protocols */
+    for (i = 0; i < sizeof(prottest) / sizeof(prottest[0]); i++)
+    {
+        s = socket(prottest[i].family, prottest[i].type, prottest[i].proto);
+        if (s == INVALID_SOCKET && prottest[i].family == AF_INET6) continue;
+
+        ok(s != INVALID_SOCKET, "Failed to create socket: %d\n",
+          WSAGetLastError());
+
+        /* compare both A and W version */
+        infoA.szProtocol[0] = 0;
+        size = sizeof(WSAPROTOCOL_INFOA);
+        err = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, &size);
+        ok(!err,"getsockopt failed with %d\n", WSAGetLastError());
+        ok(size == sizeof(WSAPROTOCOL_INFOA), "got size %d\n", size);
+
+        infoW.szProtocol[0] = 0;
+        size = sizeof(WSAPROTOCOL_INFOW);
+        err = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOW, (char *) &infoW, &size);
+        ok(!err,"getsockopt failed with %d\n", WSAGetLastError());
+        ok(size == sizeof(WSAPROTOCOL_INFOW), "got size %d\n", size);
+
+        trace("provider name '%s', family %d, type %d, proto %d\n",
+              infoA.szProtocol, prottest[i].family, prottest[i].type, prottest[i].proto);
+
+        ok(infoA.szProtocol[0] || broken(!infoA.szProtocol[0]) /* NT4 */,
+           "WSAPROTOCOL_INFOA was not filled\n");
+        ok(infoW.szProtocol[0] || broken(!infoA.szProtocol[0]) /* NT4 */,
+           "WSAPROTOCOL_INFOW was not filled\n");
+
+        WideCharToMultiByte(CP_ACP, 0, infoW.szProtocol, -1,
+                            providername, sizeof(providername), NULL, NULL);
+        ok(!strcmp(infoA.szProtocol,providername),
+           "different provider names '%s' != '%s'\n", infoA.szProtocol, providername);
+
+        ok(!memcmp(&infoA, &infoW, FIELD_OFFSET(WSAPROTOCOL_INFOA, szProtocol)),
+           "SO_PROTOCOL_INFO[A/W] comparison failed\n");
+
+        /* Remove IF when WSAEnumProtocols support IPV6 data */
+        todo_wine_if (prottest[i].family == AF_INET6)
+            ok(infoA.iAddressFamily == prottest[i].family, "socket family invalid, expected %d received %d\n",
+               prottest[i].family, infoA.iAddressFamily);
+        ok(infoA.iSocketType == prottest[i].type, "socket type invalid, expected %d received %d\n",
+           prottest[i].type, infoA.iSocketType);
+        ok(infoA.iProtocol == prottest[i].proto, "socket protocol invalid, expected %d received %d\n",
+           prottest[i].proto, infoA.iProtocol);
+
+        closesocket(s);
+    }
+
+    /* Test SO_BSP_STATE - Present only in >= Win 2008 */
+    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    ok(s != INVALID_SOCKET, "Failed to create socket\n");
+    s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    ok(s2 != INVALID_SOCKET, "Failed to create socket\n");
+
+    SetLastError(0xdeadbeef);
+    size = sizeof(csinfoA);
+    err = getsockopt(s, SOL_SOCKET, SO_BSP_STATE, (char *) &csinfoA, &size);
+    if (!err)
+    {
+        struct sockaddr_in saddr;
+        memset(&saddr, 0, sizeof(saddr));
+        saddr.sin_family = AF_INET;
+        saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+        /* Socket is not bound, no information provided */
+        ok(!csinfoA.cs.LocalAddr.iSockaddrLength, "Expected 0, got %d\n", csinfoA.cs.LocalAddr.iSockaddrLength);
+        ok(csinfoA.cs.LocalAddr.lpSockaddr == NULL, "Expected NULL, got %p\n", csinfoA.cs.LocalAddr.lpSockaddr);
+        /* Socket is not connected, no information provided */
+        ok(!csinfoA.cs.RemoteAddr.iSockaddrLength, "Expected 0, got %d\n", csinfoA.cs.LocalAddr.iSockaddrLength);
+        ok(csinfoA.cs.RemoteAddr.lpSockaddr == NULL, "Expected NULL, got %p\n", csinfoA.cs.LocalAddr.lpSockaddr);
+
+        err = bind(s, (struct sockaddr*)&saddr, sizeof(saddr));
+        ok(!err, "Expected 0, got %d\n", err);
+        size = sizeof(csinfoA);
+        err = getsockopt(s, SOL_SOCKET, SO_BSP_STATE, (char *) &csinfoA, &size);
+        ok(!err, "Expected 0, got %d\n", err);
+
+        /* Socket is bound */
+        ok(csinfoA.cs.LocalAddr.iSockaddrLength, "Expected non-zero\n");
+        ok(csinfoA.cs.LocalAddr.lpSockaddr != NULL, "Expected non-null\n");
+        /* Socket is not connected, no information provided */
+        ok(!csinfoA.cs.RemoteAddr.iSockaddrLength, "Expected 0, got %d\n", csinfoA.cs.LocalAddr.iSockaddrLength);
+        ok(csinfoA.cs.RemoteAddr.lpSockaddr == NULL, "Expected NULL, got %p\n", csinfoA.cs.LocalAddr.lpSockaddr);
+
+        err = bind(s2, (struct sockaddr*)&saddr, sizeof(saddr));
+        ok(!err, "Expected 0, got %d\n", err);
+        err = getsockname(s2, (struct sockaddr *)&saddr, &size);
+        ok(!err, "Expected 0, got %d\n", err);
+        err = listen(s2, 1);
+        ok(!err, "Expected 0, got %d\n", err);
+        err = connect(s, (struct sockaddr*)&saddr, sizeof(saddr));
+        ok(!err, "Expected 0, got %d\n", err);
+        size = sizeof(saddr);
+        err = accept(s2, (struct sockaddr*)&saddr, &size);
+        ok(err != INVALID_SOCKET, "Failed to accept socket\n");
+        closesocket(s2);
+        s2 = err;
+
+        size = sizeof(csinfoA);
+        err = getsockopt(s, SOL_SOCKET, SO_BSP_STATE, (char *) &csinfoA, &size);
+        ok(!err, "Expected 0, got %d\n", err);
+        err = getsockopt(s2, SOL_SOCKET, SO_BSP_STATE, (char *) &csinfoB, &size);
+        ok(!err, "Expected 0, got %d\n", err);
+        ok(size == sizeof(csinfoA), "Got %d\n", size);
+        size = sizeof(saddr);
+        ok(size == csinfoA.cs.LocalAddr.iSockaddrLength, "Expected %d, got %d\n", size,
+           csinfoA.cs.LocalAddr.iSockaddrLength);
+        ok(size == csinfoA.cs.RemoteAddr.iSockaddrLength, "Expected %d, got %d\n", size,
+           csinfoA.cs.RemoteAddr.iSockaddrLength);
+        ok(!memcmp(csinfoA.cs.LocalAddr.lpSockaddr, csinfoB.cs.RemoteAddr.lpSockaddr, size),
+           "Expected matching addresses\n");
+        ok(!memcmp(csinfoB.cs.LocalAddr.lpSockaddr, csinfoA.cs.RemoteAddr.lpSockaddr, size),
+           "Expected matching addresses\n");
+        ok(csinfoA.cs.iSocketType == SOCK_STREAM, "Wrong socket type\n");
+        ok(csinfoB.cs.iSocketType == SOCK_STREAM, "Wrong socket type\n");
+        ok(csinfoA.cs.iProtocol == IPPROTO_TCP, "Wrong socket protocol\n");
+        ok(csinfoB.cs.iProtocol == IPPROTO_TCP, "Wrong socket protocol\n");
+
+        err = getpeername(s, (struct sockaddr *)&saddr, &size);
+        ok(!err, "Expected 0, got %d\n", err);
+        ok(!memcmp(&saddr, csinfoA.cs.RemoteAddr.lpSockaddr, size), "Expected matching addresses\n");
+        ok(!memcmp(&saddr, csinfoB.cs.LocalAddr.lpSockaddr, size), "Expected matching addresses\n");
+        err = getpeername(s2, (struct sockaddr *)&saddr, &size);
+        ok(!err, "Expected 0, got %d\n", err);
+        ok(!memcmp(&saddr, csinfoB.cs.RemoteAddr.lpSockaddr, size), "Expected matching addresses\n");
+        ok(!memcmp(&saddr, csinfoA.cs.LocalAddr.lpSockaddr, size), "Expected matching addresses\n");
+        err = getsockname(s, (struct sockaddr *)&saddr, &size);
+        ok(!err, "Expected 0, got %d\n", err);
+        ok(!memcmp(&saddr, csinfoA.cs.LocalAddr.lpSockaddr, size), "Expected matching addresses\n");
+        ok(!memcmp(&saddr, csinfoB.cs.RemoteAddr.lpSockaddr, size), "Expected matching addresses\n");
+        err = getsockname(s2, (struct sockaddr *)&saddr, &size);
+        ok(!err, "Expected 0, got %d\n", err);
+        ok(!memcmp(&saddr, csinfoB.cs.LocalAddr.lpSockaddr, size), "Expected matching addresses\n");
+        ok(!memcmp(&saddr, csinfoA.cs.RemoteAddr.lpSockaddr, size), "Expected matching addresses\n");
+
+        SetLastError(0xdeadbeef);
+        size = sizeof(CSADDR_INFO);
+        err = getsockopt(s, SOL_SOCKET, SO_BSP_STATE, (char *) &csinfoA, &size);
+        ok(err, "Expected non-zero\n");
+        ok(size == sizeof(CSADDR_INFO), "Got %d\n", size);
+        ok(GetLastError() == WSAEFAULT, "Expected 10014, got %d\n", GetLastError());
+
+        /* At least for IPv4 the size is exactly 56 bytes */
+        size = sizeof(*csinfoA.cs.LocalAddr.lpSockaddr) * 2 + sizeof(csinfoA.cs);
+        err = getsockopt(s, SOL_SOCKET, SO_BSP_STATE, (char *) &csinfoA, &size);
+        ok(!err, "Expected 0, got %d\n", err);
+        size--;
+        SetLastError(0xdeadbeef);
+        err = getsockopt(s, SOL_SOCKET, SO_BSP_STATE, (char *) &csinfoA, &size);
+        ok(err, "Expected non-zero\n");
+        ok(GetLastError() == WSAEFAULT, "Expected 10014, got %d\n", GetLastError());
+    }
+    else
+        ok(GetLastError() == WSAENOPROTOOPT, "Expected 10042, got %d\n", GetLastError());
 
     closesocket(s);
+    closesocket(s2);
 }
 
 static void test_so_reuseaddr(void)
@@ -1205,6 +1732,7 @@ static void test_so_reuseaddr(void)
     SOCKET s1,s2;
     unsigned int rc,reuse;
     int size;
+    DWORD err;
 
     saddr.sin_family      = AF_INET;
     saddr.sin_port        = htons(9375);
@@ -1233,9 +1761,44 @@ static void test_so_reuseaddr(void)
     /* On Win2k3 and above, all SO_REUSEADDR seems to do is to allow binding to
      * a port immediately after closing another socket on that port, so
      * basically following the BSD socket semantics here. */
-    closesocket(s1);
     rc = bind(s2, (struct sockaddr*)&saddr, sizeof(saddr));
-    ok(rc==0, "bind() failed error: %d\n", WSAGetLastError());
+    if(rc==0)
+    {
+        int s3=socket(AF_INET, SOCK_STREAM, 0), s4;
+        trace("<= Win XP behavior of SO_REUSEADDR\n");
+
+        /* If we could bind again in the same port this is Windows version <= XP.
+         * Lets test if we can really connect to one of them. */
+        set_blocking(s1, FALSE);
+        set_blocking(s2, FALSE);
+        rc = listen(s1, 1);
+        ok(!rc, "listen() failed with error: %d\n", WSAGetLastError());
+        rc = listen(s2, 1);
+        ok(!rc, "listen() failed with error: %d\n", WSAGetLastError());
+        rc = connect(s3, (struct sockaddr*)&saddr, sizeof(saddr));
+        ok(!rc, "connecting to accepting socket failed %d\n", WSAGetLastError());
+
+        /* the delivery of the connection is random so we need to try on both sockets */
+        size = sizeof(saddr);
+        s4 = accept(s1, (struct sockaddr*)&saddr, &size);
+        if(s4 == INVALID_SOCKET)
+            s4 = accept(s2, (struct sockaddr*)&saddr, &size);
+        ok(s4 != INVALID_SOCKET, "none of the listening sockets could get the connection\n");
+
+        closesocket(s1);
+        closesocket(s3);
+        closesocket(s4);
+    }
+    else
+    {
+        trace(">= Win 2003 behavior of SO_REUSEADDR\n");
+        err = WSAGetLastError();
+        ok(err==WSAEACCES, "expected 10013, got %d\n", err);
+
+        closesocket(s1);
+        rc = bind(s2, (struct sockaddr*)&saddr, sizeof(saddr));
+        ok(rc==0, "bind() failed error: %d\n", WSAGetLastError());
+    }
 
     closesocket(s2);
 }
@@ -1249,7 +1812,8 @@ static void test_ip_pktinfo(void)
     struct sockaddr_in s1addr, s2addr, s3addr;
     GUID WSARecvMsg_GUID = WSAID_WSARECVMSG;
     LPFN_WSARECVMSG pWSARecvMsg = NULL;
-    unsigned int rc, foundhdr, yes = 1;
+    unsigned int rc, yes = 1;
+    BOOL foundhdr;
     DWORD dwBytes, dwSize, dwFlags;
     socklen_t addrlen;
     WSACMSGHDR *cmsg;
@@ -1260,7 +1824,7 @@ static void test_ip_pktinfo(void)
     int i, err;
 
     memset(&ov, 0, sizeof(ov));
-    ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    ov.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
     if (ov.hEvent == INVALID_HANDLE_VALUE)
     {
         skip("Could not create event object, some tests will be skipped. errno = %d\n", GetLastError());
@@ -1335,8 +1899,10 @@ static void test_ip_pktinfo(void)
          * Send a packet from the client to the server and test for specifying
          * a short control header.
          */
+        SetLastError(0xdeadbeef);
         rc=sendto(s2, msg, sizeof(msg), 0, (struct sockaddr*)&s2addr, sizeof(s2addr));
         ok(rc == sizeof(msg), "sendto() failed error: %d\n", WSAGetLastError());
+        ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
         hdr.Control.len = 1;
         rc=pWSARecvMsg(s1, &hdr, &dwSize, NULL, NULL);
         err=WSAGetLastError();
@@ -1349,8 +1915,10 @@ static void test_ip_pktinfo(void)
         rc=pWSARecvMsg(s1, &hdr, NULL, &ov, NULL);
         err=WSAGetLastError();
         ok(rc != 0 && err == WSA_IO_PENDING, "WSARecvMsg() failed error: %d\n", err);
+        SetLastError(0xdeadbeef);
         rc=sendto(s2, msg, sizeof(msg), 0, (struct sockaddr*)&s2addr, sizeof(s2addr));
         ok(rc == sizeof(msg), "sendto() failed error: %d\n", WSAGetLastError());
+        ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
         if (WaitForSingleObject(ov.hEvent, 100) != WAIT_OBJECT_0)
         {
             skip("Server side did not receive packet, some tests skipped.\n");
@@ -1593,7 +2161,8 @@ static DWORD WINAPI do_getservbyname( void *param )
     int i, j;
     struct servent *pserv[2];
 
-    ok ( WaitForSingleObject ( *starttest, TEST_TIMEOUT * 1000 ) != WAIT_TIMEOUT, "test_getservbyname: timeout waiting for start signal\n");
+    ok ( WaitForSingleObject ( *starttest, TEST_TIMEOUT * 1000 ) != WAIT_TIMEOUT,
+         "test_getservbyname: timeout waiting for start signal\n" );
 
     /* ensure that necessary buffer resizes are completed */
     for ( j = 0; j < 2; j++) {
@@ -1603,14 +2172,19 @@ static DWORD WINAPI do_getservbyname( void *param )
     for ( i = 0; i < NUM_QUERIES / 2; i++ ) {
         for ( j = 0; j < 2; j++ ) {
             pserv[j] = getservbyname ( serv[j].name, serv[j].proto );
-            ok ( pserv[j] != NULL, "getservbyname could not retrieve information for %s: %d\n", serv[j].name, WSAGetLastError() );
+            ok ( pserv[j] != NULL || broken(pserv[j] == NULL) /* win8, fixed in win81 */,
+                 "getservbyname could not retrieve information for %s: %d\n", serv[j].name, WSAGetLastError() );
             if ( !pserv[j] ) continue;
-            ok ( pserv[j]->s_port == htons(serv[j].port), "getservbyname returned the wrong port for %s: %d\n", serv[j].name, ntohs(pserv[j]->s_port) );
-            ok ( !strcmp ( pserv[j]->s_proto, serv[j].proto ), "getservbyname returned the wrong protocol for %s: %s\n", serv[j].name, pserv[j]->s_proto );
-            ok ( !strcmp ( pserv[j]->s_name, serv[j].name ), "getservbyname returned the wrong name for %s: %s\n", serv[j].name, pserv[j]->s_name );
+            ok ( pserv[j]->s_port == htons(serv[j].port),
+                 "getservbyname returned the wrong port for %s: %d\n", serv[j].name, ntohs(pserv[j]->s_port) );
+            ok ( !strcmp ( pserv[j]->s_proto, serv[j].proto ),
+                 "getservbyname returned the wrong protocol for %s: %s\n", serv[j].name, pserv[j]->s_proto );
+            ok ( !strcmp ( pserv[j]->s_name, serv[j].name ),
+                 "getservbyname returned the wrong name for %s: %s\n", serv[j].name, pserv[j]->s_name );
         }
 
-        ok ( pserv[0] == pserv[1], "getservbyname: winsock resized servent buffer when not necessary\n" );
+        ok ( pserv[0] == pserv[1] || broken(pserv[0] != pserv[1]) /* win8, fixed in win81 */,
+             "getservbyname: winsock resized servent buffer when not necessary\n" );
     }
 
     return 0;
@@ -1622,7 +2196,7 @@ static void test_getservbyname(void)
     HANDLE starttest, thread[NUM_THREADS];
     DWORD thread_id[NUM_THREADS];
 
-    starttest = CreateEvent ( NULL, 1, 0, "test_getservbyname_starttest" );
+    starttest = CreateEventA ( NULL, 1, 0, "test_getservbyname_starttest" );
 
     /* create threads */
     for ( i = 0; i < NUM_THREADS; i++ ) {
@@ -1641,17 +2215,120 @@ static void test_WSASocket(void)
 {
     SOCKET sock = INVALID_SOCKET;
     WSAPROTOCOL_INFOA *pi;
-    int providers[] = {6, 0};
-    int ret, err;
+    int wsaproviders[] = {IPPROTO_TCP, IPPROTO_IP};
+    int autoprotocols[] = {IPPROTO_TCP, IPPROTO_UDP};
+    int items, err, size, socktype, i, j;
     UINT pi_size;
 
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(0, 0, 0, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEINVAL, "Expected 10022, received %d\n", err);
+
+    sock = WSASocketA(AF_INET, 0, 0, NULL, 0, 0);
+    ok(sock != INVALID_SOCKET, "WSASocketA should have succeeded\n");
+    closesocket(sock);
+
+    sock = WSASocketA(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
+    ok(sock != INVALID_SOCKET, "WSASocketA should have succeeded\n");
+    closesocket(sock);
+
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(0, SOCK_STREAM, -1, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEPROTONOSUPPORT, "Expected 10043, received %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(0, -1, IPPROTO_UDP, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAESOCKTNOSUPPORT, "Expected 10044, received %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(0, -1, 0, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEINVAL, "Expected 10022, received %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(AF_INET, -1, 0, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAESOCKTNOSUPPORT, "Expected 10044, received %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(AF_INET, 0, -1, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEPROTONOSUPPORT, "Expected 10043, received %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(0, -1, -1, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAESOCKTNOSUPPORT, "Expected 10044, received %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(-1, SOCK_STREAM, IPPROTO_UDP, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEAFNOSUPPORT, "Expected 10047, received %d\n", err);
+
+    sock = WSASocketA(AF_INET, 0, IPPROTO_TCP, NULL, 0, 0);
+    ok(sock != INVALID_SOCKET, "WSASocketA should have succeeded\n");
+    closesocket(sock);
+
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(0, SOCK_STREAM, 0, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEINVAL, "Expected 10022, received %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(0, 0, 0xdead, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEPROTONOSUPPORT, "Expected 10043, received %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(AF_INET, 0xdead, 0, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAESOCKTNOSUPPORT, "Expected 10044, received %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(0, 0xdead, 0, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEINVAL, "Expected 10022, received %d\n", err);
+
+    sock = WSASocketA(0, 0, IPPROTO_TCP, NULL, 0, 0);
+    ok(sock != INVALID_SOCKET, "WSASocketA should have succeeded\n");
+    closesocket(sock);
+
+    /* SOCK_STREAM does not support IPPROTO_UDP */
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_UDP, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEPROTONOSUPPORT, "Expected 10043, received %d\n", err);
+
+    /* SOCK_DGRAM does not support IPPROTO_TCP */
+    SetLastError(0xdeadbeef);
+    ok(WSASocketA(AF_INET, SOCK_DGRAM, IPPROTO_TCP, NULL, 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEPROTONOSUPPORT, "Expected 10043, received %d\n", err);
+
     /* Set pi_size explicitly to a value below 2*sizeof(WSAPROTOCOL_INFOA)
      * to avoid a crash on win98.
      */
     pi_size = 0;
-    ret = WSAEnumProtocolsA(providers, NULL, &pi_size);
-    ok(ret == SOCKET_ERROR, "WSAEnumProtocolsA({6,0}, NULL, 0) returned %d\n",
-            ret);
+    items = WSAEnumProtocolsA(wsaproviders, NULL, &pi_size);
+    ok(items == SOCKET_ERROR, "WSAEnumProtocolsA({6,0}, NULL, 0) returned %d\n",
+            items);
     err = WSAGetLastError();
     ok(err == WSAENOBUFS, "WSAEnumProtocolsA error is %d, not WSAENOBUFS(%d)\n",
             err, WSAENOBUFS);
@@ -1663,11 +2340,11 @@ static void test_WSASocket(void)
         return;
     }
 
-    ret = WSAEnumProtocolsA(providers, pi, &pi_size);
-    ok(ret != SOCKET_ERROR, "WSAEnumProtocolsA failed, last error is %d\n",
+    items = WSAEnumProtocolsA(wsaproviders, pi, &pi_size);
+    ok(items != SOCKET_ERROR, "WSAEnumProtocolsA failed, last error is %d\n",
             WSAGetLastError());
 
-    if (ret == 0) {
+    if (items == 0) {
         skip("No protocols enumerated.\n");
         HeapFree(GetProcessHeap(), 0, pi);
         return;
@@ -1677,58 +2354,537 @@ static void test_WSASocket(void)
                       FROM_PROTOCOL_INFO, &pi[0], 0, 0);
     ok(sock != INVALID_SOCKET, "Failed to create socket: %d\n",
             WSAGetLastError());
-
     closesocket(sock);
-    HeapFree(GetProcessHeap(), 0, pi);
-}
 
-static void test_WSAAddressToStringA(void)
-{
-    SOCKET v6 = INVALID_SOCKET;
-    INT ret;
-    DWORD len;
-    int GLE;
-    SOCKADDR_IN sockaddr;
-    CHAR address[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
+    /* find what parameters are used first: plain parameters or protocol info struct */
+    pi[0].iProtocol = -1;
+    pi[0].iSocketType = -1;
+    pi[0].iAddressFamily = -1;
+    ok(WSASocketA(0, 0, IPPROTO_UDP, &pi[0], 0, 0) == INVALID_SOCKET,
+       "WSASocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEAFNOSUPPORT, "Expected 10047, received %d\n", err);
 
-    CHAR expect1[] = "0.0.0.0";
-    CHAR expect2[] = "255.255.255.255";
-    CHAR expect3[] = "0.0.0.0:65535";
-    CHAR expect4[] = "255.255.255.255:65535";
+    pi[0].iProtocol = 0;
+    pi[0].iSocketType = 0;
+    pi[0].iAddressFamily = 0;
+    sock = WSASocketA(0, 0, IPPROTO_UDP, &pi[0], 0, 0);
+    if(sock != INVALID_SOCKET)
+    {
+      win_skip("must work only in OS <= 2003\n");
+      closesocket(sock);
+    }
+    else
+    {
+      err = WSAGetLastError();
+      ok(err == WSAEAFNOSUPPORT, "Expected 10047, received %d\n", err);
+    }
 
-    SOCKADDR_IN6 sockaddr6;
-    CHAR address6[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
+    pi[0].iProtocol = IPPROTO_UDP;
+    pi[0].iSocketType = SOCK_DGRAM;
+    pi[0].iAddressFamily = AF_INET;
+    sock = WSASocketA(0, 0, 0, &pi[0], 0, 0);
+    ok(sock != INVALID_SOCKET, "Failed to create socket: %d\n",
+            WSAGetLastError());
+    size = sizeof(socktype);
+    socktype = 0xdead;
+    err = getsockopt(sock, SOL_SOCKET, SO_TYPE, (char *) &socktype, &size);
+    ok(!err,"getsockopt failed with %d\n", WSAGetLastError());
+    ok(socktype == SOCK_DGRAM, "Wrong socket type, expected %d received %d\n",
+       SOCK_DGRAM, socktype);
+    closesocket(sock);
 
-    CHAR addr6_1[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
-    CHAR addr6_2[] = {0x20,0xab,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
-    CHAR addr6_3[] = {0x20,0xab,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01};
+    sock = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, &pi[0], 0, 0);
+    ok(sock != INVALID_SOCKET, "Failed to create socket: %d\n",
+            WSAGetLastError());
+    size = sizeof(socktype);
+    socktype = 0xdead;
+    err = getsockopt(sock, SOL_SOCKET, SO_TYPE, (char *) &socktype, &size);
+    ok(!err,"getsockopt failed with %d\n", WSAGetLastError());
+    ok(socktype == SOCK_STREAM, "Wrong socket type, expected %d received %d\n",
+       SOCK_STREAM, socktype);
+    closesocket(sock);
 
-    CHAR expect6_1[] = "::1";
-    CHAR expect6_2[] = "20ab::1";
-    CHAR expect6_3[] = "[20ab::2001]:33274";
-    CHAR expect6_3_nt[] = "20ab::2001@33274";
-    CHAR expect6_3_w2k[] = "20ab::2001";
-    CHAR expect6_3_2[] = "[20ab::2001%4660]:33274";
-    CHAR expect6_3_2_nt[] = "4660/20ab::2001@33274";
-    CHAR expect6_3_2_w2k[] = "20ab::2001%4660";
-    CHAR expect6_3_3[] = "20ab::2001%4660";
-    CHAR expect6_3_3_nt[] = "4660/20ab::2001";
+    HeapFree(GetProcessHeap(), 0, pi);
 
-    len = 0;
+    pi_size = 0;
+    items = WSAEnumProtocolsA(NULL, NULL, &pi_size);
+    ok(items == SOCKET_ERROR, "WSAEnumProtocolsA(NULL, NULL, 0) returned %d\n",
+            items);
+    err = WSAGetLastError();
+    ok(err == WSAENOBUFS, "WSAEnumProtocolsA error is %d, not WSAENOBUFS(%d)\n",
+            err, WSAENOBUFS);
 
-    sockaddr.sin_family = AF_INET;
-    sockaddr.sin_port = 0;
-    sockaddr.sin_addr.s_addr = 0;
+    pi = HeapAlloc(GetProcessHeap(), 0, pi_size);
+    ok(pi != NULL, "Failed to allocate memory\n");
+    if (pi == NULL) {
+        skip("Can't continue without memory.\n");
+        return;
+    }
 
-    ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
-    GLE = WSAGetLastError();
-    ok( (ret == SOCKET_ERROR && GLE == WSAEFAULT) || (ret == 0), 
-        "WSAAddressToStringA() failed unexpectedly: WSAGetLastError()=%d, ret=%d\n",
-        GLE, ret );
+    items = WSAEnumProtocolsA(NULL, pi, &pi_size);
+    ok(items != SOCKET_ERROR, "WSAEnumProtocolsA failed, last error is %d\n",
+            WSAGetLastError());
 
-    len = sizeof(address);
+    /* when no protocol and socket type are specified the first entry
+     * from WSAEnumProtocols that has the flag PFL_MATCHES_PROTOCOL_ZERO
+     * is returned */
+    sock = WSASocketA(AF_INET, 0, 0, NULL, 0, 0);
+    ok(sock != INVALID_SOCKET, "Failed to create socket: %d\n",
+            WSAGetLastError());
 
-    sockaddr.sin_family = AF_INET;
+    size = sizeof(socktype);
+    socktype = 0xdead;
+    err = getsockopt(sock, SOL_SOCKET, SO_TYPE, (char *) &socktype, &size);
+    ok(!err, "getsockopt failed with %d\n", WSAGetLastError());
+    for(i = 0; i < items; i++)
+    {
+        if(pi[i].dwProviderFlags & PFL_MATCHES_PROTOCOL_ZERO)
+        {
+            ok(socktype == pi[i].iSocketType, "Wrong socket type, expected %d received %d\n",
+               pi[i].iSocketType, socktype);
+             break;
+        }
+    }
+    ok(i != items, "Creating a socket without protocol and socket type didn't work\n");
+    closesocket(sock);
+
+    /* when no socket type is specified the first entry from WSAEnumProtocols
+     * that matches the protocol is returned */
+    for (i = 0; i < sizeof(autoprotocols) / sizeof(autoprotocols[0]); i++)
+    {
+        sock = WSASocketA(0, 0, autoprotocols[i], NULL, 0, 0);
+        ok(sock != INVALID_SOCKET, "Failed to create socket for protocol %d, received %d\n",
+                autoprotocols[i], WSAGetLastError());
+
+        size = sizeof(socktype);
+        socktype = 0xdead;
+        err = getsockopt(sock, SOL_SOCKET, SO_TYPE, (char *) &socktype, &size);
+        ok(!err, "getsockopt failed with %d\n", WSAGetLastError());
+
+        for (err = 1, j = 0; j < items; j++)
+        {
+            if (pi[j].iProtocol == autoprotocols[i])
+            {
+                if (socktype == pi[j].iSocketType)
+                    err = 0;
+                else
+                    ok(0, "Wrong socket type, expected %d received %d\n",
+                       pi[j].iSocketType, socktype);
+                break;
+            }
+        }
+        ok(!err, "Protocol %d not found in WSAEnumProtocols\n", autoprotocols[i]);
+
+        closesocket(sock);
+    }
+
+    HeapFree(GetProcessHeap(), 0, pi);
+
+    SetLastError(0xdeadbeef);
+    /* starting on vista the socket function returns error during the socket
+       creation and no longer in the socket operations (sendto, readfrom) */
+    sock = WSASocketA(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0);
+    if (sock == INVALID_SOCKET)
+    {
+        err = WSAGetLastError();
+        ok(err == WSAEACCES, "Expected 10013, received %d\n", err);
+        skip("SOCK_RAW is not supported\n");
+    }
+    else
+    {
+        trace("SOCK_RAW is supported\n");
+
+        size = sizeof(socktype);
+        socktype = 0xdead;
+        err = getsockopt(sock, SOL_SOCKET, SO_TYPE, (char *) &socktype, &size);
+        ok(!err, "getsockopt failed with %d\n", WSAGetLastError());
+        ok(socktype == SOCK_RAW, "Wrong socket type, expected %d received %d\n",
+           SOCK_RAW, socktype);
+        closesocket(sock);
+
+        todo_wine {
+        sock = WSASocketA(0, 0, IPPROTO_RAW, NULL, 0, 0);
+        ok(sock != INVALID_SOCKET, "Failed to create socket: %d\n",
+           WSAGetLastError());
+        size = sizeof(socktype);
+        socktype = 0xdead;
+        err = getsockopt(sock, SOL_SOCKET, SO_TYPE, (char *) &socktype, &size);
+        ok(!err, "getsockopt failed with %d\n", WSAGetLastError());
+        ok(socktype == SOCK_RAW, "Wrong socket type, expected %d received %d\n",
+           SOCK_RAW, socktype);
+        closesocket(sock);
+        }
+
+        sock = WSASocketA(AF_INET, SOCK_RAW, IPPROTO_TCP, NULL, 0, 0);
+        ok(sock != INVALID_SOCKET, "Failed to create socket: %d\n",
+           WSAGetLastError());
+        size = sizeof(socktype);
+        socktype = 0xdead;
+        err = getsockopt(sock, SOL_SOCKET, SO_TYPE, (char *) &socktype, &size);
+        ok(!err, "getsockopt failed with %d\n", WSAGetLastError());
+        ok(socktype == SOCK_RAW, "Wrong socket type, expected %d received %d\n",
+           SOCK_RAW, socktype);
+        closesocket(sock);
+    }
+
+    /* IPX socket tests */
+
+    SetLastError(0xdeadbeef);
+    sock = WSASocketA(AF_IPX, SOCK_DGRAM, NSPROTO_IPX, NULL, 0, 0);
+    if (sock == INVALID_SOCKET)
+    {
+        err = WSAGetLastError();
+        todo_wine_if (err == WSAEPROTONOSUPPORT)
+        ok(err == WSAEAFNOSUPPORT || broken(err == WSAEPROTONOSUPPORT), "Expected 10047, received %d\n", err);
+        skip("IPX is not supported\n");
+    }
+    else
+    {
+        WSAPROTOCOL_INFOA info;
+        closesocket(sock);
+
+        trace("IPX is supported\n");
+
+        sock = WSASocketA(0, 0, NSPROTO_IPX, NULL, 0, 0);
+        ok(sock != INVALID_SOCKET, "Failed to create socket: %d\n",
+                WSAGetLastError());
+
+        size = sizeof(socktype);
+        socktype = 0xdead;
+        err = getsockopt(sock, SOL_SOCKET, SO_TYPE, (char *) &socktype, &size);
+        ok(!err,"getsockopt failed with %d\n", WSAGetLastError());
+        ok(socktype == SOCK_DGRAM, "Wrong socket type, expected %d received %d\n",
+           SOCK_DGRAM, socktype);
+
+        /* check socket family, type and protocol */
+        size = sizeof(WSAPROTOCOL_INFOA);
+        err = getsockopt(sock, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &info, &size);
+        ok(!err,"getsockopt failed with %d\n", WSAGetLastError());
+        ok(info.iProtocol == NSPROTO_IPX, "expected protocol %d, received %d\n",
+           NSPROTO_IPX, info.iProtocol);
+        ok(info.iAddressFamily == AF_IPX, "expected family %d, received %d\n",
+           AF_IPX, info.iProtocol);
+        ok(info.iSocketType == SOCK_DGRAM, "expected type %d, received %d\n",
+           SOCK_DGRAM, info.iSocketType);
+        closesocket(sock);
+
+        /* SOCK_STREAM does not support NSPROTO_IPX */
+        SetLastError(0xdeadbeef);
+        ok(WSASocketA(AF_IPX, SOCK_STREAM, NSPROTO_IPX, NULL, 0, 0) == INVALID_SOCKET,
+           "WSASocketA should have failed\n");
+        err = WSAGetLastError();
+        ok(err == WSAEPROTONOSUPPORT, "Expected 10043, received %d\n", err);
+
+        /* test extended IPX support - that is adding any number between 0 and 255
+         * to the IPX protocol value will make it be used as IPX packet type */
+        for(i = 0;i <= 255;i += 17)
+        {
+          SetLastError(0xdeadbeef);
+          sock = WSASocketA(0, 0, NSPROTO_IPX + i, NULL, 0, 0);
+          ok(sock != INVALID_SOCKET, "Failed to create socket: %d\n",
+                  WSAGetLastError());
+
+          size = sizeof(int);
+          socktype = -1;
+          err = getsockopt(sock, NSPROTO_IPX, IPX_PTYPE, (char *) &socktype, &size);
+          ok(!err, "getsockopt failed with %d\n", WSAGetLastError());
+          ok(socktype == i, "Wrong IPX packet type, expected %d received %d\n",
+             i, socktype);
+
+          closesocket(sock);
+        }
+    }
+}
+
+static void test_WSADuplicateSocket(void)
+{
+    SOCKET source, dupsock;
+    WSAPROTOCOL_INFOA info;
+    DWORD err;
+    struct sockaddr_in addr;
+    int socktype, size, addrsize, ret;
+    char teststr[] = "TEST", buffer[16];
+
+    source = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
+    ok(source != INVALID_SOCKET, "WSASocketA should have succeeded\n");
+
+    /* test invalid parameters */
+    SetLastError(0xdeadbeef);
+    ok(WSADuplicateSocketA(0, 0, NULL), "WSADuplicateSocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAENOTSOCK, "expected 10038, received %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ok(WSADuplicateSocketA(source, 0, NULL),
+       "WSADuplicateSocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEINVAL, "expected 10022, received %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ok(WSADuplicateSocketA(source, ~0, &info),
+       "WSADuplicateSocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEINVAL, "expected 10022, received %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ok(WSADuplicateSocketA(0, GetCurrentProcessId(), &info),
+       "WSADuplicateSocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAENOTSOCK, "expected 10038, received %d\n", err);
+
+    SetLastError(0xdeadbeef);
+    ok(WSADuplicateSocketA(source, GetCurrentProcessId(), NULL),
+       "WSADuplicateSocketA should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEFAULT, "expected 10014, received %d\n", err);
+
+    /* test returned structure */
+    memset(&info, 0, sizeof(info));
+    ok(!WSADuplicateSocketA(source, GetCurrentProcessId(), &info),
+       "WSADuplicateSocketA should have worked\n");
+
+    ok(info.iProtocol == IPPROTO_TCP, "expected protocol %d, received %d\n",
+       IPPROTO_TCP, info.iProtocol);
+    ok(info.iAddressFamily == AF_INET, "expected family %d, received %d\n",
+       AF_INET, info.iProtocol);
+    ok(info.iSocketType == SOCK_STREAM, "expected type %d, received %d\n",
+       SOCK_STREAM, info.iSocketType);
+
+    dupsock = WSASocketA(0, 0, 0, &info, 0, 0);
+    ok(dupsock != INVALID_SOCKET, "WSASocketA should have succeeded\n");
+
+    closesocket(dupsock);
+    closesocket(source);
+
+    /* create a socket, bind it, duplicate it then send data on source and
+     * receive in the duplicated socket */
+    source = WSASocketA(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
+    ok(source != INVALID_SOCKET, "WSASocketA should have succeeded\n");
+
+    memset(&info, 0, sizeof(info));
+    ok(!WSADuplicateSocketA(source, GetCurrentProcessId(), &info),
+       "WSADuplicateSocketA should have worked\n");
+
+    ok(info.iProtocol == IPPROTO_UDP, "expected protocol %d, received %d\n",
+       IPPROTO_UDP, info.iProtocol);
+    ok(info.iAddressFamily == AF_INET, "expected family %d, received %d\n",
+       AF_INET, info.iProtocol);
+    ok(info.iSocketType == SOCK_DGRAM, "expected type %d, received %d\n",
+       SOCK_DGRAM, info.iSocketType);
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+    ok(!bind(source, (struct sockaddr*)&addr, sizeof(addr)),
+       "bind should have worked\n");
+
+    /* read address to find out the port number to be used in sendto */
+    memset(&addr, 0, sizeof(addr));
+    addrsize = sizeof(addr);
+    ok(!getsockname(source, (struct sockaddr *) &addr, &addrsize),
+       "getsockname should have worked\n");
+    ok(addr.sin_port, "socket port should be != 0\n");
+
+    dupsock = WSASocketA(0, 0, 0, &info, 0, 0);
+    ok(dupsock != INVALID_SOCKET, "WSASocketA should have succeeded\n");
+
+    size = sizeof(int);
+    ret = getsockopt(dupsock, SOL_SOCKET, SO_TYPE, (char *) &socktype, &size);
+    ok(!ret, "getsockopt failed with %d\n", WSAGetLastError());
+    ok(socktype == SOCK_DGRAM, "Wrong socket type, expected %d received %d\n",
+       SOCK_DGRAM, socktype);
+
+    set_blocking(source, TRUE);
+
+    /* send data on source socket */
+    addrsize = sizeof(addr);
+    size = sendto(source, teststr, sizeof(teststr), 0, (struct sockaddr *) &addr, addrsize);
+    ok(size == sizeof(teststr), "got %d (err %d)\n", size, WSAGetLastError());
+
+    /* receive on duplicated socket */
+    addrsize = sizeof(addr);
+    memset(buffer, 0, sizeof(buffer));
+    size = recvfrom(dupsock, buffer, sizeof(teststr), 0, (struct sockaddr *) &addr, &addrsize);
+    ok(size == sizeof(teststr), "got %d (err %d)\n", size, WSAGetLastError());
+    buffer[sizeof(teststr) - 1] = 0;
+    ok(!strcmp(buffer, teststr), "expected '%s', received '%s'\n", teststr, buffer);
+
+    closesocket(dupsock);
+    closesocket(source);
+
+    /* show that the source socket need to be bound before the duplicated
+     * socket is created */
+    source = WSASocketA(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
+    ok(source != INVALID_SOCKET, "WSASocketA should have succeeded\n");
+
+    memset(&info, 0, sizeof(info));
+    ok(!WSADuplicateSocketA(source, GetCurrentProcessId(), &info),
+       "WSADuplicateSocketA should have worked\n");
+
+    dupsock = WSASocketA(0, 0, 0, &info, 0, 0);
+    ok(dupsock != INVALID_SOCKET, "WSASocketA should have succeeded\n");
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+    ok(!bind(source, (struct sockaddr*)&addr, sizeof(addr)),
+       "bind should have worked\n");
+
+    /* read address to find out the port number to be used in sendto */
+    memset(&addr, 0, sizeof(addr));
+    addrsize = sizeof(addr);
+    ok(!getsockname(source, (struct sockaddr *) &addr, &addrsize),
+       "getsockname should have worked\n");
+    ok(addr.sin_port, "socket port should be != 0\n");
+
+    set_blocking(source, TRUE);
+
+    addrsize = sizeof(addr);
+    size = sendto(source, teststr, sizeof(teststr), 0, (struct sockaddr *) &addr, addrsize);
+    ok(size == sizeof(teststr), "got %d (err %d)\n", size, WSAGetLastError());
+
+    SetLastError(0xdeadbeef);
+    addrsize = sizeof(addr);
+    memset(buffer, 0, sizeof(buffer));
+    todo_wine {
+    ok(recvfrom(dupsock, buffer, sizeof(teststr), 0, (struct sockaddr *) &addr, &addrsize) == -1,
+       "recvfrom should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEINVAL, "expected 10022, received %d\n", err);
+    }
+
+    closesocket(dupsock);
+    closesocket(source);
+}
+
+static void test_WSAEnumNetworkEvents(void)
+{
+    SOCKET s, s2;
+    int sock_type[] = {SOCK_STREAM, SOCK_DGRAM, SOCK_STREAM}, i, j, k, l;
+    struct sockaddr_in address;
+    HANDLE event;
+    WSANETWORKEVENTS net_events;
+    /* Windows 2000 Pro without SP installed (testbot) will crash if
+     * WSAEnumNetworkEvents have a NULL event, so skip this test in <= 2000 */
+    DWORD ver = GetVersion() & 0xFFFF;
+    BOOL supports_null = ((ver & 0xFF) << 8 | (ver >> 8)) > 0x0500;
+
+    memset(&address, 0, sizeof(address));
+    address.sin_addr.s_addr = htonl(INADDR_ANY);
+    address.sin_family = AF_INET;
+
+    /* This test follows the steps from bugs 10204 and 24946 */
+    for (l = 0; l < 2; l++)
+    {
+        if (l == 1 && !supports_null && broken(1)) continue;
+
+        for (i = 0; i < sizeof(sock_type) / sizeof(sock_type[0]); i++)
+        {
+            if (i == 2)
+                ok(!tcp_socketpair(&s, &s2), "Test[%d]: creating socket pair failed\n", i);
+            else
+            {
+                s = socket(AF_INET, sock_type[i], 0);
+                ok (s != SOCKET_ERROR, "Test[%d]: failed to create socket\n", i);
+                ok (!bind(s, (struct sockaddr*) &address, sizeof(address)), "Test[%d]: bind failed\n", i);
+            }
+            event = WSACreateEvent();
+            ok (event != NULL, "Test[%d]: failed to create event\n", i);
+            for (j = 0; j < 5; j++) /* Repeat sometimes and the result must be the same */
+            {
+                /* When the TCP socket is not connected NO events will be returned.
+                 * When connected and no data pending it will get the write event.
+                 * UDP sockets don't have connections so as soon as they are bound
+                 * they can read/write data. Since nobody is sendind us data only
+                 * the write event will be returned and ONLY once.
+                 */
+                ok (!WSAEventSelect(s, event, FD_READ | FD_WRITE), "Test[%d]: WSAEventSelect failed\n", i);
+                memset(&net_events, 0xAB, sizeof(net_events));
+                ok (!WSAEnumNetworkEvents(s, l == 0 ? event : NULL, &net_events),
+                    "Test[%d]: WSAEnumNetworkEvents failed\n", i);
+                if (i >= 1 && j == 0) /* FD_WRITE is SET on first try for UDP and connected TCP */
+                {
+                    todo_wine_if (i == 0 || net_events.lNetworkEvents == 0)
+                        ok (net_events.lNetworkEvents == FD_WRITE, "Test[%d]: expected 2, got %d\n",
+                            i, net_events.lNetworkEvents);
+                }
+                else
+                {
+                    todo_wine_if (i != 0 && net_events.lNetworkEvents != 0)
+                        ok (net_events.lNetworkEvents == 0, "Test[%d]: expected 0, got %d\n",
+                            i, net_events.lNetworkEvents);
+                }
+                for (k = 0; k < FD_MAX_EVENTS; k++)
+                {
+                    if (i >= 1 && j == 0 && k == 1) /* first UDP and connected TCP test, FD_WRITE bit no error*/
+                    {
+                        ok (net_events.iErrorCode[k] == 0x0, "Test[%d][%d]: expected 0x0, got 0x%x\n",
+                            i, k, net_events.iErrorCode[k]);
+                    }
+                    else
+                    {
+                        /* Bits that are not set in lNetworkEvents MUST not be changed */
+                        todo_wine
+                        ok (net_events.iErrorCode[k] == 0xABABABAB, "Test[%d][%d]: expected 0xABABABAB, got 0x%x\n",
+                            i, k, net_events.iErrorCode[k]);
+                    }
+                }
+            }
+            closesocket(s);
+            WSACloseEvent(event);
+            if (i == 2) closesocket(s2);
+        }
+    }
+}
+
+static void test_WSAAddressToStringA(void)
+{
+    SOCKET v6 = INVALID_SOCKET;
+    INT ret;
+    DWORD len;
+    int GLE;
+    SOCKADDR_IN sockaddr;
+    CHAR address[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
+
+    CHAR expect1[] = "0.0.0.0";
+    CHAR expect2[] = "255.255.255.255";
+    CHAR expect3[] = "0.0.0.0:65535";
+    CHAR expect4[] = "255.255.255.255:65535";
+
+    SOCKADDR_IN6 sockaddr6;
+    CHAR address6[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
+
+    CHAR addr6_1[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
+    CHAR addr6_2[] = {0x20,0xab,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
+    CHAR addr6_3[] = {0x20,0xab,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x01};
+
+    CHAR expect6_1[] = "::1";
+    CHAR expect6_2[] = "20ab::1";
+    CHAR expect6_3[] = "[20ab::2001]:33274";
+    CHAR expect6_3_nt[] = "20ab::2001@33274";
+    CHAR expect6_3_w2k[] = "20ab::2001";
+    CHAR expect6_3_2[] = "[20ab::2001%4660]:33274";
+    CHAR expect6_3_2_nt[] = "4660/20ab::2001@33274";
+    CHAR expect6_3_2_w2k[] = "20ab::2001%4660";
+    CHAR expect6_3_3[] = "20ab::2001%4660";
+    CHAR expect6_3_3_nt[] = "4660/20ab::2001";
+
+    len = 0;
+
+    sockaddr.sin_family = AF_INET;
+    sockaddr.sin_port = 0;
+    sockaddr.sin_addr.s_addr = 0;
+
+    ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
+    GLE = WSAGetLastError();
+    ok( (ret == SOCKET_ERROR && GLE == WSAEFAULT) || (ret == 0), 
+        "WSAAddressToStringA() failed unexpectedly: WSAGetLastError()=%d, ret=%d\n",
+        GLE, ret );
+
+    len = sizeof(address);
+
+    sockaddr.sin_family = AF_INET;
     sockaddr.sin_port = 0;
     sockaddr.sin_addr.s_addr = 0;
 
@@ -2069,6 +3225,7 @@ static void test_WSAStringToAddressA(void)
     CHAR address6[] = "::1";
     CHAR address7[] = "[::1]";
     CHAR address8[] = "[::1]:65535";
+    CHAR address9[] = "2001::1";
 
     len = 0;
     sockaddr.sin_family = AF_INET;
@@ -2152,6 +3309,12 @@ static void test_WSAStringToAddressA(void)
         (ret == SOCKET_ERROR && GLE == WSAEINVAL),
         "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE);
 
+    len = sizeof(sockaddr);
+
+    ret = WSAStringToAddressA( address9, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
+    GLE = WSAGetLastError();
+    ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL),
+        "WSAStringToAddressA() should have failed with %d\n", GLE );
 }
 
 static void test_WSAStringToAddressW(void)
@@ -2172,6 +3335,7 @@ static void test_WSAStringToAddressW(void)
     WCHAR address6[] = {':',':','1','\0'};
     WCHAR address7[] = {'[',':',':','1',']','\0'};
     WCHAR address8[] = {'[',':',':','1',']',':','6','5','5','3','5','\0'};
+    WCHAR address9[] = {'2','0','0','1',':',':','1','\0'};
 
     len = 0;
     sockaddr.sin_family = AF_INET;
@@ -2268,6 +3432,12 @@ static void test_WSAStringToAddressW(void)
         (ret == SOCKET_ERROR && GLE == WSAEINVAL),
         "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE);
 
+    len = sizeof(sockaddr);
+
+    ret = WSAStringToAddressW( address9, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
+    GLE = WSAGetLastError();
+    ok( (ret == SOCKET_ERROR && GLE == WSAEINVAL),
+        "WSAStringToAddressW() should have failed with %d\n", GLE );
 }
 
 static DWORD WINAPI SelectReadThread(void *param)
@@ -2296,6 +3466,14 @@ static DWORD WINAPI SelectReadThread(void *param)
     return 0;
 }
 
+static DWORD WINAPI SelectCloseThread(void *param)
+{
+    SOCKET s = *(SOCKET*)param;
+    Sleep(500);
+    closesocket(s);
+    return 0;
+}
+
 static void test_errors(void)
 {
     SOCKET sock;
@@ -2333,50 +3511,147 @@ static void test_errors(void)
     ok ( (ret == 0), "closesocket failed unexpectedly: %d\n", WSAGetLastError());
 }
 
+static void test_listen(void)
+{
+    SOCKET fdA, fdB;
+    int ret, acceptc, olen = sizeof(acceptc);
+    struct sockaddr_in address;
+
+    memset(&address, 0, sizeof(address));
+    address.sin_addr.s_addr = inet_addr("127.0.0.1");
+    address.sin_family = AF_INET;
+    address.sin_port = htons(SERVERPORT);
+
+    /* invalid socket tests */
+    SetLastError(0xdeadbeef);
+    ok ((listen(0, 0) == SOCKET_ERROR), "listen did not fail\n");
+    ret = WSAGetLastError();
+    ok (ret == WSAENOTSOCK, "expected 10038, received %d\n", ret);
+
+    SetLastError(0xdeadbeef);
+    ok ((listen(0xdeadbeef, 0) == SOCKET_ERROR), "listen did not fail\n");
+    ret = WSAGetLastError();
+    ok (ret == WSAENOTSOCK, "expected 10038, received %d\n", ret);
+
+    /* tcp tests */
+    fdA = socket(AF_INET, SOCK_STREAM, 0);
+    ok ((fdA != INVALID_SOCKET), "socket failed unexpectedly: %d\n", WSAGetLastError() );
+
+    fdB = socket(AF_INET, SOCK_STREAM, 0);
+    ok ((fdB != INVALID_SOCKET), "socket failed unexpectedly: %d\n", WSAGetLastError() );
+
+    SetLastError(0xdeadbeef);
+    ok ((listen(fdA, -2) == SOCKET_ERROR), "listen did not fail\n");
+    ret = WSAGetLastError();
+    ok (ret == WSAEINVAL, "expected 10022, received %d\n", ret);
+
+    SetLastError(0xdeadbeef);
+    ok ((listen(fdA, 1) == SOCKET_ERROR), "listen did not fail\n");
+    ret = WSAGetLastError();
+    ok (ret == WSAEINVAL, "expected 10022, received %d\n", ret);
+
+    SetLastError(0xdeadbeef);
+    ok ((listen(fdA, SOMAXCONN) == SOCKET_ERROR), "listen did not fail\n");
+    ret = WSAGetLastError();
+    ok (ret == WSAEINVAL, "expected 10022, received %d\n", ret);
+
+    ok (!bind(fdA, (struct sockaddr*) &address, sizeof(address)), "bind failed\n");
+
+    SetLastError(0xdeadbeef);
+    ok (bind(fdB, (struct sockaddr*) &address, sizeof(address)), "bind should have failed\n");
+    ok (ret == WSAEINVAL, "expected 10022, received %d\n", ret);
+
+    acceptc = 0xdead;
+    ret = getsockopt(fdA, SOL_SOCKET, SO_ACCEPTCONN, (char*)&acceptc, &olen);
+    ok (!ret, "getsockopt failed\n");
+    ok (acceptc == 0, "SO_ACCEPTCONN should be 0, received %d\n", acceptc);
+
+    ok (!listen(fdA, 0), "listen failed\n");
+    ok (!listen(fdA, SOMAXCONN), "double listen failed\n");
+
+    acceptc = 0xdead;
+    ret = getsockopt(fdA, SOL_SOCKET, SO_ACCEPTCONN, (char*)&acceptc, &olen);
+    ok (!ret, "getsockopt failed\n");
+    ok (acceptc == 1, "SO_ACCEPTCONN should be 1, received %d\n", acceptc);
+
+    SetLastError(0xdeadbeef);
+    ok ((listen(fdB, SOMAXCONN) == SOCKET_ERROR), "listen did not fail\n");
+    ret = WSAGetLastError();
+    ok (ret == WSAEINVAL, "expected 10022, received %d\n", ret);
+
+    ret = closesocket(fdB);
+    ok (ret == 0, "closesocket failed unexpectedly: %d\n", ret);
+
+    fdB = socket(AF_INET, SOCK_STREAM, 0);
+    ok ((fdB != INVALID_SOCKET), "socket failed unexpectedly: %d\n", WSAGetLastError() );
+
+    SetLastError(0xdeadbeef);
+    ok (bind(fdB, (struct sockaddr*) &address, sizeof(address)), "bind should have failed\n");
+    ret = WSAGetLastError();
+    ok (ret == WSAEADDRINUSE, "expected 10048, received %d\n", ret);
+
+    ret = closesocket(fdA);
+    ok (ret == 0, "closesocket failed unexpectedly: %d\n", ret);
+    ret = closesocket(fdB);
+    ok (ret == 0, "closesocket failed unexpectedly: %d\n", ret);
+}
+
+#define FD_ZERO_ALL() { FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds); }
+#define FD_SET_ALL(s) { FD_SET(s, &readfds); FD_SET(s, &writefds); FD_SET(s, &exceptfds); }
 static void test_select(void)
 {
-    SOCKET fdRead, fdWrite;
+    static char tmp_buf[1024];
+
+    SOCKET fdListen, fdRead, fdWrite;
     fd_set readfds, writefds, exceptfds;
     unsigned int maxfd;
-    int ret;
+    int ret, len;
     char buffer;
     struct timeval select_timeout;
+    struct sockaddr_in address;
     select_thread_params thread_params;
     HANDLE thread_handle;
-    DWORD id;
+    DWORD ticks, id;
 
     fdRead = socket(AF_INET, SOCK_STREAM, 0);
     ok( (fdRead != INVALID_SOCKET), "socket failed unexpectedly: %d\n", WSAGetLastError() );
     fdWrite = socket(AF_INET, SOCK_STREAM, 0);
     ok( (fdWrite != INVALID_SOCKET), "socket failed unexpectedly: %d\n", WSAGetLastError() );
-    FD_ZERO(&readfds);
-    FD_ZERO(&writefds);
-    FD_ZERO(&exceptfds);
-    FD_SET(fdRead, &readfds);
-    FD_SET(fdWrite, &writefds);
-    FD_SET(fdRead, &exceptfds);
-    FD_SET(fdWrite, &exceptfds);
-    select_timeout.tv_sec=0;
-    select_timeout.tv_usec=500;
 
     maxfd = fdRead;
     if (fdWrite > maxfd)
         maxfd = fdWrite;
-       
-    todo_wine {
-    ret = select(maxfd+1, &readfds, &writefds, &exceptfds, &select_timeout);
-    ok ( (ret == 0), "select should not return any socket handles\n");
-    ok ( !FD_ISSET(fdRead, &readfds), "FD should not be set\n");
-    }
-    ok ( !FD_ISSET(fdWrite, &writefds), "FD should not be set\n");
 
-    ok ( !FD_ISSET(fdRead, &exceptfds), "FD should not be set\n");
-    ok ( !FD_ISSET(fdWrite, &exceptfds), "FD should not be set\n");
+    FD_ZERO_ALL();
+    FD_SET_ALL(fdRead);
+    FD_SET_ALL(fdWrite);
+    select_timeout.tv_sec=0;
+    select_timeout.tv_usec=0;
+
+    ticks = GetTickCount();
+    ret = select(maxfd+1, &readfds, &writefds, &exceptfds, &select_timeout);
+    ticks = GetTickCount() - ticks;
+    ok(ret == 0, "select should not return any socket handles\n");
+    ok(ticks < 10, "select was blocking for %u ms, expected < 10 ms\n", ticks);
+    ok(!FD_ISSET(fdRead, &readfds), "FD should not be set\n");
+    ok(!FD_ISSET(fdWrite, &writefds), "FD should not be set\n");
+    ok(!FD_ISSET(fdRead, &exceptfds), "FD should not be set\n");
+    ok(!FD_ISSET(fdWrite, &exceptfds), "FD should not be set\n");
  
-    todo_wine {
+    FD_ZERO_ALL();
+    FD_SET_ALL(fdRead);
+    FD_SET_ALL(fdWrite);
+    select_timeout.tv_sec=0;
+    select_timeout.tv_usec=500;
+
+    ret = select(maxfd+1, &readfds, &writefds, &exceptfds, &select_timeout);
+    ok(ret == 0, "select should not return any socket handles\n");
+    ok(!FD_ISSET(fdRead, &readfds), "FD should not be set\n");
+    ok(!FD_ISSET(fdWrite, &writefds), "FD should not be set\n");
+    ok(!FD_ISSET(fdRead, &exceptfds), "FD should not be set\n");
+    ok(!FD_ISSET(fdWrite, &exceptfds), "FD should not be set\n");
+
     ok ((listen(fdWrite, SOMAXCONN) == SOCKET_ERROR), "listen did not fail\n");
-    }
     ret = closesocket(fdWrite);
     ok ( (ret == 0), "closesocket failed unexpectedly: %d\n", ret);
 
@@ -2399,9 +3674,7 @@ static void test_select(void)
     ok( (ret == -1), "peek at closed socket expected -1 got %d\n", ret);
 
     /* Test selecting invalid handles */
-    FD_ZERO(&readfds);
-    FD_ZERO(&writefds);
-    FD_ZERO(&exceptfds);
+    FD_ZERO_ALL();
 
     SetLastError(0);
     ret = select(maxfd+1, 0, 0, 0, &select_timeout);
@@ -2435,7 +3708,278 @@ static void test_select(void)
     ok ( (ret == SOCKET_ERROR), "expected SOCKET_ERROR, got %i\n", ret);
     ok ( WSAGetLastError() == WSAENOTSOCK, "expected WSAENOTSOCK, got %i\n", WSAGetLastError());
     ok ( !FD_ISSET(fdRead, &exceptfds), "FD should not be set\n");
+
+    ok(!tcp_socketpair(&fdRead, &fdWrite), "creating socket pair failed\n");
+    maxfd = fdRead;
+    if(fdWrite > maxfd) maxfd = fdWrite;
+
+    FD_ZERO(&readfds);
+    FD_SET(fdRead, &readfds);
+    ret = select(fdRead+1, &readfds, NULL, NULL, &select_timeout);
+    ok(!ret, "select returned %d\n", ret);
+
+    FD_ZERO(&writefds);
+    FD_SET(fdWrite, &writefds);
+    ret = select(fdWrite+1, NULL, &writefds, NULL, &select_timeout);
+    ok(ret == 1, "select returned %d\n", ret);
+    ok(FD_ISSET(fdWrite, &writefds), "fdWrite socket is not in the set\n");
+
+    /* tests for overlapping fd_set pointers */
+    FD_ZERO(&readfds);
+    FD_SET(fdWrite, &readfds);
+    ret = select(fdWrite+1, &readfds, &readfds, NULL, &select_timeout);
+    ok(ret == 1, "select returned %d\n", ret);
+    ok(FD_ISSET(fdWrite, &readfds), "fdWrite socket is not in the set\n");
+
+    FD_ZERO(&readfds);
+    FD_SET(fdWrite, &readfds);
+    FD_SET(fdRead, &readfds);
+    ret = select(maxfd+1, &readfds, &readfds, NULL, &select_timeout);
+    ok(ret == 2, "select returned %d\n", ret);
+    ok(FD_ISSET(fdWrite, &readfds), "fdWrite socket is not in the set\n");
+    ok(FD_ISSET(fdRead, &readfds), "fdRead socket is not in the set\n");
+
+    ok(send(fdWrite, "test", 4, 0) == 4, "failed to send data\n");
+    FD_ZERO(&readfds);
+    FD_SET(fdRead, &readfds);
+    ret = select(fdRead+1, &readfds, NULL, NULL, &select_timeout);
+    ok(ret == 1, "select returned %d\n", ret);
+    ok(FD_ISSET(fdRead, &readfds), "fdRead socket is not in the set\n");
+
+    FD_ZERO(&readfds);
+    FD_SET(fdWrite, &readfds);
+    FD_SET(fdRead, &readfds);
+    ret = select(maxfd+1, &readfds, &readfds, NULL, &select_timeout);
+    ok(ret == 2, "select returned %d\n", ret);
+    ok(FD_ISSET(fdWrite, &readfds), "fdWrite socket is not in the set\n");
+    ok(FD_ISSET(fdRead, &readfds), "fdRead socket is not in the set\n");
+
+#if ROSTESTS_233_IS_FIXED
+    while(1) {
+        FD_ZERO(&writefds);
+        FD_SET(fdWrite, &writefds);
+        ret = select(fdWrite+1, NULL, &writefds, NULL, &select_timeout);
+        if(!ret) break;
+        ok(send(fdWrite, tmp_buf, sizeof(tmp_buf), 0) > 0, "failed to send data\n");
+    }
+#endif /* ROSTESTS_233_IS_FIXED */
+
+    FD_ZERO(&readfds);
+    FD_SET(fdWrite, &readfds);
+    FD_SET(fdRead, &readfds);
+    ret = select(maxfd+1, &readfds, &readfds, NULL, &select_timeout);
+    ok(ret == 1, "select returned %d\n", ret);
+    ok(!FD_ISSET(fdWrite, &readfds), "fdWrite socket is in the set\n");
+    ok(FD_ISSET(fdRead, &readfds), "fdRead socket is not in the set\n");
+
+    ok(send(fdRead, "test", 4, 0) == 4, "failed to send data\n");
+    Sleep(100);
+    FD_ZERO(&readfds);
+    FD_SET(fdWrite, &readfds);
+    FD_SET(fdRead, &readfds);
+    ret = select(maxfd+1, &readfds, &readfds, NULL, &select_timeout);
+    ok(ret == 2, "select returned %d\n", ret);
+    ok(FD_ISSET(fdWrite, &readfds), "fdWrite socket is not in the set\n");
+    ok(FD_ISSET(fdRead, &readfds), "fdRead socket is not in the set\n");
+
+    closesocket(fdRead);
+    closesocket(fdWrite);
+
+    /* select() works in 3 distinct states:
+     * - to check if a connection attempt ended with success or error;
+     * - to check if a pending connection is waiting for acceptance;
+     * - to check for data to read, availability for write and OOB data
+     *
+     * The tests below ensure that all conditions are tested.
+     */
+    memset(&address, 0, sizeof(address));
+    address.sin_addr.s_addr = inet_addr("127.0.0.1");
+    address.sin_family = AF_INET;
+    len = sizeof(address);
+    fdListen = setup_server_socket(&address, &len);
+    select_timeout.tv_sec = 1;
+    select_timeout.tv_usec = 250000;
+
+    /* When no events are pending select returns 0 with no error */
+    FD_ZERO_ALL();
+    FD_SET_ALL(fdListen);
+    ret = select(0, &readfds, &writefds, &exceptfds, &select_timeout);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+
+    /* When a socket is attempting to connect the listening socket receives the read descriptor */
+    fdWrite = setup_connector_socket(&address, len, TRUE);
+    FD_ZERO_ALL();
+    FD_SET_ALL(fdListen);
+    ret = select(0, &readfds, &writefds, &exceptfds, &select_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(FD_ISSET(fdListen, &readfds), "fdListen socket is not in the set\n");
+    len = sizeof(address);
+    fdRead = accept(fdListen, (struct sockaddr*) &address, &len);
+    ok(fdRead != INVALID_SOCKET, "expected a valid socket\n");
+
+    /* The connector is signaled through the write descriptor */
+    FD_ZERO_ALL();
+    FD_SET_ALL(fdListen);
+    FD_SET_ALL(fdRead);
+    FD_SET_ALL(fdWrite);
+    ret = select(0, &readfds, &writefds, &exceptfds, &select_timeout);
+    ok(ret == 2, "expected 2, got %d\n", ret);
+    ok(FD_ISSET(fdWrite, &writefds), "fdWrite socket is not in the set\n");
+    ok(FD_ISSET(fdRead, &writefds), "fdRead socket is not in the set\n");
+    len = sizeof(id);
+    id = 0xdeadbeef;
+    ret = getsockopt(fdWrite, SOL_SOCKET, SO_ERROR, (char*)&id, &len);
+    ok(!ret, "getsockopt failed with %d\n", WSAGetLastError());
+    ok(id == 0, "expected 0, got %d\n", id);
+
+    /* When data is received the receiver gets the read descriptor */
+    ret = send(fdWrite, "1234", 4, 0);
+    ok(ret == 4, "expected 4, got %d\n", ret);
+    FD_ZERO_ALL();
+    FD_SET_ALL(fdListen);
+    FD_SET(fdRead, &readfds);
+    FD_SET(fdRead, &exceptfds);
+    ret = select(0, &readfds, &writefds, &exceptfds, &select_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(FD_ISSET(fdRead, &readfds), "fdRead socket is not in the set\n");
+    ret = recv(fdRead, tmp_buf, sizeof(tmp_buf), 0);
+    ok(ret == 4, "expected 4, got %d\n", ret);
+    ok(!strcmp(tmp_buf, "1234"), "data received differs from sent\n");
+
+    /* When OOB data is received the socket is set in the except descriptor */
+    ret = send(fdWrite, "A", 1, MSG_OOB);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    FD_ZERO_ALL();
+    FD_SET_ALL(fdListen);
+    FD_SET(fdRead, &readfds);
+    FD_SET(fdRead, &exceptfds);
+    ret = select(0, &readfds, &writefds, &exceptfds, &select_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(FD_ISSET(fdRead, &exceptfds), "fdRead socket is not in the set\n");
+    tmp_buf[0] = 0xAF;
+    ret = recv(fdRead, tmp_buf, sizeof(tmp_buf), MSG_OOB);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(tmp_buf[0] == 'A', "expected 'A', got 0x%02X\n", tmp_buf[0]);
+
+    /* If the socket is OOBINLINED it will not receive the OOB in except fds */
+    ret = 1;
+    ret = setsockopt(fdRead, SOL_SOCKET, SO_OOBINLINE, (char*) &ret, sizeof(ret));
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    ret = send(fdWrite, "A", 1, MSG_OOB);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    FD_ZERO_ALL();
+    FD_SET_ALL(fdListen);
+    FD_SET(fdRead, &readfds);
+    FD_SET(fdRead, &exceptfds);
+    ret = select(0, &readfds, &writefds, &exceptfds, &select_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(FD_ISSET(fdRead, &readfds), "fdRead socket is not in the set\n");
+    tmp_buf[0] = 0xAF;
+    SetLastError(0xdeadbeef);
+    ret = recv(fdRead, tmp_buf, sizeof(tmp_buf), MSG_OOB);
+    if (ret == SOCKET_ERROR) /* can't recv with MSG_OOB if OOBINLINED */
+    {
+        ok(GetLastError() == WSAEINVAL, "expected 10022, got %d\n", GetLastError());
+        ret = recv(fdRead, tmp_buf, sizeof(tmp_buf), 0);
+        ok(ret == 1, "expected 1, got %d\n", ret);
+        ok(tmp_buf[0] == 'A', "expected 'A', got 0x%02X\n", tmp_buf[0]);
+    }
+    else ok(broken(ret == 1) /* <= NT4 */, "expected error, got 1\n");
+
+    /* When the connection is closed the socket is set in the read descriptor */
+    ret = closesocket(fdRead);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    FD_ZERO_ALL();
+    FD_SET_ALL(fdListen);
+    FD_SET(fdWrite, &readfds);
+    ret = select(0, &readfds, &writefds, &exceptfds, &select_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(FD_ISSET(fdWrite, &readfds), "fdWrite socket is not in the set\n");
+    ret = recv(fdWrite, tmp_buf, sizeof(tmp_buf), 0);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+
+    /* When a connection is attempted to a non-listening socket it will get to the except descriptor */
+    ret = closesocket(fdWrite);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    ret = closesocket(fdListen);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    len = sizeof(address);
+    fdWrite = setup_connector_socket(&address, len, TRUE);
+    FD_ZERO_ALL();
+    FD_SET(fdWrite, &writefds);
+    FD_SET(fdWrite, &exceptfds);
+    select_timeout.tv_sec = 2; /* requires more time to realize it will not connect */
+    ret = select(0, &readfds, &writefds, &exceptfds, &select_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    len = sizeof(id);
+    id = 0xdeadbeef;
+    ret = getsockopt(fdWrite, SOL_SOCKET, SO_ERROR, (char*)&id, &len);
+    ok(!ret, "getsockopt failed with %d\n", WSAGetLastError());
+    ok(id == WSAECONNREFUSED, "expected 10061, got %d\n", id);
+    ok(FD_ISSET(fdWrite, &exceptfds), "fdWrite socket is not in the set\n");
+    ok(select_timeout.tv_usec == 250000, "select timeout should not have changed\n");
+    closesocket(fdWrite);
+
+    /* Try select() on a closed socket after connection */
+    ok(!tcp_socketpair(&fdRead, &fdWrite), "creating socket pair failed\n");
+    closesocket(fdRead);
+    FD_ZERO_ALL();
+    FD_SET_ALL(fdWrite);
+    FD_SET_ALL(fdRead);
+    SetLastError(0xdeadbeef);
+    ret = select(0, &readfds, NULL, &exceptfds, &select_timeout);
+    ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+todo_wine
+    ok(GetLastError() == WSAENOTSOCK, "expected 10038, got %d\n", GetLastError());
+    /* descriptor sets are unchanged */
+    ok(readfds.fd_count == 2, "expected 2, got %d\n", readfds.fd_count);
+    ok(exceptfds.fd_count == 2, "expected 2, got %d\n", exceptfds.fd_count);
+    closesocket(fdWrite);
+
+#if ROSTESTS_233_IS_FIXED
+
+    /* Close the socket currently being selected in a thread - bug 38399 */
+    ok(!tcp_socketpair(&fdRead, &fdWrite), "creating socket pair failed\n");
+    thread_handle = CreateThread(NULL, 0, SelectCloseThread, &fdWrite, 0, &id);
+    ok(thread_handle != NULL, "CreateThread failed unexpectedly: %d\n", GetLastError());
+    FD_ZERO_ALL();
+    FD_SET_ALL(fdWrite);
+    ret = select(0, &readfds, NULL, &exceptfds, &select_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(FD_ISSET(fdWrite, &readfds), "fdWrite socket is not in the set\n");
+    WaitForSingleObject (thread_handle, 1000);
+    closesocket(fdRead);
+    /* test again with only the except descriptor */
+    ok(!tcp_socketpair(&fdRead, &fdWrite), "creating socket pair failed\n");
+    thread_handle = CreateThread(NULL, 0, SelectCloseThread, &fdWrite, 0, &id);
+    ok(thread_handle != NULL, "CreateThread failed unexpectedly: %d\n", GetLastError());
+    FD_ZERO_ALL();
+    FD_SET(fdWrite, &exceptfds);
+    SetLastError(0xdeadbeef);
+    ret = select(0, NULL, NULL, &exceptfds, &select_timeout);
+todo_wine
+    ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+todo_wine
+    ok(GetLastError() == WSAENOTSOCK, "expected 10038, got %d\n", GetLastError());
+    WaitForSingleObject (thread_handle, 1000);
+    closesocket(fdRead);
+
+#endif /* ROSTESTS_233_IS_FIXED */
+
+    /* test UDP behavior of unbound sockets */
+    select_timeout.tv_sec = 0;
+    select_timeout.tv_usec = 250000;
+    fdWrite = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    ok(fdWrite != INVALID_SOCKET, "socket call failed\n");
+    FD_ZERO_ALL();
+    FD_SET_ALL(fdWrite);
+    ret = select(0, &readfds, &writefds, &exceptfds, &select_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(FD_ISSET(fdWrite, &writefds), "fdWrite socket is not in the set\n");
+    closesocket(fdWrite);
 }
+#undef FD_SET_ALL
+#undef FD_ZERO_ALL
 
 static DWORD WINAPI AcceptKillThread(void *param)
 {
@@ -2455,59 +3999,108 @@ static DWORD WINAPI AcceptKillThread(void *param)
 
 static int CALLBACK AlwaysDeferConditionFunc(LPWSABUF lpCallerId, LPWSABUF lpCallerData, LPQOS pQos,
                                              LPQOS lpGQOS, LPWSABUF lpCalleeId, LPWSABUF lpCalleeData,
-                                             GROUP FAR * g, DWORD_PTR dwCallbackData)
+                                             GROUP *g, DWORD_PTR dwCallbackData)
 {
     return CF_DEFER;
 }
 
-static void test_accept(void)
+static SOCKET setup_server_socket(struct sockaddr_in *addr, int *len)
 {
-    int ret;
-    SOCKET server_socket = INVALID_SOCKET, accepted = INVALID_SOCKET, connector = INVALID_SOCKET;
-    struct sockaddr_in address;
-    int socklen;
-    select_thread_params thread_params;
-    HANDLE thread_handle = NULL;
-    DWORD id;
+    int ret, val;
+    SOCKET server_socket;
 
     server_socket = socket(AF_INET, SOCK_STREAM, 0);
     if (server_socket == INVALID_SOCKET)
     {
         trace("error creating server socket: %d\n", WSAGetLastError());
-        goto done;
+        return INVALID_SOCKET;
     }
 
-    memset(&address, 0, sizeof(address));
-    address.sin_addr.s_addr = inet_addr("127.0.0.1");
-    address.sin_family = AF_INET;
-    ret = bind(server_socket, (struct sockaddr*) &address, sizeof(address));
-    if (ret != 0)
+    val = 1;
+    ret = setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
+    if (ret)
+    {
+        trace("error setting SO_REUSEADDR: %d\n", WSAGetLastError());
+        closesocket(server_socket);
+        return INVALID_SOCKET;
+    }
+
+    ret = bind(server_socket, (struct sockaddr *)addr, *len);
+    if (ret)
     {
         trace("error binding server socket: %d\n", WSAGetLastError());
-        goto done;
     }
 
-    socklen = sizeof(address);
-    ret = getsockname(server_socket, (struct sockaddr*)&address, &socklen);
-    if (ret != 0) {
-        skip("failed to lookup bind address, error %d\n", WSAGetLastError());
-        goto done;
+    ret = getsockname(server_socket, (struct sockaddr *)addr, len);
+    if (ret)
+    {
+        skip("failed to lookup bind address: %d\n", WSAGetLastError());
+        closesocket(server_socket);
+        return INVALID_SOCKET;
     }
 
     ret = listen(server_socket, 5);
-    if (ret != 0)
+    if (ret)
     {
         trace("error making server socket listen: %d\n", WSAGetLastError());
-        goto done;
+        closesocket(server_socket);
+        return INVALID_SOCKET;
     }
 
-    trace("Blocking accept next\n");
+    return server_socket;
+}
+
+static SOCKET setup_connector_socket(struct sockaddr_in *addr, int len, BOOL nonblock)
+{
+    int ret;
+    SOCKET connector;
 
     connector = socket(AF_INET, SOCK_STREAM, 0);
-    ok(connector != INVALID_SOCKET, "Failed to create connector socket, error %d\n", WSAGetLastError());
+    ok(connector != INVALID_SOCKET, "failed to create connector socket %d\n", WSAGetLastError());
+
+    if (nonblock)
+        set_blocking(connector, !nonblock);
+
+    ret = connect(connector, (struct sockaddr *)addr, len);
+    if (!nonblock)
+        ok(!ret, "connecting to accepting socket failed %d\n", WSAGetLastError());
+    else if (ret == SOCKET_ERROR)
+    {
+        DWORD error = WSAGetLastError();
+        ok(error == WSAEWOULDBLOCK || error == WSAEINPROGRESS,
+           "expected 10035 or 10036, got %d\n", error);
+    }
+
+    return connector;
+}
+
+static void test_accept(void)
+{
+    int ret;
+    SOCKET server_socket, accepted = INVALID_SOCKET, connector;
+    struct sockaddr_in address;
+    SOCKADDR_STORAGE ss;
+    int socklen;
+    select_thread_params thread_params;
+    HANDLE thread_handle = NULL;
+    DWORD id;
 
-    ret = connect(connector, (struct sockaddr*)&address, sizeof(address));
-    ok(ret == 0, "connecting to accepting socket failed, error %d\n", WSAGetLastError());
+    memset(&address, 0, sizeof(address));
+    address.sin_addr.s_addr = inet_addr("127.0.0.1");
+    address.sin_family = AF_INET;
+
+    socklen = sizeof(address);
+    server_socket = setup_server_socket(&address, &socklen);
+    if (server_socket == INVALID_SOCKET)
+    {
+        trace("error creating server socket: %d\n", WSAGetLastError());
+        return;
+    }
+
+    connector = setup_connector_socket(&address, socklen, FALSE);
+    if (connector == INVALID_SOCKET) goto done;
+
+    trace("Blocking accept next\n");
 
     accepted = WSAAccept(server_socket, NULL, NULL, AlwaysDeferConditionFunc, 0);
     ok(accepted == INVALID_SOCKET && WSAGetLastError() == WSATRY_AGAIN, "Failed to defer connection, %d\n", WSAGetLastError());
@@ -2544,6 +4137,80 @@ static void test_accept(void)
     ok(thread_params.ReadKilled || broken(!thread_params.ReadKilled) /* Win98/ME, after accept */,
        "closesocket did not wakeup accept\n");
 
+    closesocket(accepted);
+    closesocket(connector);
+    accepted = connector = INVALID_SOCKET;
+
+    socklen = sizeof(address);
+    server_socket = setup_server_socket(&address, &socklen);
+    if (server_socket == INVALID_SOCKET) goto done;
+
+    connector = setup_connector_socket(&address, socklen, FALSE);
+    if (connector == INVALID_SOCKET) goto done;
+
+    socklen = 0;
+    accepted = WSAAccept(server_socket, (struct sockaddr *)&ss, &socklen, NULL, 0);
+    ok(accepted == INVALID_SOCKET && WSAGetLastError() == WSAEFAULT, "got %d\n", WSAGetLastError());
+    ok(!socklen, "got %d\n", socklen);
+    closesocket(connector);
+    connector = INVALID_SOCKET;
+
+    socklen = sizeof(address);
+    connector = setup_connector_socket(&address, socklen, FALSE);
+    if (connector == INVALID_SOCKET) goto done;
+
+    accepted = WSAAccept(server_socket, NULL, NULL, NULL, 0);
+    ok(accepted != INVALID_SOCKET, "Failed to accept connection, %d\n", WSAGetLastError());
+    closesocket(accepted);
+    closesocket(connector);
+    accepted = connector = INVALID_SOCKET;
+
+    socklen = sizeof(address);
+    connector = setup_connector_socket(&address, socklen, FALSE);
+    if (connector == INVALID_SOCKET) goto done;
+
+    socklen = sizeof(ss);
+    memset(&ss, 0, sizeof(ss));
+    accepted = WSAAccept(server_socket, (struct sockaddr *)&ss, &socklen, NULL, 0);
+    ok(accepted != INVALID_SOCKET, "Failed to accept connection, %d\n", WSAGetLastError());
+    ok(socklen != sizeof(ss), "unexpected length\n");
+    ok(ss.ss_family, "family not set\n");
+    closesocket(accepted);
+    closesocket(connector);
+    accepted = connector = INVALID_SOCKET;
+
+    socklen = sizeof(address);
+    connector = setup_connector_socket(&address, socklen, FALSE);
+    if (connector == INVALID_SOCKET) goto done;
+
+    socklen = 0;
+    accepted = accept(server_socket, (struct sockaddr *)&ss, &socklen);
+    ok(accepted == INVALID_SOCKET && WSAGetLastError() == WSAEFAULT, "got %d\n", WSAGetLastError());
+    ok(!socklen, "got %d\n", socklen);
+    closesocket(connector);
+    accepted = connector = INVALID_SOCKET;
+
+    socklen = sizeof(address);
+    connector = setup_connector_socket(&address, socklen, FALSE);
+    if (connector == INVALID_SOCKET) goto done;
+
+    accepted = accept(server_socket, NULL, NULL);
+    ok(accepted != INVALID_SOCKET, "Failed to accept connection, %d\n", WSAGetLastError());
+    closesocket(accepted);
+    closesocket(connector);
+    accepted = connector = INVALID_SOCKET;
+
+    socklen = sizeof(address);
+    connector = setup_connector_socket(&address, socklen, FALSE);
+    if (connector == INVALID_SOCKET) goto done;
+
+    socklen = sizeof(ss);
+    memset(&ss, 0, sizeof(ss));
+    accepted = accept(server_socket, (struct sockaddr *)&ss, &socklen);
+    ok(accepted != INVALID_SOCKET, "Failed to accept connection, %d\n", WSAGetLastError());
+    ok(socklen != sizeof(ss), "unexpected length\n");
+    ok(ss.ss_family, "family not set\n");
+
 done:
     if (accepted != INVALID_SOCKET)
         closesocket(accepted);
@@ -2683,6 +4350,7 @@ static void test_getsockname(void)
     int sa_get_len = sa_set_len;
     static const unsigned char null_padding[] = {0,0,0,0,0,0,0,0};
     int ret;
+    struct hostent *h;
 
     if(WSAStartup(MAKEWORD(2,0), &wsa)){
         trace("Winsock failed: %d. Aborting test\n", WSAGetLastError());
@@ -2701,7 +4369,7 @@ static void test_getsockname(void)
         return;
     }
 
-    memcpy(&sa_get, &sa_set, sizeof(sa_set));
+    sa_get = sa_set;
     if (getsockname(sock, (struct sockaddr*) &sa_get, &sa_get_len) == 0)
         ok(0, "getsockname on unbound socket should fail\n");
     else {
@@ -2729,7 +4397,39 @@ static void test_getsockname(void)
     ok(ret == 0 || broken(ret != 0), /* NT4 */
             "getsockname did not zero the sockaddr_in structure\n");
 
-    closesocket(sock);
+    closesocket(sock);
+
+    h = gethostbyname("");
+    if (h && h->h_length == 4) /* this test is only meaningful in IPv4 */
+    {
+        int i;
+        for (i = 0; h->h_addr_list[i]; i++)
+        {
+            char ipstr[32];
+            struct in_addr ip;
+            ip.s_addr = *(ULONG *) h->h_addr_list[i];
+
+            sock = socket(AF_INET, SOCK_DGRAM, 0);
+            ok(sock != INVALID_SOCKET, "socket failed with %d\n", GetLastError());
+
+            memset(&sa_set, 0, sizeof(sa_set));
+            sa_set.sin_family = AF_INET;
+            sa_set.sin_addr.s_addr = ip.s_addr;
+            /* The same address we bind must be the same address we get */
+            ret = bind(sock, (struct sockaddr*)&sa_set, sizeof(sa_set));
+            ok(ret == 0, "bind failed with %d\n", GetLastError());
+            sa_get_len = sizeof(sa_get);
+            ret = getsockname(sock, (struct sockaddr*)&sa_get, &sa_get_len);
+            ok(ret == 0, "getsockname failed with %d\n", GetLastError());
+            strcpy(ipstr, inet_ntoa(sa_get.sin_addr));
+            trace("testing bind on interface %s\n", ipstr);
+            ok(sa_get.sin_addr.s_addr == sa_set.sin_addr.s_addr,
+               "address does not match: %s != %s\n", ipstr, inet_ntoa(sa_set.sin_addr));
+
+            closesocket(sock);
+        }
+    }
+
     WSACleanup();
 }
 
@@ -2763,22 +4463,22 @@ static void test_dns(void)
     addr.mem = h + 1;
     if(h->h_addr_list == addr.mem) /* <= W2K */
     {
-        skip("Skipping hostent tests since this OS is unsupported\n");
+        win_skip("Skipping hostent tests since this OS is unsupported\n");
         return;
     }
 
-    todo_wine ok(h->h_aliases == addr.mem,
+    ok(h->h_aliases == addr.mem,
        "hostent->h_aliases should be in %p, it is in %p\n", addr.mem, h->h_aliases);
 
     for(ptr = h->h_aliases, acount = 1; *ptr; ptr++) acount++;
     addr.chr += sizeof(*ptr) * acount;
-    todo_wine ok(h->h_addr_list == addr.mem,
+    ok(h->h_addr_list == addr.mem,
        "hostent->h_addr_list should be in %p, it is in %p\n", addr.mem, h->h_addr_list);
 
     for(ptr = h->h_addr_list, acount = 1; *ptr; ptr++) acount++;
 
     addr.chr += sizeof(*ptr) * acount;
-    todo_wine ok(h->h_addr_list[0] == addr.mem,
+    ok(h->h_addr_list[0] == addr.mem,
        "hostent->h_addr_list[0] should be in %p, it is in %p\n", addr.mem, h->h_addr_list[0]);
 }
 
@@ -2789,6 +4489,102 @@ static void test_dns(void)
 int WINAPI gethostname(char *name, int namelen);
 #endif
 
+static void test_gethostbyname(void)
+{
+    struct hostent *he;
+    struct in_addr **addr_list;
+    char name[256], first_ip[16];
+    int ret, i, count;
+    PMIB_IPFORWARDTABLE routes = NULL;
+    PIP_ADAPTER_INFO adapters = NULL, k;
+    DWORD adap_size = 0, route_size = 0;
+    BOOL found_default = FALSE;
+    BOOL local_ip = FALSE;
+
+    ret = gethostname(name, sizeof(name));
+    ok(ret == 0, "gethostname() call failed: %d\n", WSAGetLastError());
+
+    he = gethostbyname(name);
+    ok(he != NULL, "gethostbyname(\"%s\") failed: %d\n", name, WSAGetLastError());
+#ifdef __REACTOS__ /* ROSTESTS-233 */
+    if (he != NULL)
+    {
+#endif
+        addr_list = (struct in_addr **)he->h_addr_list;
+        strcpy(first_ip, inet_ntoa(*addr_list[0]));
+
+        trace("List of local IPs:\n");
+        for(count = 0; addr_list[count] != NULL; count++)
+        {
+            char *ip = inet_ntoa(*addr_list[count]);
+            if (!strcmp(ip, "127.0.0.1"))
+                local_ip = TRUE;
+            trace("%s\n", ip);
+        }
+#ifdef __REACTOS__ /* ROSTESTS-233 */
+    }
+#endif
+
+    if (local_ip)
+    {
+        ok (count == 1, "expected 127.0.0.1 to be the only IP returned\n");
+        skip("Only the loopback address is present, skipping tests\n");
+        return;
+    }
+
+    if (!pGetAdaptersInfo || !pGetIpForwardTable)
+    {
+        win_skip("GetAdaptersInfo and/or GetIpForwardTable not found, skipping tests\n");
+        return;
+    }
+
+    ret = pGetAdaptersInfo(NULL, &adap_size);
+    ok (ret  == ERROR_BUFFER_OVERFLOW, "GetAdaptersInfo failed with a different error: %d\n", ret);
+    ret = pGetIpForwardTable(NULL, &route_size, FALSE);
+    ok (ret == ERROR_INSUFFICIENT_BUFFER, "GetIpForwardTable failed with a different error: %d\n", ret);
+
+    adapters = HeapAlloc(GetProcessHeap(), 0, adap_size);
+    routes = HeapAlloc(GetProcessHeap(), 0, route_size);
+
+    ret = pGetAdaptersInfo(adapters, &adap_size);
+    ok (ret  == NO_ERROR, "GetAdaptersInfo failed, error: %d\n", ret);
+    ret = pGetIpForwardTable(routes, &route_size, FALSE);
+    ok (ret == NO_ERROR, "GetIpForwardTable failed, error: %d\n", ret);
+
+    /* This test only has meaning if there is more than one IP configured */
+    if (adapters->Next == NULL && count == 1)
+    {
+        skip("Only one IP is present, skipping tests\n");
+        goto cleanup;
+    }
+
+    for (i = 0; !found_default && i < routes->dwNumEntries; i++)
+    {
+        /* default route (ip 0.0.0.0) ? */
+        if (routes->table[i].dwForwardDest) continue;
+
+        for (k = adapters; k != NULL; k = k->Next)
+        {
+            char *ip;
+
+            if (k->Index != routes->table[i].dwForwardIfIndex) continue;
+
+            /* the first IP returned from gethostbyname must be a default route */
+            ip = k->IpAddressList.IpAddress.String;
+            if (!strcmp(first_ip, ip))
+            {
+                found_default = TRUE;
+                break;
+            }
+        }
+    }
+    ok (found_default, "failed to find the first IP from gethostbyname!\n");
+
+cleanup:
+    HeapFree(GetProcessHeap(), 0, adapters);
+    HeapFree(GetProcessHeap(), 0, routes);
+}
+
 static void test_gethostbyname_hack(void)
 {
     struct hostent *he;
@@ -2822,7 +4618,6 @@ static void test_gethostbyname_hack(void)
         return;
     }
 
-    he = NULL;
     he = gethostbyname(name);
     ok(he != NULL, "gethostbyname(\"%s\") failed: %d\n", name, h_errno);
     if(he)
@@ -2847,6 +4642,39 @@ static void test_gethostbyname_hack(void)
      * resolve nonexistent host names to addresses of the ISP's spam pages. */
 }
 
+static void test_gethostname(void)
+{
+    struct hostent *he;
+    char name[256];
+    int ret, len;
+
+    WSASetLastError(0xdeadbeef);
+    ret = gethostname(NULL, 256);
+    ok(ret == -1, "gethostname() returned %d\n", ret);
+    ok(WSAGetLastError() == WSAEFAULT, "gethostname with null buffer "
+            "failed with %d, expected %d\n", WSAGetLastError(), WSAEFAULT);
+
+    ret = gethostname(name, sizeof(name));
+    ok(ret == 0, "gethostname() call failed: %d\n", WSAGetLastError());
+    he = gethostbyname(name);
+    ok(he != NULL, "gethostbyname(\"%s\") failed: %d\n", name, WSAGetLastError());
+
+    len = strlen(name);
+    WSASetLastError(0xdeadbeef);
+    strcpy(name, "deadbeef");
+    ret = gethostname(name, len);
+    ok(ret == -1, "gethostname() returned %d\n", ret);
+    ok(!strcmp(name, "deadbeef"), "name changed unexpected!\n");
+    ok(WSAGetLastError() == WSAEFAULT, "gethostname with insufficient length "
+            "failed with %d, expected %d\n", WSAGetLastError(), WSAEFAULT);
+
+    len++;
+    ret = gethostname(name, len);
+    ok(ret == 0, "gethostname() call failed: %d\n", WSAGetLastError());
+    he = gethostbyname(name);
+    ok(he != NULL, "gethostbyname(\"%s\") failed: %d\n", name, WSAGetLastError());
+}
+
 static void test_inet_addr(void)
 {
     u_long addr;
@@ -2986,14 +4814,160 @@ static void test_addr_to_print(void)
     pdst = pInetNtop(AF_INET6, (void*)&in6.s6_addr, dst6, 18);
     ok(pdst != NULL, "The pointer should be returned (%p)\n", pdst);
 }
+static void test_inet_pton(void)
+{
+    struct TEST_DATA
+    {
+        int family, ret;
+        DWORD err;
+        const char *printable, *collapsed, *raw_data;
+    } tests[] = {
+        {AF_UNSPEC, -1, WSAEFAULT,    /* Test 0 */
+        NULL, NULL, NULL},
+        {AF_INET, -1, WSAEFAULT,
+        NULL, NULL, NULL},
+        {AF_INET6, -1, WSAEFAULT,
+        NULL, NULL, NULL},
+        {AF_UNSPEC, -1, WSAEAFNOSUPPORT,
+        "127.0.0.1", NULL, NULL},
+        {AF_INET, 1, 0,
+        "127.0.0.1", "127.0.0.1",
+        "\x7f\x00\x00\x01"},
+        {AF_INET6, 0, 0,
+        "127.0.0.1", "127.0.0.1", NULL},
+        {AF_INET, 0, 0,
+        "::1/128", NULL, NULL},
+        {AF_INET6, 0, 0,
+        "::1/128", NULL, NULL},
+        {AF_UNSPEC, -1, WSAEAFNOSUPPORT,
+        "broken", NULL, NULL},
+        {AF_INET, 0, 0,
+        "broken", NULL, NULL},
+        {AF_INET6, 0, 0,              /* Test 10 */
+        "broken", NULL, NULL},
+        {AF_UNSPEC, -1, WSAEAFNOSUPPORT,
+        "177.32.45.20", NULL, NULL},
+        {AF_INET, 1, 0,
+        "177.32.45.20", "177.32.45.20",
+        "\xb1\x20\x2d\x14"},
+        {AF_INET6, 0, 0,
+        "177.32.45.20", NULL, NULL},
+        {AF_INET, 0, 0,
+        "2607:f0d0:1002:51::4", NULL, NULL},
+        {AF_INET6, 1, 0,
+        "2607:f0d0:1002:51::4", "2607:f0d0:1002:51::4",
+        "\x26\x07\xf0\xd0\x10\x02\x00\x51\x00\x00\x00\x00\x00\x00\x00\x04"},
+        {AF_INET, 0, 0,
+        "::177.32.45.20", NULL, NULL},
+        {AF_INET6, 1, 0,
+        "::177.32.45.20", "::177.32.45.20",
+        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb1\x20\x2d\x14"},
+        {AF_INET, 0, 0,
+        "fe80::0202:b3ff:fe1e:8329", NULL, NULL},
+        {AF_INET6, 1, 0,
+        "fe80::0202:b3ff:fe1e:8329", "fe80::202:b3ff:fe1e:8329",
+        "\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x02\xb3\xff\xfe\x1e\x83\x29"},
+        {AF_INET6, 1, 0,              /* Test 20 */
+        "fe80::202:b3ff:fe1e:8329", "fe80::202:b3ff:fe1e:8329",
+        "\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x02\xb3\xff\xfe\x1e\x83\x29"},
+        {AF_INET, 0, 0,
+        "a", NULL, NULL},
+        {AF_INET, 0, 0,
+        "a.b", NULL, NULL},
+        {AF_INET, 0, 0,
+        "a.b.c",  NULL, NULL},
+        {AF_INET, 0, 0,
+        "a.b.c.d", NULL, NULL},
+        {AF_INET6, 1, 0,
+        "2001:cdba:0000:0000:0000:0000:3257:9652", "2001:cdba::3257:9652",
+        "\x20\x01\xcd\xba\x00\x00\x00\x00\x00\x00\x00\x00\x32\x57\x96\x52"},
+        {AF_INET6, 1, 0,
+        "2001:cdba::3257:9652", "2001:cdba::3257:9652",
+        "\x20\x01\xcd\xba\x00\x00\x00\x00\x00\x00\x00\x00\x32\x57\x96\x52"},
+        {AF_INET6, 1, 0,
+        "2001:cdba:0:0:0:0:3257:9652", "2001:cdba::3257:9652",
+        "\x20\x01\xcd\xba\x00\x00\x00\x00\x00\x00\x00\x00\x32\x57\x96\x52"}
+    };
+    int i, ret;
+    DWORD err;
+    char buffer[64],str[64];
+    WCHAR printableW[64], collapsedW[64];
+    const char *ptr;
+    const WCHAR *ptrW;
+
+    /* InetNtop and InetPton became available in Vista and Win2008 */
+    if (!pInetNtop || !pInetNtopW || !pInetPtonA || !pInetPtonW)
+    {
+        win_skip("InetNtop and/or InetPton not present, not executing tests\n");
+        return;
+    }
+
+    for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
+    {
+        WSASetLastError(0xdeadbeef);
+        ret = pInetPtonA(tests[i].family, tests[i].printable, buffer);
+        ok (ret == tests[i].ret, "Test [%d]: Expected %d, got %d\n", i, tests[i].ret, ret);
+        if (tests[i].ret == -1)
+        {
+            err = WSAGetLastError();
+            ok (tests[i].err == err, "Test [%d]: Expected 0x%x, got 0x%x\n", i, tests[i].err, err);
+        }
+        if (tests[i].ret != 1) continue;
+        ok (memcmp(buffer, tests[i].raw_data,
+            tests[i].family == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr)) == 0,
+            "Test [%d]: Expected binary data differs\n", i);
+
+        /* Test the result from Pton with Ntop */
+        strcpy (str, "deadbeef");
+        ptr = pInetNtop(tests[i].family, buffer, str, sizeof(str));
+        ok (ptr != NULL, "Test [%d]: Failed with NULL\n", i);
+        ok (ptr == str, "Test [%d]: Pointers differ (%p != %p)\n", i, ptr, str);
+        if (!ptr) continue;
+        ok (strcmp(ptr, tests[i].collapsed) == 0, "Test [%d]: Expected '%s', got '%s'\n",
+            i, tests[i].collapsed, ptr);
+    }
+
+    for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
+    {
+        if (tests[i].printable)
+            MultiByteToWideChar(CP_ACP, 0, tests[i].printable, -1, printableW,
+                                sizeof(printableW) / sizeof(printableW[0]));
+        WSASetLastError(0xdeadbeef);
+        ret = pInetPtonW(tests[i].family, tests[i].printable ? printableW : NULL, buffer);
+        ok(ret == tests[i].ret, "Test [%d]: Expected %d, got %d\n", i, tests[i].ret, ret);
+        if (tests[i].ret == -1)
+        {
+            err = WSAGetLastError();
+            ok(tests[i].err == err, "Test [%d]: Expected 0x%x, got 0x%x\n", i, tests[i].err, err);
+        }
+        if (tests[i].ret != 1) continue;
+        ok(memcmp(buffer, tests[i].raw_data,
+           tests[i].family == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr)) == 0,
+           "Test [%d]: Expected binary data differs\n", i);
+
+        /* Test the result from Pton with Ntop */
+        printableW[0] = 0xdead;
+        ptrW = pInetNtopW(tests[i].family, buffer, printableW, sizeof(printableW) / sizeof(printableW[0]));
+        ok (ptrW != NULL, "Test [%d]: Failed with NULL\n", i);
+        ok (ptrW == printableW, "Test [%d]: Pointers differ (%p != %p)\n", i, ptrW, printableW);
+        if (!ptrW) continue;
+
+        MultiByteToWideChar(CP_ACP, 0, tests[i].collapsed, -1, collapsedW,
+                            sizeof(collapsedW) / sizeof(collapsedW[0]));
+        ok (lstrcmpW(ptrW, collapsedW) == 0, "Test [%d]: Expected '%s', got '%s'\n",
+            i, tests[i].collapsed, wine_dbgstr_w(ptrW));
+    }
+}
 
 static void test_ioctlsocket(void)
 {
-    SOCKET sock;
+    SOCKET sock, src, dst;
     struct tcp_keepalive kalive;
     int ret, optval;
     static const LONG cmds[] = {FIONBIO, FIONREAD, SIOCATMARK};
-    UINT i;
+    UINT i, bytes_rec;
+    char data;
+    WSABUF bufs;
     u_long arg = 0;
 
     sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
@@ -3029,12 +5003,13 @@ static void test_ioctlsocket(void)
     ok(ret != SOCKET_ERROR, "ioctlsocket failed unexpectedly\n");
     ok(arg, "SIOCATMARK expected a non-zero value\n");
 
-    /* disable SO_OOBINLINE and get the same old bahavior */
+    /* disable SO_OOBINLINE and get the same old behavior */
     optval = 0;
     ret = setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (void *)&optval, sizeof(optval));
     ok(ret != SOCKET_ERROR, "setsockopt failed unexpectedly\n");
     arg = 0;
     ret = ioctlsocket(sock, SIOCATMARK, &arg);
+    ok(ret != SOCKET_ERROR, "ioctlsocket failed unexpectedly\n");
     ok(arg, "SIOCATMARK expected a non-zero value\n");
 
     ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &arg, 0, NULL, 0, &arg, NULL, NULL);
@@ -3073,9 +5048,68 @@ static void test_ioctlsocket(void)
     ok(ret == 0 || broken(ret == SOCKET_ERROR), "WSAIoctl failed unexpectedly\n");
 
     closesocket(sock);
+
+    if (tcp_socketpair(&src, &dst) != 0)
+    {
+        ok(0, "creating socket pair failed, skipping test\n");
+        return;
+    }
+
+    /* test FIONREAD on TCP sockets */
+    optval = 0xdeadbeef;
+    ret = WSAIoctl(dst, FIONREAD, NULL, 0, &optval, sizeof(optval), &arg, NULL, NULL);
+    ok(ret == 0, "WSAIoctl failed unexpectedly with error %d\n", WSAGetLastError());
+    ok(optval == 0, "FIONREAD should have returned 0 bytes, got %d instead\n", optval);
+
+    optval = 0xdeadbeef;
+    ok(send(src, "TEST", 4, 0) == 4, "failed to send test data\n");
+    Sleep(100);
+    ret = WSAIoctl(dst, FIONREAD, NULL, 0, &optval, sizeof(optval), &arg, NULL, NULL);
+    ok(ret == 0, "WSAIoctl failed unexpectedly with error %d\n", WSAGetLastError());
+    ok(optval == 4, "FIONREAD should have returned 4 bytes, got %d instead\n", optval);
+
+    /* trying to read from an OOB inlined socket with MSG_OOB results in WSAEINVAL */
+    set_blocking(dst, FALSE);
+    i = MSG_OOB;
+    SetLastError(0xdeadbeef);
+    ret = recv(dst, &data, 1, i);
+    ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+    ret = GetLastError();
+    ok(ret == WSAEWOULDBLOCK, "expected 10035, got %d\n", ret);
+    bufs.len = sizeof(char);
+    bufs.buf = &data;
+    ret = WSARecv(dst, &bufs, 1, &bytes_rec, &i, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+    ret = GetLastError();
+    ok(ret == WSAEWOULDBLOCK, "expected 10035, got %d\n", ret);
+    optval = 1;
+    ret = setsockopt(dst, SOL_SOCKET, SO_OOBINLINE, (void *)&optval, sizeof(optval));
+    ok(ret != SOCKET_ERROR, "setsockopt failed unexpectedly\n");
+    i = MSG_OOB;
+    SetLastError(0xdeadbeef);
+    ret = recv(dst, &data, 1, i);
+    if (ret == SOCKET_ERROR)
+    {
+        ret = GetLastError();
+        ok(ret == WSAEINVAL, "expected 10022, got %d\n", ret);
+        bufs.len = sizeof(char);
+        bufs.buf = &data;
+        ret = WSARecv(dst, &bufs, 1, &bytes_rec, &i, NULL, NULL);
+        ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+        ret = GetLastError();
+        ok(ret == WSAEINVAL, "expected 10022, got %d\n", ret);
+    }
+    else ok(broken(ret == 1) /* <= NT4 */, "expected error, got 1\n");
+
+    closesocket(dst);
+    optval = 0xdeadbeef;
+    ret = WSAIoctl(dst, FIONREAD, NULL, 0, &optval, sizeof(optval), &arg, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "WSAIoctl succeeded unexpectedly\n");
+    ok(optval == 0xdeadbeef, "FIONREAD should not have changed last error, got %d instead\n", optval);
+    closesocket(src);
 }
 
-static int drain_pause=0;
+static BOOL drain_pause = FALSE;
 static DWORD WINAPI drain_socket_thread(LPVOID arg)
 {
     char buffer[1024];
@@ -3114,6 +5148,8 @@ static void test_send(void)
     OVERLAPPED ov;
     BOOL bret;
     DWORD id, bytes_sent, dwRet;
+    DWORD expected_time, connect_time;
+    socklen_t optlen;
 
     memset(&ov, 0, sizeof(ov));
 
@@ -3122,6 +5158,7 @@ static void test_send(void)
         ok(0, "creating socket pair failed, skipping test\n");
         return;
     }
+    expected_time = GetTickCount();
 
     set_blocking(dst, FALSE);
     /* force disable buffering so we can get a pending overlapped request */
@@ -3157,7 +5194,7 @@ static void test_send(void)
     buf.buf = buffer;
     buf.len = buflen;
 
-    ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    ov.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
     ok(ov.hEvent != NULL, "could not create event object, errno = %d\n", GetLastError());
     if (!ov.hEvent)
         goto end;
@@ -3208,13 +5245,33 @@ static void test_send(void)
     ok(ret == SOCKET_ERROR && WSAGetLastError() == ERROR_IO_PENDING,
        "Failed to start overlapped send %d - %d\n", ret, WSAGetLastError());
 
+    expected_time = (GetTickCount() - expected_time) / 1000;
+
+    connect_time = 0xdeadbeef;
+    optlen = sizeof(connect_time);
+    ret = getsockopt(dst, SOL_SOCKET, SO_CONNECT_TIME, (char *)&connect_time, &optlen);
+    ok(!ret, "getsockopt failed %d\n", WSAGetLastError());
+    ok(connect_time >= expected_time && connect_time <= expected_time + 1,
+       "unexpected connect time %u, expected %u\n", connect_time, expected_time);
+
+    connect_time = 0xdeadbeef;
+    optlen = sizeof(connect_time);
+    ret = getsockopt(src, SOL_SOCKET, SO_CONNECT_TIME, (char *)&connect_time, &optlen);
+    ok(!ret, "getsockopt failed %d\n", WSAGetLastError());
+    ok(connect_time >= expected_time && connect_time <= expected_time + 1,
+       "unexpected connect time %u, expected %u\n", connect_time, expected_time);
+
 end:
     if (src != INVALID_SOCKET)
         closesocket(src);
     if (dst != INVALID_SOCKET)
         closesocket(dst);
     if (hThread != NULL)
+    {
+        dwRet = WaitForSingleObject(hThread, 500);
+        ok(dwRet == WAIT_OBJECT_0, "failed to wait for thread termination: %d\n", GetLastError());
         CloseHandle(hThread);
+    }
     if (ov.hEvent)
         CloseHandle(ov.hEvent);
     HeapFree(GetProcessHeap(), 0, buffer);
@@ -3253,7 +5310,7 @@ static LRESULT CALLBACK ws2_test_WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPA
         return 0;
     }
 
-    return DefWindowProc(hwnd, msg, wparam, lparam);
+    return DefWindowProcA(hwnd, msg, wparam, lparam);
 }
 
 static void get_event_details(int event, int *bit, char *name)
@@ -3509,7 +5566,7 @@ static void test_events(int useMessages)
     struct sockaddr_in addr;
     HANDLE hThread = NULL;
     HANDLE hEvent = INVALID_HANDLE_VALUE, hEvent2 = INVALID_HANDLE_VALUE;
-    WNDCLASSEX wndclass;
+    WNDCLASSEXA wndclass;
     HWND hWnd = NULL;
     char *buffer = NULL;
     int bufferSize = 1024*1024;
@@ -3549,6 +5606,9 @@ static void test_events(int useMessages)
         goto end;
     }
 
+    ret = set_blocking(src, TRUE);
+    ok(!ret, "set_blocking failed, error %d\n", WSAGetLastError());
+
     src2 = socket(AF_INET, SOCK_STREAM, 0);
     if (src2 == INVALID_SOCKET)
     {
@@ -3556,6 +5616,9 @@ static void test_events(int useMessages)
         goto end;
     }
 
+    ret = set_blocking(src2, TRUE);
+    ok(!ret, "set_blocking failed, error %d\n", WSAGetLastError());
+
     len = sizeof(BOOL);
     if (getsockopt(src, SOL_SOCKET, SO_OOBINLINE, (void *)&bret, &len) == SOCKET_ERROR)
     {
@@ -3573,16 +5636,17 @@ static void test_events(int useMessages)
         wndclass.lpfnWndProc    = ws2_test_WndProc;
         wndclass.cbClsExtra     = 0;
         wndclass.cbWndExtra     = 0;
-        wndclass.hInstance      = GetModuleHandle(NULL);
-        wndclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
-        wndclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);
-        wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
+        wndclass.hInstance      = GetModuleHandleA(NULL);
+        wndclass.hIcon          = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
+        wndclass.hIconSm        = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
+        wndclass.hCursor        = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
         wndclass.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
         wndclass.lpszClassName  = szClassName;
         wndclass.lpszMenuName   = NULL;
-        RegisterClassEx(&wndclass);
+        RegisterClassExA(&wndclass);
 
-        hWnd = CreateWindow(szClassName, "WS2Test", WS_OVERLAPPEDWINDOW, 0, 0, 500, 500, NULL, NULL, GetModuleHandle(NULL), NULL);
+        hWnd = CreateWindowA(szClassName, "WS2Test", WS_OVERLAPPEDWINDOW,
+                            0, 0, 500, 500, NULL, NULL, GetModuleHandleA(NULL), NULL);
         if (!hWnd)
         {
             ok(0, "failed to create window: %d\n", GetLastError());
@@ -3596,12 +5660,18 @@ static void test_events(int useMessages)
             goto end;
         }
 
+        ok(set_blocking(src, TRUE) == SOCKET_ERROR, "set_blocking should failed!\n");
+        ok(WSAGetLastError() == WSAEINVAL, "expect WSAEINVAL, returned %x\n", WSAGetLastError());
+
         ret = WSAAsyncSelect(src2, hWnd, WM_SOCKET, FD_CONNECT | FD_READ | FD_OOB | FD_WRITE | FD_CLOSE);
         if (ret)
         {
             ok(0, "WSAAsyncSelect failed, error %d\n", ret);
             goto end;
         }
+
+        ok(set_blocking(src2, TRUE) == SOCKET_ERROR, "set_blocking should failed!\n");
+        ok(WSAGetLastError() == WSAEINVAL, "expect WSAEINVAL, returned %x\n", WSAGetLastError());
     }
     else
     {
@@ -3628,12 +5698,18 @@ static void test_events(int useMessages)
             goto end;
         }
 
+        ok(set_blocking(src, TRUE) == SOCKET_ERROR, "set_blocking should failed!\n");
+        ok(WSAGetLastError() == WSAEINVAL, "expect WSAEINVAL, returned %x\n", WSAGetLastError());
+
         ret = WSAEventSelect(src2, hEvent2, FD_CONNECT | FD_READ | FD_OOB | FD_WRITE | FD_CLOSE);
         if (ret)
         {
             ok(0, "WSAEventSelect failed, error %d\n", ret);
             goto end;
         }
+
+        ok(set_blocking(src2, TRUE) == SOCKET_ERROR, "set_blocking should failed!\n");
+        ok(WSAGetLastError() == WSAEINVAL, "expect WSAEINVAL, returned %x\n", WSAGetLastError());
     }
 
     server = socket(AF_INET, SOCK_STREAM, 0);
@@ -3719,14 +5795,14 @@ static void test_events(int useMessages)
         goto end;
     }
 
-    ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    ov.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
     if (ov.hEvent == NULL)
     {
         ok(0, "could not create event object, errno = %d\n", GetLastError());
         goto end;
     }
 
-    ov2.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    ov2.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
     if (ov2.hEvent == NULL)
     {
         ok(0, "could not create event object, errno = %d\n", GetLastError());
@@ -3739,23 +5815,29 @@ static void test_events(int useMessages)
     /* broken on all windows - FD_CONNECT error is garbage */
 
     /* Test simple send/recv */
+    SetLastError(0xdeadbeef);
     ret = send(dst, buffer, 100, 0);
     ok(ret == 100, "Failed to send buffer %d err %d\n", ret, GetLastError());
+    ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
     ok_event_seq(src, hEvent, read_seq, NULL, 0);
 
+    SetLastError(0xdeadbeef);
     ret = recv(src, buffer, 1, MSG_PEEK);
     ok(ret == 1, "Failed to peek at recv buffer %d err %d\n", ret, GetLastError());
+    ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
     ok_event_seq(src, hEvent, read_seq, NULL, 0);
 
+    SetLastError(0xdeadbeef);
     ret = recv(src, buffer, 50, 0);
     ok(ret == 50, "Failed to recv buffer %d err %d\n", ret, GetLastError());
+    ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
     ok_event_seq(src, hEvent, read_seq, NULL, 0);
 
     ret = recv(src, buffer, 50, 0);
     ok(ret == 50, "Failed to recv buffer %d err %d\n", ret, GetLastError());
     ok_event_seq(src, hEvent, empty_seq, NULL, 0);
 
-    /* fun fact - events are reenabled even on failure, but only for messages */
+    /* fun fact - events are re-enabled even on failure, but only for messages */
     ret = send(dst, "1", 1, 0);
     ok(ret == 1, "Failed to send buffer %d err %d\n", ret, GetLastError());
     ok_event_seq(src, hEvent, read_seq, NULL, 0);
@@ -3772,8 +5854,10 @@ static void test_events(int useMessages)
     else
         ok_event_seq(src, hEvent, empty_seq, NULL, 0);
 
+    SetLastError(0xdeadbeef);
     ret = recv(src, buffer, 1, 0);
     ok(ret == 1, "Failed to recv buffer %d err %d\n", ret, GetLastError());
+    ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
     ok_event_seq(src, hEvent, empty_seq, NULL, 0);
 
     /* Interaction with overlapped */
@@ -3815,8 +5899,10 @@ static void test_events(int useMessages)
         ok(buffer[1] == '2', "Got %c instead of 2\n", buffer[1]);
     }
 
+    SetLastError(0xdeadbeef);
     ret = send(dst, "1", 1, 0);
     ok(ret == 1, "Failed to send buffer %d err %d\n", ret, GetLastError());
+    ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
     ok_event_seq(src, hEvent, read_seq, NULL, 0);
 
     ret = recv(src, buffer, 1, 0);
@@ -3885,12 +5971,12 @@ static void test_events(int useMessages)
      * take some of it, and we will get a short write. This will trigger
      * another FD_WRITE event as soon as data is sent and more space becomes
      * available, but not any earlier. */
-    drain_pause=1;
+    drain_pause = TRUE;
     do
     {
         ret = send(src, buffer, bufferSize, 0);
     } while (ret == bufferSize);
-    drain_pause=0;
+    drain_pause = FALSE;
     if (ret >= 0 || WSAGetLastError() == WSAEWOULDBLOCK)
     {
         Sleep(400); /* win9x */
@@ -3966,6 +6052,51 @@ static void test_events(int useMessages)
     ok(ret == 1, "Sending to half-closed socket failed %d err %d\n", ret, GetLastError());
     ok_event_seq(src2, hEvent2, empty_seq, NULL, 0);
 
+    if (useMessages)
+    {
+        ret = WSAAsyncSelect(src, hWnd, WM_SOCKET, 0);
+        if (ret)
+        {
+            ok(0, "WSAAsyncSelect failed, error %d\n", ret);
+            goto end;
+        }
+
+        ret = set_blocking(src, TRUE);
+        ok(!ret, "set_blocking failed, error %d\n", WSAGetLastError());
+
+        ret = WSAAsyncSelect(src2, hWnd, WM_SOCKET, 0);
+        if (ret)
+        {
+            ok(0, "WSAAsyncSelect failed, error %d\n", ret);
+            goto end;
+        }
+
+        ret = set_blocking(src2, TRUE);
+        ok(!ret, "set_blocking failed, error %d\n", WSAGetLastError());
+    }
+    else
+    {
+        ret = WSAEventSelect(src, hEvent2, 0);
+        if (ret)
+        {
+            ok(0, "WSAAsyncSelect failed, error %d\n", ret);
+            goto end;
+        }
+
+        ret = set_blocking(src, TRUE);
+        ok(!ret, "set_blocking failed, error %d\n", WSAGetLastError());
+
+        ret = WSAEventSelect(src2, hEvent2, 0);
+        if (ret)
+        {
+            ok(0, "WSAAsyncSelect failed, error %d\n", ret);
+            goto end;
+        }
+
+        ret = set_blocking(src2, TRUE);
+        ok(!ret, "set_blocking failed, error %d\n", WSAGetLastError());
+    }
+
 end:
     if (src != INVALID_SOCKET)
     {
@@ -4044,6 +6175,191 @@ end:
         closesocket(v6);
 }
 
+static void test_WSASendMsg(void)
+{
+    SOCKET sock, dst;
+    struct sockaddr_in sendaddr, sockaddr;
+    GUID WSASendMsg_GUID = WSAID_WSASENDMSG;
+    LPFN_WSASENDMSG pWSASendMsg = NULL;
+    char teststr[12] = "hello world", buffer[32];
+    WSABUF iovec[2];
+    WSAMSG msg;
+    DWORD bytesSent, err;
+    int ret, addrlen;
+
+    /* FIXME: Missing OVERLAPPED and OVERLAPPED COMPLETION ROUTINE tests */
+
+    sock = socket(AF_INET, SOCK_DGRAM, 0);
+    ok(sock != INVALID_SOCKET, "socket() failed\n");
+
+    /* Obtain the WSASendMsg function */
+    WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &WSASendMsg_GUID, sizeof(WSASendMsg_GUID),
+             &pWSASendMsg, sizeof(pWSASendMsg), &err, NULL, NULL);
+    if (!pWSASendMsg)
+    {
+        closesocket(sock);
+        win_skip("WSASendMsg is unsupported, some tests will be skipped.\n");
+        return;
+    }
+
+    /* fake address for now */
+    sendaddr.sin_family = AF_INET;
+    sendaddr.sin_port = htons(139);
+    sendaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+    memset(&msg, 0, sizeof(msg));
+    iovec[0].buf      = teststr;
+    iovec[0].len      = sizeof(teststr);
+    iovec[1].buf      = teststr;
+    iovec[1].len      = sizeof(teststr) / 2;
+    msg.name          = (struct sockaddr *) &sendaddr;
+    msg.namelen       = sizeof(sendaddr);
+    msg.lpBuffers     = iovec;
+    msg.dwBufferCount = 1; /* send only one buffer for now */
+
+    WSASetLastError(0xdeadbeef);
+    ret = pWSASendMsg(INVALID_SOCKET, &msg, 0, NULL, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "WSASendMsg should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAENOTSOCK, "expected 10038, got %d instead\n", err);
+
+    WSASetLastError(0xdeadbeef);
+    ret = pWSASendMsg(sock, NULL, 0, NULL, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "WSASendMsg should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
+
+    WSASetLastError(0xdeadbeef);
+    ret = pWSASendMsg(sock, NULL, 0, &bytesSent, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "WSASendMsg should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
+
+    WSASetLastError(0xdeadbeef);
+    ret = pWSASendMsg(sock, &msg, 0, NULL, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "WSASendMsg should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err);
+
+    closesocket(sock);
+
+    sock = socket(AF_INET, SOCK_DGRAM, 0);
+    ok(sock != INVALID_SOCKET, "socket() failed\n");
+
+    dst = socket(AF_INET, SOCK_DGRAM, 0);
+    ok(dst != INVALID_SOCKET, "socket() failed\n");
+
+    memset(&sockaddr, 0, sizeof(sockaddr));
+    sockaddr.sin_family = AF_INET;
+    sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+    ok(!bind(dst, (struct sockaddr*)&sockaddr, sizeof(sockaddr)),
+       "bind should have worked\n");
+
+    /* read address to find out the port number to be used in send */
+    memset(&sendaddr, 0, sizeof(sendaddr));
+    addrlen = sizeof(sendaddr);
+    ok(!getsockname(dst, (struct sockaddr *) &sendaddr, &addrlen),
+       "getsockname should have worked\n");
+    ok(sendaddr.sin_port, "socket port should be != 0\n");
+
+    /* ensure the sending socket is not bound */
+    WSASetLastError(0xdeadbeef);
+    addrlen = sizeof(sockaddr);
+    ret = getsockname(sock, (struct sockaddr*)&sockaddr, &addrlen);
+    ok(ret == SOCKET_ERROR, "getsockname should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEINVAL, "expected 10022, got %d instead\n", err);
+
+    set_blocking(sock, TRUE);
+
+    bytesSent = 0;
+    SetLastError(0xdeadbeef);
+    ret = pWSASendMsg(sock, &msg, 0, &bytesSent, NULL, NULL);
+    ok(!ret, "WSASendMsg should have worked\n");
+    ok(GetLastError() == 0 || broken(GetLastError() == 0xdeadbeef) /* Win <= 2008 */,
+       "Expected 0, got %d\n", GetLastError());
+    ok(bytesSent == iovec[0].len, "incorret bytes sent, expected %d, sent %d\n",
+       iovec[0].len, bytesSent);
+
+    /* receive data */
+    addrlen = sizeof(sockaddr);
+    memset(buffer, 0, sizeof(buffer));
+    SetLastError(0xdeadbeef);
+    ret = recvfrom(dst, buffer, sizeof(buffer), 0, (struct sockaddr *) &sockaddr, &addrlen);
+    ok(ret == bytesSent, "got %d, expected %d\n",
+       ret, bytesSent);
+    ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
+
+    /* A successful call to WSASendMsg must have bound the socket */
+    addrlen = sizeof(sockaddr);
+    sockaddr.sin_port = 0;
+    sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+    ret = getsockname(sock, (struct sockaddr*)&sockaddr, &addrlen);
+    ok(!ret, "getsockname should have worked\n");
+    ok(sockaddr.sin_addr.s_addr == htonl(INADDR_ANY), "expected 0.0.0.0, got %s\n",
+       inet_ntoa(sockaddr.sin_addr));
+    ok(sockaddr.sin_port, "sin_port should be != 0\n");
+
+    msg.dwBufferCount = 2; /* send both buffers */
+
+    bytesSent = 0;
+    SetLastError(0xdeadbeef);
+    ret = pWSASendMsg(sock, &msg, 0, &bytesSent, NULL, NULL);
+    ok(!ret, "WSASendMsg should have worked\n");
+    ok(bytesSent == iovec[0].len + iovec[1].len, "incorret bytes sent, expected %d, sent %d\n",
+       iovec[0].len + iovec[1].len, bytesSent);
+    ok(GetLastError() == 0 || broken(GetLastError() == 0xdeadbeef) /* Win <= 2008 */,
+       "Expected 0, got %d\n", GetLastError());
+
+    /* receive data */
+    addrlen = sizeof(sockaddr);
+    memset(buffer, 0, sizeof(buffer));
+    SetLastError(0xdeadbeef);
+    ret = recvfrom(dst, buffer, sizeof(buffer), 0, (struct sockaddr *) &sockaddr, &addrlen);
+    ok(ret == bytesSent, "got %d, expected %d\n",
+       ret, bytesSent);
+    ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
+
+    closesocket(sock);
+    closesocket(dst);
+
+    /* a bad call to WSASendMsg will also bind the socket */
+    addrlen = sizeof(sockaddr);
+    sockaddr.sin_port = 0;
+    sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+    sock = socket(AF_INET, SOCK_DGRAM, 0);
+    ok(sock != INVALID_SOCKET, "socket() failed\n");
+    ok(pWSASendMsg(sock, &msg, 0, NULL, NULL, NULL) == SOCKET_ERROR, "WSASendMsg should have failed\n");
+todo_wine {
+    ok(!getsockname(sock, (struct sockaddr*)&sockaddr, &addrlen), "getsockname should have worked\n");
+    ok(sockaddr.sin_addr.s_addr == htonl(INADDR_ANY), "expected 0.0.0.0, got %s\n",
+       inet_ntoa(sockaddr.sin_addr));
+    ok(sockaddr.sin_port, "sin_port should be > 0\n");
+}
+    closesocket(sock);
+
+    /* a bad call without msg parameter will not trigger the auto-bind */
+    sock = socket(AF_INET, SOCK_DGRAM, 0);
+    ok(sock != INVALID_SOCKET, "socket() failed\n");
+    ok(pWSASendMsg(sock, NULL, 0, NULL, NULL, NULL) == SOCKET_ERROR, "WSASendMsg should have failed\n");
+    ok(getsockname(sock, (struct sockaddr*)&sockaddr, &addrlen), "getsockname should have failed\n");
+    err = WSAGetLastError();
+    ok(err == WSAEINVAL, "expected 10022, got %d instead\n", err);
+    closesocket(sock);
+
+    /* SOCK_STREAM sockets are not supported */
+    bytesSent = 0;
+    sock = socket(AF_INET, SOCK_STREAM, 0);
+    ok(sock != INVALID_SOCKET, "socket() failed\n");
+    SetLastError(0xdeadbeef);
+    ret = pWSASendMsg(sock, &msg, 0, &bytesSent, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "WSASendMsg should have failed\n");
+    err = WSAGetLastError();
+todo_wine
+    ok(err == WSAEINVAL, "expected 10014, got %d instead\n", err);
+    closesocket(sock);
+}
+
 static void test_WSASendTo(void)
 {
     SOCKET s;
@@ -4115,8 +6431,6 @@ static void test_WSARecv(void)
     BOOL bret;
     HANDLE thread;
 
-    memset(&ov, 0, sizeof(ov));
-
     tcp_socketpair(&src, &dest);
     if (src == INVALID_SOCKET || dest == INVALID_SOCKET)
     {
@@ -4124,11 +6438,44 @@ static void test_WSARecv(void)
         goto end;
     }
 
-    bufs.len = sizeof(buf);
-    bufs.buf = buf;
+    memset(&ov, 0, sizeof(ov));
     flags = 0;
+    bufs.len = 2;
+    bufs.buf = buf;
+
+    /* Send 4 bytes and receive in two calls of 2 */
+    SetLastError(0xdeadbeef);
+    iret = send(src, "test", 4, 0);
+    ok(iret == 4, "Expected 4, got %d\n", iret);
+    ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    bytesReturned = 0xdeadbeef;
+    iret = WSARecv(dest, &bufs, 1, &bytesReturned, &flags, NULL, NULL);
+    ok(!iret, "Expected 0, got %d\n", iret);
+    ok(bytesReturned, "Expected 2, got %d\n", bytesReturned);
+    ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    bytesReturned = 0xdeadbeef;
+    iret = WSARecv(dest, &bufs, 1, &bytesReturned, &flags, NULL, NULL);
+    ok(!iret, "Expected 0, got %d\n", iret);
+    ok(bytesReturned, "Expected 2, got %d\n", bytesReturned);
+    ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
+
+    bufs.len = 4;
+    SetLastError(0xdeadbeef);
+    iret = send(src, "test", 4, 0);
+    ok(iret == 4, "Expected 4, got %d\n", iret);
+    ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
+    SetLastError(0xdeadbeef);
+    bytesReturned = 0xdeadbeef;
+    iret = WSARecv(dest, &bufs, 1, &bytesReturned, &flags, NULL, NULL);
+    ok(!iret, "Expected 0, got %d\n", iret);
+    ok(bytesReturned, "Expected 4, got %d\n", bytesReturned);
+    ok(GetLastError() == ERROR_SUCCESS, "Expected 0, got %d\n", GetLastError());
+
+    bufs.len = sizeof(buf);
 
-    ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    ov.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
     ok(ov.hEvent != NULL, "could not create event object, errno = %d\n", GetLastError());
     if (!ov.hEvent)
         goto end;
@@ -4154,6 +6501,8 @@ static void test_WSARecv(void)
     todo_wine ok(!bret && (GetLastError() == ERROR_NETNAME_DELETED || broken(GetLastError() == ERROR_IO_INCOMPLETE) /* win9x */),
         "Did not get disconnect event: %d, error %d\n", bret, GetLastError());
     ok(bytesReturned == 0, "Bytes received is %d\n", bytesReturned);
+    closesocket(dest);
+    dest = INVALID_SOCKET;
 
     src = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
     ok(src != INVALID_SOCKET, "failed to create socket %d\n", WSAGetLastError());
@@ -4186,6 +6535,7 @@ static void test_WSARecv(void)
 
     send(src, "test message", sizeof("test message"), 0);
     thread = CreateThread(NULL, 0, recv_thread, &dest, 0, &id);
+    WaitForSingleObject(thread, 3000);
     CloseHandle(thread);
 
 end:
@@ -4199,14 +6549,241 @@ end:
         WSACloseEvent(ov.hEvent);
 }
 
+#define POLL_CLEAR() ix = 0
+#define POLL_SET(s, ev) {fds[ix].fd = s; fds[ix++].events = ev;}
+#define POLL_ISSET(s, rev) poll_isset(fds, ix, s, rev)
+static BOOL poll_isset(WSAPOLLFD *fds, int max, SOCKET s, int rev)
+{
+    int k;
+    for (k = 0; k < max; k++)
+        if (fds[k].fd == s && (fds[k].revents == rev)) return TRUE;
+    return FALSE;
+}
+
+static void test_WSAPoll(void)
+{
+    int ix, ret, err, poll_timeout;
+    SOCKET fdListen, fdRead, fdWrite;
+    struct sockaddr_in address;
+    socklen_t len;
+    static char tmp_buf[1024];
+    WSAPOLLFD fds[16];
+    HANDLE thread_handle;
+    DWORD id;
+
+    if (!pWSAPoll) /* >= Vista */
+    {
+        skip("WSAPoll is unsupported, some tests will be skipped.\n");
+        return;
+    }
+
+    /* Invalid parameters test */
+    SetLastError(0xdeadbeef);
+    ret = pWSAPoll(NULL, 0, 0);
+    err = GetLastError();
+    ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+    ok(err == WSAEINVAL, "expected 10022, got %d\n", err);
+    SetLastError(0xdeadbeef);
+    ret = pWSAPoll(NULL, 1, 0);
+    err = GetLastError();
+    ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+    ok(err == WSAEFAULT, "expected 10014, got %d\n", err);
+    SetLastError(0xdeadbeef);
+    ret = pWSAPoll(NULL, 0, 1);
+    err = GetLastError();
+    ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+    ok(err == WSAEINVAL, "expected 10022, got %d\n", err);
+    SetLastError(0xdeadbeef);
+    ret = pWSAPoll(NULL, 1, 1);
+    err = GetLastError();
+    ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+    ok(err == WSAEFAULT, "expected 10014, got %d\n", err);
+
+    /* WSAPoll() tries to mime the unix poll() call. The following tests do:
+     * - check if a connection attempt ended with success or error;
+     * - check if a pending connection is waiting for acceptance;
+     * - check for data to read, availability for write and OOB data
+     */
+    memset(&address, 0, sizeof(address));
+    address.sin_addr.s_addr = inet_addr("127.0.0.1");
+    address.sin_family = AF_INET;
+    len = sizeof(address);
+    fdListen = setup_server_socket(&address, &len);
+    poll_timeout = 100;
+
+    /* When no events are pending poll returns 0 with no error */
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+
+    /* Test listening socket connection attempt notifications */
+    fdWrite = setup_connector_socket(&address, len, TRUE);
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN | POLLOUT);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(POLL_ISSET(fdListen, POLLRDNORM), "fdListen socket events incorrect\n");
+    len = sizeof(address);
+    fdRead = accept(fdListen, (struct sockaddr*) &address, &len);
+    ok(fdRead != INVALID_SOCKET, "expected a valid socket\n");
+
+    /* Test client side connection attempt notifications */
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN | POLLOUT);
+    POLL_SET(fdRead, POLLIN | POLLOUT);
+    POLL_SET(fdWrite, POLLIN | POLLOUT);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 2, "expected 2, got %d\n", ret);
+    ok(POLL_ISSET(fdWrite, POLLWRNORM), "fdWrite socket events incorrect\n");
+    ok(POLL_ISSET(fdRead, POLLWRNORM), "fdRead socket events incorrect\n");
+    len = sizeof(id);
+    id = 0xdeadbeef;
+    err = getsockopt(fdWrite, SOL_SOCKET, SO_ERROR, (char*)&id, &len);
+    ok(!err, "getsockopt failed with %d\n", WSAGetLastError());
+    ok(id == 0, "expected 0, got %d\n", id);
+
+    /* Test data receiving notifications */
+    ret = send(fdWrite, "1234", 4, 0);
+    ok(ret == 4, "expected 4, got %d\n", ret);
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN | POLLOUT);
+    POLL_SET(fdRead, POLLIN);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(POLL_ISSET(fdRead, POLLRDNORM), "fdRead socket events incorrect\n");
+    ret = recv(fdRead, tmp_buf, sizeof(tmp_buf), 0);
+    ok(ret == 4, "expected 4, got %d\n", ret);
+    ok(!strcmp(tmp_buf, "1234"), "data received differs from sent\n");
+
+    /* Test OOB data notifications */
+    ret = send(fdWrite, "A", 1, MSG_OOB);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN | POLLOUT);
+    POLL_SET(fdRead, POLLIN);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(POLL_ISSET(fdRead, POLLRDBAND), "fdRead socket events incorrect\n");
+    tmp_buf[0] = 0xAF;
+    ret = recv(fdRead, tmp_buf, sizeof(tmp_buf), MSG_OOB);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(tmp_buf[0] == 'A', "expected 'A', got 0x%02X\n", tmp_buf[0]);
+
+    /* If the socket is OOBINLINED the notification is like normal data */
+    ret = 1;
+    ret = setsockopt(fdRead, SOL_SOCKET, SO_OOBINLINE, (char*) &ret, sizeof(ret));
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    ret = send(fdWrite, "A", 1, MSG_OOB);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN | POLLOUT);
+    POLL_SET(fdRead, POLLIN | POLLOUT);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    tmp_buf[0] = 0xAF;
+    SetLastError(0xdeadbeef);
+    ret = recv(fdRead, tmp_buf, sizeof(tmp_buf), MSG_OOB);
+    ok(ret == SOCKET_ERROR, "expected -1, got %d\n", ret);
+    ok(GetLastError() == WSAEINVAL, "expected 10022, got %d\n", GetLastError());
+    ret = recv(fdRead, tmp_buf, sizeof(tmp_buf), 0);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(tmp_buf[0] == 'A', "expected 'A', got 0x%02X\n", tmp_buf[0]);
+
+    /* Test connection closed notifications */
+    ret = closesocket(fdRead);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    POLL_CLEAR();
+    POLL_SET(fdListen, POLLIN | POLLOUT);
+    POLL_SET(fdWrite, POLLIN);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+todo_wine
+    ok(POLL_ISSET(fdWrite, POLLHUP), "fdWrite socket events incorrect\n");
+    ret = recv(fdWrite, tmp_buf, sizeof(tmp_buf), 0);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+
+    /* When a connection is attempted to a non-listening socket due to a bug
+     * in the MS code it will never be notified. This is a long standing issue
+     * that will never be fixed for compatibility reasons so we have to deal
+     * with it manually. */
+    ret = closesocket(fdWrite);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    ret = closesocket(fdListen);
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    len = sizeof(address);
+    fdWrite = setup_connector_socket(&address, len, TRUE);
+    POLL_CLEAR();
+    POLL_SET(fdWrite, POLLIN | POLLOUT);
+    poll_timeout = 2000;
+    ret = pWSAPoll(fds, ix, poll_timeout);
+todo_wine
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    len = sizeof(id);
+    id = 0xdeadbeef;
+    err = getsockopt(fdWrite, SOL_SOCKET, SO_ERROR, (char*)&id, &len);
+    ok(!err, "getsockopt failed with %d\n", WSAGetLastError());
+    ok(id == WSAECONNREFUSED, "expected 10061, got %d\n", id);
+    closesocket(fdWrite);
+
+    /* Try poll() on a closed socket after connection */
+    ok(!tcp_socketpair(&fdRead, &fdWrite), "creating socket pair failed\n");
+    closesocket(fdRead);
+    POLL_CLEAR();
+    POLL_SET(fdWrite, POLLIN | POLLOUT);
+    POLL_SET(fdRead, POLLIN | POLLOUT);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(POLL_ISSET(fdRead, POLLNVAL), "fdRead socket events incorrect\n");
+    POLL_CLEAR();
+    POLL_SET(fdWrite, POLLIN | POLLOUT);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+todo_wine
+    ok(POLL_ISSET(fdWrite, POLLWRNORM | POLLHUP) || broken(POLL_ISSET(fdWrite, POLLWRNORM)) /* <= 2008 */,
+       "fdWrite socket events incorrect\n");
+    closesocket(fdWrite);
+
+    /* Close the socket currently being polled in a thread */
+    ok(!tcp_socketpair(&fdRead, &fdWrite), "creating socket pair failed\n");
+    thread_handle = CreateThread(NULL, 0, SelectCloseThread, &fdWrite, 0, &id);
+    ok(thread_handle != NULL, "CreateThread failed unexpectedly: %d\n", GetLastError());
+    POLL_CLEAR();
+    POLL_SET(fdWrite, POLLIN | POLLOUT);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+    ok(POLL_ISSET(fdWrite, POLLWRNORM), "fdWrite socket events incorrect\n");
+    WaitForSingleObject (thread_handle, 1000);
+    closesocket(fdRead);
+    /* test again with less flags - behavior changes */
+    ok(!tcp_socketpair(&fdRead, &fdWrite), "creating socket pair failed\n");
+    thread_handle = CreateThread(NULL, 0, SelectCloseThread, &fdWrite, 0, &id);
+    ok(thread_handle != NULL, "CreateThread failed unexpectedly: %d\n", GetLastError());
+    POLL_CLEAR();
+    POLL_SET(fdWrite, POLLIN);
+    ret = pWSAPoll(fds, ix, poll_timeout);
+    ok(ret == 1, "expected 1, got %d\n", ret);
+todo_wine
+    ok(POLL_ISSET(fdWrite, POLLNVAL), "fdWrite socket events incorrect\n");
+    WaitForSingleObject (thread_handle, 1000);
+    closesocket(fdRead);
+}
+#undef POLL_SET
+#undef POLL_ISSET
+#undef POLL_CLEAR
+
 static void test_GetAddrInfoW(void)
 {
     static const WCHAR port[] = {'8','0',0};
     static const WCHAR empty[] = {0};
     static const WCHAR localhost[] = {'l','o','c','a','l','h','o','s','t',0};
+    static const WCHAR nxdomain[] =
+        {'n','x','d','o','m','a','i','n','.','c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
     static const WCHAR zero[] = {'0',0};
-    int ret;
-    ADDRINFOW *result, hint;
+    int i, ret;
+    ADDRINFOW *result, *result2, *p, hint;
+    WCHAR name[256];
+    DWORD size = sizeof(name)/sizeof(WCHAR);
 
     if (!pGetAddrInfoW || !pFreeAddrInfoW)
     {
@@ -4214,27 +6791,50 @@ static void test_GetAddrInfoW(void)
         return;
     }
     memset(&hint, 0, sizeof(ADDRINFOW));
+    name[0] = 0;
+    GetComputerNameExW( ComputerNamePhysicalDnsHostname, name, &size );
 
+    result = (ADDRINFOW *)0xdeadbeef;
+    WSASetLastError(0xdeadbeef);
     ret = pGetAddrInfoW(NULL, NULL, NULL, &result);
     ok(ret == WSAHOST_NOT_FOUND, "got %d expected WSAHOST_NOT_FOUND\n", ret);
+    ok(WSAGetLastError() == WSAHOST_NOT_FOUND, "expected 11001, got %d\n", WSAGetLastError());
+    ok(result == NULL, "got %p\n", result);
 
     result = NULL;
+    WSASetLastError(0xdeadbeef);
     ret = pGetAddrInfoW(empty, NULL, NULL, &result);
     ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
     ok(result != NULL, "GetAddrInfoW failed\n");
+    ok(WSAGetLastError() == 0, "expected 0, got %d\n", WSAGetLastError());
     pFreeAddrInfoW(result);
 
     result = NULL;
     ret = pGetAddrInfoW(NULL, zero, NULL, &result);
     ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
     ok(result != NULL, "GetAddrInfoW failed\n");
+
+    result2 = NULL;
+    ret = pGetAddrInfoW(NULL, empty, NULL, &result2);
+    ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+    ok(result2 != NULL, "GetAddrInfoW failed\n");
+    compare_addrinfow(result, result2);
     pFreeAddrInfoW(result);
+    pFreeAddrInfoW(result2);
 
     result = NULL;
     ret = pGetAddrInfoW(empty, zero, NULL, &result);
     ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+    ok(WSAGetLastError() == 0, "expected 0, got %d\n", WSAGetLastError());
     ok(result != NULL, "GetAddrInfoW failed\n");
+
+    result2 = NULL;
+    ret = pGetAddrInfoW(empty, empty, NULL, &result2);
+    ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+    ok(result2 != NULL, "GetAddrInfoW failed\n");
+    compare_addrinfow(result, result2);
     pFreeAddrInfoW(result);
+    pFreeAddrInfoW(result2);
 
     result = NULL;
     ret = pGetAddrInfoW(localhost, NULL, NULL, &result);
@@ -4257,15 +6857,123 @@ static void test_GetAddrInfoW(void)
     pFreeAddrInfoW(result);
 
     result = NULL;
+    ret = pGetAddrInfoW(localhost, NULL, &hint, &result);
+    ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+    pFreeAddrInfoW(result);
+
+    result = NULL;
+    SetLastError(0xdeadbeef);
     ret = pGetAddrInfoW(localhost, port, &hint, &result);
     ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+    ok(WSAGetLastError() == 0, "expected 0, got %d\n", WSAGetLastError());
+    pFreeAddrInfoW(result);
+
+    /* try to get information from the computer name, result is the same
+     * as if requesting with an empty host name. */
+    ret = pGetAddrInfoW(name, NULL, NULL, &result);
+    ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+    ok(result != NULL, "GetAddrInfoW failed\n");
+
+    ret = pGetAddrInfoW(empty, NULL, NULL, &result2);
+    ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+    ok(result2 != NULL, "GetAddrInfoW failed\n");
+    compare_addrinfow(result, result2);
+    pFreeAddrInfoW(result);
+    pFreeAddrInfoW(result2);
+
+    ret = pGetAddrInfoW(name, empty, NULL, &result);
+    ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+    ok(result != NULL, "GetAddrInfoW failed\n");
+
+    ret = pGetAddrInfoW(empty, empty, NULL, &result2);
+    ok(!ret, "GetAddrInfoW failed with %d\n", WSAGetLastError());
+    ok(result2 != NULL, "GetAddrInfoW failed\n");
+    compare_addrinfow(result, result2);
     pFreeAddrInfoW(result);
+    pFreeAddrInfoW(result2);
+
+    result = (ADDRINFOW *)0xdeadbeef;
+    WSASetLastError(0xdeadbeef);
+    ret = pGetAddrInfoW(NULL, NULL, NULL, &result);
+    if(ret == 0)
+    {
+        skip("nxdomain returned success. Broken ISP redirects?\n");
+        return;
+    }
+    ok(ret == WSAHOST_NOT_FOUND, "got %d expected WSAHOST_NOT_FOUND\n", ret);
+    ok(WSAGetLastError() == WSAHOST_NOT_FOUND, "expected 11001, got %d\n", WSAGetLastError());
+    ok(result == NULL, "got %p\n", result);
+
+    result = (ADDRINFOW *)0xdeadbeef;
+    WSASetLastError(0xdeadbeef);
+    ret = pGetAddrInfoW(nxdomain, NULL, NULL, &result);
+    if(ret == 0)
+    {
+        skip("nxdomain returned success. Broken ISP redirects?\n");
+        return;
+    }
+    ok(ret == WSAHOST_NOT_FOUND, "got %d expected WSAHOST_NOT_FOUND\n", ret);
+    ok(WSAGetLastError() == WSAHOST_NOT_FOUND, "expected 11001, got %d\n", WSAGetLastError());
+    ok(result == NULL, "got %p\n", result);
+
+    for (i = 0;i < (sizeof(hinttests) / sizeof(hinttests[0]));i++)
+    {
+        hint.ai_family = hinttests[i].family;
+        hint.ai_socktype = hinttests[i].socktype;
+        hint.ai_protocol = hinttests[i].protocol;
+
+        result = NULL;
+        SetLastError(0xdeadbeef);
+        ret = pGetAddrInfoW(localhost, NULL, &hint, &result);
+        if (!ret)
+        {
+            if (hinttests[i].error)
+                ok(0, "test %d: GetAddrInfoW succeeded unexpectedly\n", i);
+            else
+            {
+                p = result;
+                do
+                {
+                    /* when AF_UNSPEC is used the return will be either AF_INET or AF_INET6 */
+                    if (hinttests[i].family == AF_UNSPEC)
+                        ok(p->ai_family == AF_INET || p->ai_family == AF_INET6,
+                           "test %d: expected AF_INET or AF_INET6, got %d\n",
+                           i, p->ai_family);
+                    else
+                        ok(p->ai_family == hinttests[i].family,
+                           "test %d: expected family %d, got %d\n",
+                           i, hinttests[i].family, p->ai_family);
+
+                    ok(p->ai_socktype == hinttests[i].socktype,
+                       "test %d: expected type %d, got %d\n",
+                       i, hinttests[i].socktype, p->ai_socktype);
+                    ok(p->ai_protocol == hinttests[i].protocol,
+                       "test %d: expected protocol %d, got %d\n",
+                       i, hinttests[i].protocol, p->ai_protocol);
+                    p = p->ai_next;
+                }
+                while (p);
+            }
+            pFreeAddrInfoW(result);
+        }
+        else
+        {
+            DWORD err = WSAGetLastError();
+            if (hinttests[i].error)
+                ok(hinttests[i].error == err, "test %d: GetAddrInfoW failed with error %d, expected %d\n",
+                   i, err, hinttests[i].error);
+            else
+                ok(0, "test %d: GetAddrInfoW failed with %d (err %d)\n", i, ret, err);
+        }
+    }
 }
 
 static void test_getaddrinfo(void)
 {
-    int ret;
-    ADDRINFOA *result, hint;
+    int i, ret;
+    ADDRINFOA *result, *result2, *p, hint;
+    CHAR name[256];
+    DWORD size = sizeof(name);
 
     if (!pgetaddrinfo || !pfreeaddrinfo)
     {
@@ -4273,27 +6981,50 @@ static void test_getaddrinfo(void)
         return;
     }
     memset(&hint, 0, sizeof(ADDRINFOA));
+    GetComputerNameExA( ComputerNamePhysicalDnsHostname, name, &size );
 
+    result = (ADDRINFOA *)0xdeadbeef;
+    WSASetLastError(0xdeadbeef);
     ret = pgetaddrinfo(NULL, NULL, NULL, &result);
     ok(ret == WSAHOST_NOT_FOUND, "got %d expected WSAHOST_NOT_FOUND\n", ret);
+    ok(WSAGetLastError() == WSAHOST_NOT_FOUND, "expected 11001, got %d\n", WSAGetLastError());
+    ok(result == NULL, "got %p\n", result);
 
     result = NULL;
+    WSASetLastError(0xdeadbeef);
     ret = pgetaddrinfo("", NULL, NULL, &result);
     ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
     ok(result != NULL, "getaddrinfo failed\n");
+    ok(WSAGetLastError() == 0, "expected 0, got %d\n", WSAGetLastError());
     pfreeaddrinfo(result);
 
     result = NULL;
     ret = pgetaddrinfo(NULL, "0", NULL, &result);
     ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
     ok(result != NULL, "getaddrinfo failed\n");
+
+    result2 = NULL;
+    ret = pgetaddrinfo(NULL, "", NULL, &result2);
+    ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+    ok(result2 != NULL, "getaddrinfo failed\n");
+    compare_addrinfo(result, result2);
     pfreeaddrinfo(result);
+    pfreeaddrinfo(result2);
 
     result = NULL;
+    WSASetLastError(0xdeadbeef);
     ret = pgetaddrinfo("", "0", NULL, &result);
     ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+    ok(WSAGetLastError() == 0, "expected 0, got %d\n", WSAGetLastError());
     ok(result != NULL, "getaddrinfo failed\n");
+
+    result2 = NULL;
+    ret = pgetaddrinfo("", "", NULL, &result2);
+    ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+    ok(result2 != NULL, "getaddrinfo failed\n");
+    compare_addrinfo(result, result2);
     pfreeaddrinfo(result);
+    pfreeaddrinfo(result2);
 
     result = NULL;
     ret = pgetaddrinfo("localhost", NULL, NULL, &result);
@@ -4316,9 +7047,103 @@ static void test_getaddrinfo(void)
     pfreeaddrinfo(result);
 
     result = NULL;
+    ret = pgetaddrinfo("localhost", NULL, &hint, &result);
+    ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+    pfreeaddrinfo(result);
+
+    result = NULL;
+    WSASetLastError(0xdeadbeef);
     ret = pgetaddrinfo("localhost", "80", &hint, &result);
     ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+    ok(WSAGetLastError() == 0, "expected 0, got %d\n", WSAGetLastError());
+    pfreeaddrinfo(result);
+
+    /* try to get information from the computer name, result is the same
+     * as if requesting with an empty host name. */
+    ret = pgetaddrinfo(name, NULL, NULL, &result);
+    ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+    ok(result != NULL, "getaddrinfo failed\n");
+
+    ret = pgetaddrinfo("", NULL, NULL, &result2);
+    ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+    ok(result2 != NULL, "getaddrinfo failed\n");
+    compare_addrinfo(result, result2);
     pfreeaddrinfo(result);
+    pfreeaddrinfo(result2);
+
+    ret = pgetaddrinfo(name, "", NULL, &result);
+    ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+    ok(result != NULL, "getaddrinfo failed\n");
+
+    ret = pgetaddrinfo("", "", NULL, &result2);
+    ok(!ret, "getaddrinfo failed with %d\n", WSAGetLastError());
+    ok(result2 != NULL, "getaddrinfo failed\n");
+    compare_addrinfo(result, result2);
+    pfreeaddrinfo(result);
+    pfreeaddrinfo(result2);
+
+    result = (ADDRINFOA *)0xdeadbeef;
+    WSASetLastError(0xdeadbeef);
+    ret = pgetaddrinfo("nxdomain.codeweavers.com", NULL, NULL, &result);
+    if(ret == 0)
+    {
+        skip("nxdomain returned success. Broken ISP redirects?\n");
+        return;
+    }
+    ok(ret == WSAHOST_NOT_FOUND, "got %d expected WSAHOST_NOT_FOUND\n", ret);
+    ok(WSAGetLastError() == WSAHOST_NOT_FOUND, "expected 11001, got %d\n", WSAGetLastError());
+    ok(result == NULL, "got %p\n", result);
+
+    for (i = 0;i < (sizeof(hinttests) / sizeof(hinttests[0]));i++)
+    {
+        hint.ai_family = hinttests[i].family;
+        hint.ai_socktype = hinttests[i].socktype;
+        hint.ai_protocol = hinttests[i].protocol;
+
+        result = NULL;
+        SetLastError(0xdeadbeef);
+        ret = pgetaddrinfo("localhost", NULL, &hint, &result);
+        if(!ret)
+        {
+            if (hinttests[i].error)
+                ok(0, "test %d: getaddrinfo succeeded unexpectedly\n", i);
+            else
+            {
+                p = result;
+                do
+                {
+                    /* when AF_UNSPEC is used the return will be either AF_INET or AF_INET6 */
+                    if (hinttests[i].family == AF_UNSPEC)
+                        ok(p->ai_family == AF_INET || p->ai_family == AF_INET6,
+                           "test %d: expected AF_INET or AF_INET6, got %d\n",
+                           i, p->ai_family);
+                    else
+                        ok(p->ai_family == hinttests[i].family,
+                           "test %d: expected family %d, got %d\n",
+                           i, hinttests[i].family, p->ai_family);
+
+                    ok(p->ai_socktype == hinttests[i].socktype,
+                       "test %d: expected type %d, got %d\n",
+                       i, hinttests[i].socktype, p->ai_socktype);
+                    ok(p->ai_protocol == hinttests[i].protocol,
+                       "test %d: expected protocol %d, got %d\n",
+                       i, hinttests[i].protocol, p->ai_protocol);
+                    p = p->ai_next;
+                }
+                while (p);
+            }
+            pfreeaddrinfo(result);
+        }
+        else
+        {
+            DWORD err = WSAGetLastError();
+            if (hinttests[i].error)
+                ok(hinttests[i].error == err, "test %d: getaddrinfo failed with error %d, expected %d\n",
+                   i, err, hinttests[i].error);
+            else
+                ok(0, "test %d: getaddrinfo failed with %d (err %d)\n", i, ret, err);
+        }
+    }
 }
 
 static void test_ConnectEx(void)
@@ -4384,7 +7209,7 @@ static void test_ConnectEx(void)
         "returned %d + errno %d\n", bret, WSAGetLastError());
 
     bret = pConnectEx(connector, (struct sockaddr*)&address, addrlen, NULL, 0, &bytesReturned, &overlapped);
-    todo_wine ok(bret == FALSE && WSAGetLastError() == WSAEINVAL, "ConnectEx on a unbound socket "
+    ok(bret == FALSE && WSAGetLastError() == WSAEINVAL, "ConnectEx on a unbound socket "
         "returned %d + errno %d\n", bret, WSAGetLastError());
     if (bret == TRUE || WSAGetLastError() != WSAEINVAL)
     {
@@ -4416,7 +7241,7 @@ static void test_ConnectEx(void)
     ok(bret == FALSE && WSAGetLastError() == ERROR_INVALID_PARAMETER, "ConnectEx on a NULL overlapped "
         "returned %d + errno %d\n", bret, WSAGetLastError());
 
-    overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
     if (overlapped.hEvent == NULL) {
         skip("could not create event object, errno = %d\n", GetLastError());
         goto end;
@@ -4619,10 +7444,23 @@ static void test_AcceptEx(void)
     ok(bret == FALSE && WSAGetLastError() == WSAENOTSOCK, "AcceptEx on invalid listening socket "
         "returned %d + errno %d\n", bret, WSAGetLastError());
 
+    bret = pAcceptEx(listener, acceptor, buffer, sizeof(buffer) - 2*(sizeof(struct sockaddr_in) + 16),
+        sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16,
+        &bytesReturned, &overlapped);
+todo_wine
+    ok(bret == FALSE && WSAGetLastError() == WSAEINVAL, "AcceptEx on a non-listening socket "
+        "returned %d + errno %d\n", bret, WSAGetLastError());
+
+    iret = listen(listener, 5);
+    if (iret != 0) {
+        skip("listening failed, errno = %d\n", WSAGetLastError());
+        goto end;
+    }
+
     bret = pAcceptEx(listener, INVALID_SOCKET, buffer, sizeof(buffer) - 2*(sizeof(struct sockaddr_in) + 16),
         sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16,
         &bytesReturned, &overlapped);
-    ok(bret == FALSE && WSAGetLastError() == WSAEINVAL, "AcceptEx on invalid accepting socket "
+    ok(bret == FALSE && WSAGetLastError() == WSAENOTSOCK, "AcceptEx on invalid accepting socket "
         "returned %d + errno %d\n", bret, WSAGetLastError());
 
     bret = pAcceptEx(listener, acceptor, NULL, sizeof(buffer) - 2*(sizeof(struct sockaddr_in) + 16),
@@ -4635,13 +7473,31 @@ static void test_AcceptEx(void)
 
     bret = pAcceptEx(listener, acceptor, buffer, 0, 0, sizeof(struct sockaddr_in) + 16,
         &bytesReturned, &overlapped);
-    todo_wine ok(bret == FALSE && WSAGetLastError() == WSAEINVAL, "AcceptEx on too small local address size "
-        "returned %d + errno %d\n", bret, WSAGetLastError());
+    ok(bret == FALSE && (WSAGetLastError() == ERROR_IO_PENDING || broken(WSAGetLastError() == WSAEINVAL)) /* NT4 */,
+        "AcceptEx on too small local address size returned %d + errno %d\n",
+        bret, WSAGetLastError());
+    bret = CancelIo((HANDLE) listener);
+    ok(bret, "Failed to cancel pending accept socket\n");
+
+    bret = pAcceptEx(listener, acceptor, buffer, 0, sizeof(struct sockaddr_in) + 15,
+        sizeof(struct sockaddr_in) + 16, &bytesReturned, &overlapped);
+    ok(bret == FALSE && WSAGetLastError() == ERROR_IO_PENDING, "AcceptEx on too small local address "
+        "size returned %d + errno %d\n",
+        bret, WSAGetLastError());
+    bret = CancelIo((HANDLE) listener);
+    ok(bret, "Failed to cancel pending accept socket\n");
 
     bret = pAcceptEx(listener, acceptor, buffer, 0, sizeof(struct sockaddr_in) + 16, 0,
         &bytesReturned, &overlapped);
-    todo_wine ok(bret == FALSE && WSAGetLastError() == WSAEINVAL, "AcceptEx on too small remote address size "
-        "returned %d + errno %d\n", bret, WSAGetLastError());
+    ok(bret == FALSE && (WSAGetLastError() == WSAEFAULT || broken(WSAGetLastError() == WSAEINVAL)) /* NT4 */,
+        "AcceptEx on too small remote address size returned %d + errno %d\n", bret, WSAGetLastError());
+
+    bret = pAcceptEx(listener, acceptor, buffer, 0, sizeof(struct sockaddr_in) + 16,
+        sizeof(struct sockaddr_in) + 15, &bytesReturned, &overlapped);
+    ok(bret == FALSE && (WSAGetLastError() == ERROR_IO_PENDING || broken(WSAGetLastError() == WSAEINVAL)) /* NT4 */,
+        "AcceptEx on too small remote address size returned %d + errno %d\n", bret, WSAGetLastError());
+    bret = CancelIo((HANDLE) listener);
+    ok(bret, "Failed to cancel pending accept socket\n");
 
     bret = pAcceptEx(listener, acceptor, buffer, 0,
         sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16,
@@ -4649,19 +7505,11 @@ static void test_AcceptEx(void)
     ok(bret == FALSE && WSAGetLastError() == ERROR_INVALID_PARAMETER, "AcceptEx on a NULL overlapped "
         "returned %d + errno %d\n", bret, WSAGetLastError());
 
-    bret = pAcceptEx(listener, acceptor, buffer, sizeof(buffer) - 2*(sizeof(struct sockaddr_in) + 16),
-        sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16,
-        &bytesReturned, &overlapped);
-    todo_wine ok(bret == FALSE && WSAGetLastError() == WSAEINVAL, "AcceptEx on a non-listening socket "
+    bret = pAcceptEx(listener, acceptor, buffer, 0, 0, 0, &bytesReturned, NULL);
+    ok(bret == FALSE && WSAGetLastError() == ERROR_INVALID_PARAMETER, "AcceptEx on a NULL overlapped "
         "returned %d + errno %d\n", bret, WSAGetLastError());
 
-    iret = listen(listener, 5);
-    if (iret != 0) {
-        skip("listening failed, errno = %d\n", WSAGetLastError());
-        goto end;
-    }
-
-    overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
     if (overlapped.hEvent == NULL) {
         skip("could not create event object, errno = %d\n", GetLastError());
         goto end;
@@ -4749,6 +7597,7 @@ static void test_AcceptEx(void)
     ok(!iret, "getsockopt failed %d\n", WSAGetLastError());
     ok(connect_time == ~0u, "unexpected connect time %u\n", connect_time);
 
+    /* AcceptEx() still won't complete until we send data */
     iret = connect(connector, (struct sockaddr*)&bindAddress, sizeof(bindAddress));
     ok(iret == 0, "connecting to accepting socket failed, error %d\n", WSAGetLastError());
 
@@ -4764,7 +7613,14 @@ static void test_AcceptEx(void)
     iret = getsockname( connector, (struct sockaddr *)&peerAddress, &remoteSize);
     ok( !iret, "getsockname failed.\n");
 
-    /* Check if the buffer from AcceptEx is decoded correclty */
+    /* AcceptEx() could complete any time now */
+    iret = send(connector, buffer, 1, 0);
+    ok(iret == 1, "could not send 1 byte: send %d errno %d\n", iret, WSAGetLastError());
+
+    dwret = WaitForSingleObject(overlapped.hEvent, 1000);
+    ok(dwret == WAIT_OBJECT_0, "Waiting for accept event failed with %d + errno %d\n", dwret, GetLastError());
+
+    /* Check if the buffer from AcceptEx is decoded correctly */
     pGetAcceptExSockaddrs(buffer, 2, sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16,
                           (struct sockaddr **)&readBindAddress, &localSize,
                           (struct sockaddr **)&readRemoteAddress, &remoteSize);
@@ -4783,12 +7639,6 @@ static void test_AcceptEx(void)
             "Remote socket port is different: %d != %d\n",
             readRemoteAddress->sin_port, peerAddress.sin_port);
 
-    iret = send(connector, buffer, 1, 0);
-    ok(iret == 1, "could not send 1 byte: send %d errno %d\n", iret, WSAGetLastError());
-
-    dwret = WaitForSingleObject(overlapped.hEvent, 1000);
-    ok(dwret == WAIT_OBJECT_0, "Waiting for accept event failed with %d + errno %d\n", dwret, GetLastError());
-
     bret = GetOverlappedResult((HANDLE)listener, &overlapped, &bytesReturned, FALSE);
     ok(bret, "GetOverlappedResult failed, error %d\n", GetLastError());
     ok(bytesReturned == 1, "bytesReturned isn't supposed to be %d\n", bytesReturned);
@@ -4994,37 +7844,393 @@ static void test_AcceptEx(void)
         skip("could not create acceptor socket, error %d\n", WSAGetLastError());
         goto end;
     }
-    bret = pAcceptEx(listener, acceptor, buffer, sizeof(buffer) - 2*(sizeof(struct sockaddr_in) + 16),
-        sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16,
-        &bytesReturned, &overlapped);
-    ok(bret == FALSE && WSAGetLastError() == ERROR_IO_PENDING, "AcceptEx returned %d + errno %d\n", bret, WSAGetLastError());
-
-    closesocket(listener);
-    listener = INVALID_SOCKET;
-
-    dwret = WaitForSingleObject(overlapped.hEvent, 1000);
-    ok(dwret == WAIT_OBJECT_0, "Waiting for accept event failed with %d + errno %d\n", dwret, GetLastError());
+    bret = pAcceptEx(listener, acceptor, buffer, sizeof(buffer) - 2*(sizeof(struct sockaddr_in) + 16),
+        sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16,
+        &bytesReturned, &overlapped);
+    ok(bret == FALSE && WSAGetLastError() == ERROR_IO_PENDING, "AcceptEx returned %d + errno %d\n", bret, WSAGetLastError());
+
+    closesocket(listener);
+    listener = INVALID_SOCKET;
+
+    dwret = WaitForSingleObject(overlapped.hEvent, 1000);
+    ok(dwret == WAIT_OBJECT_0, "Waiting for accept event failed with %d + errno %d\n", dwret, GetLastError());
+
+    bret = GetOverlappedResult((HANDLE)listener, &overlapped, &bytesReturned, FALSE);
+    ok(!bret && GetLastError() == ERROR_OPERATION_ABORTED, "GetOverlappedResult failed, error %d\n", GetLastError());
+
+end:
+    if (overlapped.hEvent)
+        WSACloseEvent(overlapped.hEvent);
+    if (listener != INVALID_SOCKET)
+        closesocket(listener);
+    if (acceptor != INVALID_SOCKET)
+        closesocket(acceptor);
+    if (connector != INVALID_SOCKET)
+        closesocket(connector);
+    if (connector2 != INVALID_SOCKET)
+        closesocket(connector2);
+}
+
+static void test_DisconnectEx(void)
+{
+    SOCKET listener, acceptor, connector;
+    LPFN_DISCONNECTEX pDisconnectEx;
+    GUID disconnectExGuid = WSAID_DISCONNECTEX;
+    struct sockaddr_in address;
+    DWORD num_bytes, flags;
+    OVERLAPPED overlapped;
+    int addrlen, iret;
+    BOOL bret;
+
+    connector = socket(AF_INET, SOCK_STREAM, 0);
+    ok(connector != INVALID_SOCKET, "failed to create connector socket, error %d\n", WSAGetLastError());
+
+    iret = WSAIoctl(connector, SIO_GET_EXTENSION_FUNCTION_POINTER, &disconnectExGuid, sizeof(disconnectExGuid),
+                    &pDisconnectEx, sizeof(pDisconnectEx), &num_bytes, NULL, NULL);
+    if (iret)
+    {
+        win_skip("WSAIoctl failed to get DisconnectEx, error %d\n", WSAGetLastError());
+        closesocket(connector);
+        return;
+    }
+
+    listener = socket(AF_INET, SOCK_STREAM, 0);
+    ok(listener != INVALID_SOCKET, "failed to create listener socket, error %d\n", WSAGetLastError());
+
+    memset(&address, 0, sizeof(address));
+    address.sin_family = AF_INET;
+    address.sin_addr.s_addr = inet_addr("127.0.0.1");
+    iret = bind(listener, (struct sockaddr *)&address, sizeof(address));
+    ok(iret == 0, "failed to bind, error %d\n", WSAGetLastError());
+
+    addrlen = sizeof(address);
+    iret = getsockname(listener, (struct sockaddr *)&address, &addrlen);
+    ok(iret == 0, "failed to lookup bind address, error %d\n", WSAGetLastError());
+
+    iret = listen(listener, 1);
+    ok(iret == 0, "failed to listen, error %d\n", WSAGetLastError());
+
+    set_blocking(listener, TRUE);
+
+    memset(&overlapped, 0, sizeof(overlapped));
+    bret = pDisconnectEx(INVALID_SOCKET, &overlapped, 0, 0);
+    ok(bret == FALSE, "DisconnectEx unexpectedly succeeded\n");
+    ok(WSAGetLastError() == WSAENOTSOCK, "expected WSAENOTSOCK, got %d\n", WSAGetLastError());
+
+    memset(&overlapped, 0, sizeof(overlapped));
+    bret = pDisconnectEx(connector, &overlapped, 0, 0);
+    ok(bret == FALSE, "DisconnectEx unexpectedly succeeded\n");
+    todo_wine ok(WSAGetLastError() == WSAENOTCONN, "expected WSAENOTCONN, got %d\n", WSAGetLastError());
+
+    iret = connect(connector, (struct sockaddr *)&address, addrlen);
+    ok(iret == 0, "failed to connect, error %d\n", WSAGetLastError());
+
+    acceptor = accept(listener, NULL, NULL);
+    ok(acceptor != INVALID_SOCKET, "could not accept socket, error %d\n", WSAGetLastError());
+
+    memset(&overlapped, 0, sizeof(overlapped));
+    overlapped.hEvent = WSACreateEvent();
+    ok(overlapped.hEvent != WSA_INVALID_EVENT, "WSACreateEvent failed, error %d\n", WSAGetLastError());
+    bret = pDisconnectEx(connector, &overlapped, 0, 0);
+    if (bret)
+        ok(overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %08lx\n", overlapped.Internal);
+    else if (WSAGetLastError() == ERROR_IO_PENDING)
+        bret = WSAGetOverlappedResult(connector, &overlapped, &num_bytes, TRUE, &flags);
+    ok(bret, "DisconnectEx failed, error %d\n", WSAGetLastError());
+    WSACloseEvent(overlapped.hEvent);
+
+    iret = connect(connector, (struct sockaddr *)&address, sizeof(address));
+    ok(iret != 0, "connect unexpectedly succeeded\n");
+    ok(WSAGetLastError() == WSAEISCONN, "expected WSAEISCONN, got %d\n", WSAGetLastError());
+
+    closesocket(acceptor);
+    closesocket(connector);
+
+    connector = socket(AF_INET, SOCK_STREAM, 0);
+    ok(connector != INVALID_SOCKET, "failed to create connector socket, error %d\n", WSAGetLastError());
+
+    iret = connect(connector, (struct sockaddr *)&address, addrlen);
+    ok(iret == 0, "failed to connect, error %d\n", WSAGetLastError());
+
+    acceptor = accept(listener, NULL, NULL);
+    ok(acceptor != INVALID_SOCKET, "could not accept socket, error %d\n", WSAGetLastError());
+
+    bret = pDisconnectEx(connector, NULL, 0, 0);
+    ok(bret, "DisconnectEx failed, error %d\n", WSAGetLastError());
+
+    iret = connect(connector, (struct sockaddr *)&address, sizeof(address));
+    ok(iret != 0, "connect unexpectedly succeeded\n");
+    ok(WSAGetLastError() == WSAEISCONN, "expected WSAEISCONN, got %d\n", WSAGetLastError());
+
+    closesocket(acceptor);
+    closesocket(connector);
+    closesocket(listener);
+}
+
+#define compare_file(h,s,o) compare_file2(h,s,o,__FILE__,__LINE__)
+
+static void compare_file2(HANDLE handle, SOCKET sock, int offset, const char *file, int line)
+{
+    char buf1[256], buf2[256];
+    BOOL success;
+    int i = 0;
+
+    SetFilePointer(handle, offset, NULL, FILE_BEGIN);
+    while (1)
+    {
+        DWORD n1 = 0, n2 = 0;
+
+        success = ReadFile(handle, buf1, sizeof(buf1), &n1, NULL);
+        ok_(file,line)(success, "Failed to read from file.\n");
+        if (success && n1 == 0)
+            break;
+        else if(!success)
+            return;
+        n2 = recv(sock, buf2, n1, 0);
+        ok_(file,line)(n1 == n2, "Block %d size mismatch (%d != %d)\n", i, n1, n2);
+        ok_(file,line)(memcmp(buf1, buf2, n2) == 0, "Block %d failed\n", i);
+        i++;
+    }
+}
+
+static void test_TransmitFile(void)
+{
+    DWORD num_bytes, err, file_size, total_sent;
+    GUID transmitFileGuid = WSAID_TRANSMITFILE;
+    LPFN_TRANSMITFILE pTransmitFile = NULL;
+    HANDLE file = INVALID_HANDLE_VALUE;
+    char header_msg[] = "hello world";
+    char footer_msg[] = "goodbye!!!";
+    char system_ini_path[MAX_PATH];
+    struct sockaddr_in bindAddress;
+    TRANSMIT_FILE_BUFFERS buffers;
+    SOCKET client, server, dest;
+    WSAOVERLAPPED ov;
+    char buf[256];
+    int iret, len;
+    BOOL bret;
+
+    memset( &ov, 0, sizeof(ov) );
+
+    /* Setup sockets for testing TransmitFile */
+    client = socket(AF_INET, SOCK_STREAM, 0);
+    server = socket(AF_INET, SOCK_STREAM, 0);
+    if (client == INVALID_SOCKET || server == INVALID_SOCKET)
+    {
+        skip("could not create acceptor socket, error %d\n", WSAGetLastError());
+        goto cleanup;
+    }
+    iret = WSAIoctl(client, SIO_GET_EXTENSION_FUNCTION_POINTER, &transmitFileGuid, sizeof(transmitFileGuid),
+                    &pTransmitFile, sizeof(pTransmitFile), &num_bytes, NULL, NULL);
+    if (iret)
+    {
+        skip("WSAIoctl failed to get TransmitFile with ret %d + errno %d\n", iret, WSAGetLastError());
+        goto cleanup;
+    }
+    GetSystemWindowsDirectoryA(system_ini_path, MAX_PATH );
+    strcat(system_ini_path, "\\system.ini");
+    file = CreateFileA(system_ini_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0x0, NULL);
+    if (file == INVALID_HANDLE_VALUE)
+    {
+        skip("Unable to open a file to transmit.\n");
+        goto cleanup;
+    }
+    file_size = GetFileSize(file, NULL);
+
+    /* Test TransmitFile with an invalid socket */
+    bret = pTransmitFile(INVALID_SOCKET, file, 0, 0, NULL, NULL, 0);
+    err = WSAGetLastError();
+    ok(!bret, "TransmitFile succeeded unexpectedly.\n");
+    ok(err == WSAENOTSOCK, "TransmitFile triggered unexpected errno (%d != %d)\n", err, WSAENOTSOCK);
+
+    /* Test a bogus TransmitFile without a connected socket */
+    bret = pTransmitFile(client, NULL, 0, 0, NULL, NULL, TF_REUSE_SOCKET);
+    err = WSAGetLastError();
+    ok(!bret, "TransmitFile succeeded unexpectedly.\n");
+    ok(err == WSAENOTCONN, "TransmitFile triggered unexpected errno (%d != %d)\n", err, WSAENOTCONN);
+
+    /* Setup a properly connected socket for transfers */
+    memset(&bindAddress, 0, sizeof(bindAddress));
+    bindAddress.sin_family = AF_INET;
+    bindAddress.sin_port = htons(9375);
+    bindAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
+    iret = bind(server, (struct sockaddr*)&bindAddress, sizeof(bindAddress));
+    if (iret != 0)
+    {
+        skip("failed to bind(), error %d\n", WSAGetLastError());
+        goto cleanup;
+    }
+    iret = listen(server, 1);
+    if (iret != 0)
+    {
+        skip("failed to listen(), error %d\n", WSAGetLastError());
+        goto cleanup;
+    }
+    iret = connect(client, (struct sockaddr*)&bindAddress, sizeof(bindAddress));
+    if (iret != 0)
+    {
+        skip("failed to connect(), error %d\n", WSAGetLastError());
+        goto cleanup;
+    }
+    len = sizeof(bindAddress);
+    dest = accept(server, (struct sockaddr*)&bindAddress, &len);
+    if (dest == INVALID_SOCKET)
+    {
+        skip("failed to accept(), error %d\n", WSAGetLastError());
+        goto cleanup;
+    }
+    if (set_blocking(dest, FALSE))
+    {
+        skip("couldn't make socket non-blocking, error %d\n", WSAGetLastError());
+        goto cleanup;
+    }
+
+    /* Test TransmitFile with no possible buffer */
+    bret = pTransmitFile(client, NULL, 0, 0, NULL, NULL, 0);
+    ok(bret, "TransmitFile failed unexpectedly.\n");
+    iret = recv(dest, buf, sizeof(buf), 0);
+    ok(iret == -1, "Returned an unexpected buffer from TransmitFile (%d != -1).\n", iret);
+
+    /* Test TransmitFile with only buffer data */
+    buffers.Head = &header_msg[0];
+    buffers.HeadLength = sizeof(header_msg)+1;
+    buffers.Tail = &footer_msg[0];
+    buffers.TailLength = sizeof(footer_msg)+1;
+    bret = pTransmitFile(client, NULL, 0, 0, NULL, &buffers, 0);
+    ok(bret, "TransmitFile failed unexpectedly.\n");
+    iret = recv(dest, buf, sizeof(buf), 0);
+    ok(iret == sizeof(header_msg)+sizeof(footer_msg)+2,
+       "Returned an unexpected buffer from TransmitFile: %d\n", iret );
+    ok(memcmp(&buf[0], &header_msg[0], sizeof(header_msg)+1) == 0,
+       "TransmitFile header buffer did not match!\n");
+    ok(memcmp(&buf[sizeof(header_msg)+1], &footer_msg[0], sizeof(footer_msg)+1) == 0,
+       "TransmitFile footer buffer did not match!\n");
+
+    /* Test TransmitFile with only file data */
+    bret = pTransmitFile(client, file, 0, 0, NULL, NULL, 0);
+    ok(bret, "TransmitFile failed unexpectedly.\n");
+    compare_file(file, dest, 0);
+
+    /* Test TransmitFile with both file and buffer data */
+    buffers.Head = &header_msg[0];
+    buffers.HeadLength = sizeof(header_msg)+1;
+    buffers.Tail = &footer_msg[0];
+    buffers.TailLength = sizeof(footer_msg)+1;
+    SetFilePointer(file, 0, NULL, FILE_BEGIN);
+    bret = pTransmitFile(client, file, 0, 0, NULL, &buffers, 0);
+    ok(bret, "TransmitFile failed unexpectedly.\n");
+    iret = recv(dest, buf, sizeof(header_msg)+1, 0);
+    ok(memcmp(buf, &header_msg[0], sizeof(header_msg)+1) == 0,
+       "TransmitFile header buffer did not match!\n");
+    compare_file(file, dest, 0);
+    iret = recv(dest, buf, sizeof(footer_msg)+1, 0);
+    ok(memcmp(buf, &footer_msg[0], sizeof(footer_msg)+1) == 0,
+       "TransmitFile footer buffer did not match!\n");
+
+    /* Test overlapped TransmitFile */
+    ov.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    if (ov.hEvent == INVALID_HANDLE_VALUE)
+    {
+        skip("Could not create event object, some tests will be skipped. errno = %d\n",
+             GetLastError());
+        goto cleanup;
+    }
+    SetFilePointer(file, 0, NULL, FILE_BEGIN);
+    bret = pTransmitFile(client, file, 0, 0, &ov, NULL, 0);
+    err = WSAGetLastError();
+    ok(!bret, "TransmitFile succeeded unexpectedly.\n");
+    ok(err == ERROR_IO_PENDING, "TransmitFile triggered unexpected errno (%d != %d)\n",
+       err, ERROR_IO_PENDING);
+    iret = WaitForSingleObject(ov.hEvent, 2000);
+    ok(iret == WAIT_OBJECT_0, "Overlapped TransmitFile failed.\n");
+    WSAGetOverlappedResult(client, &ov, &total_sent, FALSE, NULL);
+    ok(total_sent == file_size,
+       "Overlapped TransmitFile sent an unexpected number of bytes (%d != %d).\n",
+       total_sent, file_size);
+    compare_file(file, dest, 0);
+
+    /* Test overlapped TransmitFile w/ start offset */
+    ov.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    if (ov.hEvent == INVALID_HANDLE_VALUE)
+    {
+        skip("Could not create event object, some tests will be skipped. errno = %d\n", GetLastError());
+        goto cleanup;
+    }
+    SetFilePointer(file, 0, NULL, FILE_BEGIN);
+    ov.Offset = 10;
+    bret = pTransmitFile(client, file, 0, 0, &ov, NULL, 0);
+    err = WSAGetLastError();
+    ok(!bret, "TransmitFile succeeded unexpectedly.\n");
+    ok(err == ERROR_IO_PENDING, "TransmitFile triggered unexpected errno (%d != %d)\n", err, ERROR_IO_PENDING);
+    iret = WaitForSingleObject(ov.hEvent, 2000);
+    ok(iret == WAIT_OBJECT_0, "Overlapped TransmitFile failed.\n");
+    WSAGetOverlappedResult(client, &ov, &total_sent, FALSE, NULL);
+    ok(total_sent == (file_size - ov.Offset),
+       "Overlapped TransmitFile sent an unexpected number of bytes (%d != %d).\n",
+       total_sent, file_size - ov.Offset);
+    compare_file(file, dest, ov.Offset);
+
+    /* Test overlapped TransmitFile w/ file and buffer data */
+    ov.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    if (ov.hEvent == INVALID_HANDLE_VALUE)
+    {
+        skip("Could not create event object, some tests will be skipped. errno = %d\n", GetLastError());
+        goto cleanup;
+    }
+    buffers.Head = &header_msg[0];
+    buffers.HeadLength = sizeof(header_msg)+1;
+    buffers.Tail = &footer_msg[0];
+    buffers.TailLength = sizeof(footer_msg)+1;
+    SetFilePointer(file, 0, NULL, FILE_BEGIN);
+    ov.Offset = 0;
+    bret = pTransmitFile(client, file, 0, 0, &ov, &buffers, 0);
+    err = WSAGetLastError();
+    ok(!bret, "TransmitFile succeeded unexpectedly.\n");
+    ok(err == ERROR_IO_PENDING, "TransmitFile triggered unexpected errno (%d != %d)\n", err, ERROR_IO_PENDING);
+    iret = WaitForSingleObject(ov.hEvent, 2000);
+    ok(iret == WAIT_OBJECT_0, "Overlapped TransmitFile failed.\n");
+    WSAGetOverlappedResult(client, &ov, &total_sent, FALSE, NULL);
+    ok(total_sent == (file_size + buffers.HeadLength + buffers.TailLength),
+       "Overlapped TransmitFile sent an unexpected number of bytes (%d != %d).\n",
+       total_sent, file_size  + buffers.HeadLength + buffers.TailLength);
+    iret = recv(dest, buf, sizeof(header_msg)+1, 0);
+    ok(memcmp(buf, &header_msg[0], sizeof(header_msg)+1) == 0,
+       "TransmitFile header buffer did not match!\n");
+    compare_file(file, dest, 0);
+    iret = recv(dest, buf, sizeof(footer_msg)+1, 0);
+    ok(memcmp(buf, &footer_msg[0], sizeof(footer_msg)+1) == 0,
+       "TransmitFile footer buffer did not match!\n");
+
+    /* Test TransmitFile w/ TF_DISCONNECT */
+    SetFilePointer(file, 0, NULL, FILE_BEGIN);
+    bret = pTransmitFile(client, file, 0, 0, NULL, NULL, TF_DISCONNECT);
+    ok(bret, "TransmitFile failed unexpectedly.\n");
+    compare_file(file, dest, 0);
+    closesocket(client);
+    ok(send(client, "test", 4, 0) == -1, "send() after TF_DISCONNECT succeeded unexpectedly.\n");
+    err = WSAGetLastError();
+    todo_wine ok(err == WSAENOTSOCK, "send() after TF_DISCONNECT triggered unexpected errno (%d != %d)\n",
+                 err, WSAENOTSOCK);
 
-    bret = GetOverlappedResult((HANDLE)listener, &overlapped, &bytesReturned, FALSE);
-    ok(!bret && GetLastError() == ERROR_OPERATION_ABORTED, "GetOverlappedResult failed, error %d\n", GetLastError());
+    /* Test TransmitFile with a UDP datagram socket */
+    client = socket(AF_INET, SOCK_DGRAM, 0);
+    bret = pTransmitFile(client, NULL, 0, 0, NULL, NULL, 0);
+    err = WSAGetLastError();
+    ok(!bret, "TransmitFile succeeded unexpectedly.\n");
+    ok(err == WSAENOTCONN, "TransmitFile triggered unexpected errno (%d != %d)\n", err, WSAENOTCONN);
 
-end:
-    if (overlapped.hEvent)
-        WSACloseEvent(overlapped.hEvent);
-    if (listener != INVALID_SOCKET)
-        closesocket(listener);
-    if (acceptor != INVALID_SOCKET)
-        closesocket(acceptor);
-    if (connector != INVALID_SOCKET)
-        closesocket(connector);
-    if (connector2 != INVALID_SOCKET)
-        closesocket(connector2);
+cleanup:
+    CloseHandle(file);
+    CloseHandle(ov.hEvent);
+    closesocket(client);
+    closesocket(server);
 }
 
 static void test_getpeername(void)
 {
     SOCKET sock;
     struct sockaddr_in sa, sa_out;
+    SOCKADDR_STORAGE ss;
     int sa_len;
     const char buf[] = "hello world";
     int ret;
@@ -5083,17 +8289,31 @@ static void test_getpeername(void)
            "Expected WSAGetLastError() to return WSAEFAULT, got %d\n", WSAGetLastError());
     }
 
+    ret = getpeername(sock, (struct sockaddr*)&sa_out, NULL);
+    ok(ret == SOCKET_ERROR, "Expected getpeername to return 0, got %d\n", ret);
+    ok(WSAGetLastError() == WSAEFAULT,
+       "Expected WSAGetLastError() to return WSAEFAULT, got %d\n", WSAGetLastError());
+
+    sa_len = 0;
+    ret = getpeername(sock, NULL, &sa_len);
+    ok(ret == SOCKET_ERROR, "Expected getpeername to return 0, got %d\n", ret);
+    ok(WSAGetLastError() == WSAEFAULT,
+       "Expected WSAGetLastError() to return WSAEFAULT, got %d\n", WSAGetLastError());
+    ok(!sa_len, "got %d\n", sa_len);
+
     sa_len = 0;
-    ret = getpeername(sock, (struct sockaddr*)&sa_out, &sa_len);
+    ret = getpeername(sock, (struct sockaddr *)&ss, &sa_len);
     ok(ret == SOCKET_ERROR, "Expected getpeername to return 0, got %d\n", ret);
     ok(WSAGetLastError() == WSAEFAULT,
        "Expected WSAGetLastError() to return WSAEFAULT, got %d\n", WSAGetLastError());
+    ok(!sa_len, "got %d\n", sa_len);
 
-    sa_len = sizeof(sa_out);
-    ret = getpeername(sock, (struct sockaddr*)&sa_out, &sa_len);
+    sa_len = sizeof(ss);
+    ret = getpeername(sock, (struct sockaddr *)&ss, &sa_len);
     ok(ret == 0, "Expected getpeername to return 0, got %d\n", ret);
-    ok(!memcmp(&sa, &sa_out, sizeof(sa)),
+    ok(!memcmp(&sa, &ss, sizeof(sa)),
        "Expected the returned structure to be identical to the connect structure\n");
+    ok(sa_len == sizeof(sa), "got %d\n", sa_len);
 
     closesocket(sock);
 }
@@ -5159,6 +8379,73 @@ static void test_sioRoutingInterfaceQuery(void)
     closesocket(sock);
 }
 
+static void test_sioAddressListChange(void)
+{
+    struct sockaddr_in bindAddress;
+    struct in_addr net_address;
+    WSAOVERLAPPED overlapped;
+    struct hostent *h;
+    DWORD num_bytes;
+    SOCKET sock;
+    int acount;
+    int ret;
+
+    if (!winetest_interactive)
+    {
+        skip("Cannot test SIO_ADDRESS_LIST_CHANGE, interactive tests must be enabled\n");
+        return;
+    }
+
+    /* Use gethostbyname to find the list of local network interfaces */
+    h = gethostbyname("");
+    if (!h)
+    {
+        skip("Cannot test SIO_ADDRESS_LIST_CHANGE, gethostbyname failed with %u\n",
+             WSAGetLastError());
+        return;
+    }
+    for (acount = 0; h->h_addr_list[acount]; acount++);
+    if (acount == 0)
+    {
+        skip("Cannot test SIO_ADDRESS_LIST_CHANGE, test requires a network card.\n");
+        return;
+    }
+    net_address.s_addr = *(ULONG *) h->h_addr_list[0];
+
+    /* Bind an overlapped socket to the first found network interface */
+    sock = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
+    ok(sock != INVALID_SOCKET, "Expected socket to return a valid socket\n");
+    if (sock == INVALID_SOCKET)
+    {
+        skip("Cannot test SIO_ADDRESS_LIST_CHANGE, socket creation failed with %u\n",
+             WSAGetLastError());
+        return;
+    }
+    memset(&bindAddress, 0, sizeof(bindAddress));
+    bindAddress.sin_family = AF_INET;
+    bindAddress.sin_addr.s_addr = net_address.s_addr;
+    ret = bind(sock, (struct sockaddr*)&bindAddress, sizeof(bindAddress));
+    if (ret != 0)
+    {
+        skip("Cannot test SIO_ADDRESS_LIST_CHANGE, failed to bind, error %u\n", WSAGetLastError());
+        goto end;
+    }
+
+    /* Wait for address changes, request that the user connects/disconnects an interface */
+    memset(&overlapped, 0, sizeof(overlapped));
+    overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
+    ret = WSAIoctl(sock, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &num_bytes, &overlapped, NULL);
+    ok(ret == SOCKET_ERROR, "WSAIoctl succeeded unexpectedly\n");
+    ok(WSAGetLastError() == WSA_IO_PENDING, "Expected pending last error %d\n", WSAGetLastError());
+    trace("Testing socket-based ipv4 address list change notification. Please connect/disconnect or"
+          " change the ipv4 address of any of the local network interfaces (10 second timeout).\n");
+    ret = WaitForSingleObject(overlapped.hEvent, 10000);
+    ok(ret == WAIT_OBJECT_0, "failed to get overlapped event %u\n", ret);
+
+end:
+    closesocket(sock);
+}
+
 static void test_synchronous_WSAIoctl(void)
 {
     HANDLE previous_port, io_port;
@@ -5206,16 +8493,16 @@ static HWND create_async_message_window(void)
     wndclass.cbClsExtra     = 0;
     wndclass.cbWndExtra     = 0;
     wndclass.hInstance      = GetModuleHandleA(NULL);
-    wndclass.hIcon          = LoadIconA(NULL, IDI_APPLICATION);
-    wndclass.hIconSm        = LoadIconA(NULL, IDI_APPLICATION);
-    wndclass.hCursor        = LoadCursorA(NULL, IDC_ARROW);
+    wndclass.hIcon          = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
+    wndclass.hIconSm        = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
+    wndclass.hCursor        = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
     wndclass.hbrBackground  = (HBRUSH)(COLOR_WINDOW + 1);
     wndclass.lpszClassName  = class_name;
     wndclass.lpszMenuName   = NULL;
 
     RegisterClassExA(&wndclass);
 
-    hWnd = CreateWindow(class_name, "ws2_32 async message window", WS_OVERLAPPEDWINDOW,
+    hWnd = CreateWindowA(class_name, "ws2_32 async message window", WS_OVERLAPPEDWINDOW,
                         0, 0, 500, 500, NULL, NULL, GetModuleHandleA(NULL), NULL);
     if (!hWnd)
     {
@@ -5226,6 +8513,22 @@ static HWND create_async_message_window(void)
     return hWnd;
 }
 
+static void wait_for_async_message(HWND hwnd, HANDLE handle)
+{
+    BOOL ret;
+    MSG msg;
+
+    while ((ret = GetMessageA(&msg, 0, 0, 0)) &&
+           !(msg.hwnd == hwnd && msg.message == WM_ASYNCCOMPLETE))
+    {
+        TranslateMessage(&msg);
+        DispatchMessageA(&msg);
+    }
+
+    ok(ret, "did not expect WM_QUIT message\n");
+    ok(msg.wParam == (WPARAM)handle, "expected wParam = %p, got %lx\n", handle, msg.wParam);
+}
+
 static void test_WSAAsyncGetServByPort(void)
 {
     HWND hwnd = create_async_message_window();
@@ -5243,12 +8546,15 @@ static void test_WSAAsyncGetServByPort(void)
 
     ret = WSAAsyncGetServByPort(hwnd, WM_ASYNCCOMPLETE, 0, NULL, NULL, 0);
     ok(ret != NULL, "WSAAsyncGetServByPort returned NULL\n");
+    wait_for_async_message(hwnd, ret);
 
     ret = WSAAsyncGetServByPort(hwnd, WM_ASYNCCOMPLETE, htons(80), NULL, NULL, 0);
     ok(ret != NULL, "WSAAsyncGetServByPort returned NULL\n");
+    wait_for_async_message(hwnd, ret);
 
     ret = WSAAsyncGetServByPort(hwnd, WM_ASYNCCOMPLETE, htons(80), NULL, buffer, MAXGETHOSTSTRUCT);
     ok(ret != NULL, "WSAAsyncGetServByPort returned NULL\n");
+    wait_for_async_message(hwnd, ret);
 
     DestroyWindow(hwnd);
 }
@@ -5267,15 +8573,19 @@ static void test_WSAAsyncGetServByName(void)
     /* Parameters are not checked when initiating the asynchronous operation.  */
     ret = WSAAsyncGetServByName(hwnd, WM_ASYNCCOMPLETE, "", NULL, NULL, 0);
     ok(ret != NULL, "WSAAsyncGetServByName returned NULL\n");
+    wait_for_async_message(hwnd, ret);
 
     ret = WSAAsyncGetServByName(hwnd, WM_ASYNCCOMPLETE, "", "", buffer, MAXGETHOSTSTRUCT);
     ok(ret != NULL, "WSAAsyncGetServByName returned NULL\n");
+    wait_for_async_message(hwnd, ret);
 
     ret = WSAAsyncGetServByName(hwnd, WM_ASYNCCOMPLETE, "http", NULL, NULL, 0);
     ok(ret != NULL, "WSAAsyncGetServByName returned NULL\n");
+    wait_for_async_message(hwnd, ret);
 
     ret = WSAAsyncGetServByName(hwnd, WM_ASYNCCOMPLETE, "http", "tcp", buffer, MAXGETHOSTSTRUCT);
     ok(ret != NULL, "WSAAsyncGetServByName returned NULL\n");
+    wait_for_async_message(hwnd, ret);
 
     DestroyWindow(hwnd);
 }
@@ -5349,6 +8659,7 @@ static void test_completion_port(void)
     GUID acceptExGuid = WSAID_ACCEPTEX;
     LPFN_ACCEPTEX pAcceptEx = NULL;
 
+    memset(buf, 0, sizeof(buf));
     previous_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
     ok( previous_port != NULL, "Failed to create completion port %u\n", GetLastError());
 
@@ -5379,6 +8690,8 @@ static void test_completion_port(void)
     ok(iret == SOCKET_ERROR, "WSARecv returned %d\n", iret);
     ok(GetLastError() == ERROR_IO_PENDING, "Last error was %d\n", GetLastError());
 
+    Sleep(100);
+
     closesocket(src);
     src = INVALID_SOCKET;
 
@@ -5408,8 +8721,6 @@ static void test_completion_port(void)
 
     if (dest != INVALID_SOCKET)
         closesocket(dest);
-    if (src != INVALID_SOCKET)
-        closesocket(src);
 
     memset(&ov, 0, sizeof(ov));
 
@@ -5436,6 +8747,9 @@ static void test_completion_port(void)
 
     closesocket(src);
     src = INVALID_SOCKET;
+
+    Sleep(100);
+
     num_bytes = 0xdeadbeef;
     SetLastError(0xdeadbeef);
 
@@ -5500,11 +8814,11 @@ static void test_completion_port(void)
 
     bret = GetQueuedCompletionStatus(io_port, &num_bytes, &key, &olp, 100);
     ok(bret == FALSE, "failed to get completion status %u\n", bret);
-    todo_wine ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
-    todo_wine ok(key == 125, "Key is %lu\n", key);
-    todo_wine ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
-    todo_wine ok(olp == &ov, "Overlapped structure is at %p\n", olp);
-    todo_wine ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
+    ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
+    ok(key == 125, "Key is %lu\n", key);
+    ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
+    ok(olp == &ov, "Overlapped structure is at %p\n", olp);
+    ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
 
     SetLastError(0xdeadbeef);
     key = 0xdeadbeef;
@@ -5543,11 +8857,11 @@ static void test_completion_port(void)
 
     bret = GetQueuedCompletionStatus(io_port, &num_bytes, &key, &olp, 100);
     ok(bret == FALSE, "failed to get completion status %u\n", bret);
-    todo_wine ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
-    todo_wine ok(key == 125, "Key is %lu\n", key);
-    todo_wine ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
-    todo_wine ok(olp == &ov, "Overlapped structure is at %p\n", olp);
-    todo_wine ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
+    ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
+    ok(key == 125, "Key is %lu\n", key);
+    ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
+    ok(olp == &ov, "Overlapped structure is at %p\n", olp);
+    ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
 
     SetLastError(0xdeadbeef);
     key = 0xdeadbeef;
@@ -5570,8 +8884,8 @@ static void test_completion_port(void)
     io_port = CreateIoCompletionPort((HANDLE)src, previous_port, 125, 0);
     ok(io_port != NULL, "failed to create completion port %u\n", GetLastError());
 
-    WSADuplicateSocket( src, GetCurrentProcessId(), &info );
-    dup = WSASocket(AF_INET, SOCK_STREAM, 0, &info, 0, WSA_FLAG_OVERLAPPED);
+    WSADuplicateSocketA( src, GetCurrentProcessId(), &info );
+    dup = WSASocketA(AF_INET, SOCK_STREAM, 0, &info, 0, WSA_FLAG_OVERLAPPED);
     ok(dup != INVALID_SOCKET, "failed to duplicate socket!\n");
 
     bret = pAcceptEx(dup, dest, buf, sizeof(buf) - 2*(sizeof(struct sockaddr_in) + 16),
@@ -5602,11 +8916,11 @@ static void test_completion_port(void)
     olp = (WSAOVERLAPPED *)0xdeadbeef;
     bret = GetQueuedCompletionStatus(io_port, &num_bytes, &key, &olp, 100);
     ok(bret == FALSE, "failed to get completion status %u\n", bret);
-    todo_wine ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
-    todo_wine ok(key == 125, "Key is %lu\n", key);
-    todo_wine ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
-    todo_wine ok(olp == &ov, "Overlapped structure is at %p\n", olp);
-    todo_wine ok(olp && olp->Internal == (ULONG)STATUS_CANCELLED, "Internal status is %lx\n", olp ? olp->Internal : 0);
+    ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
+    ok(key == 125, "Key is %lu\n", key);
+    ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
+    ok(olp == &ov, "Overlapped structure is at %p\n", olp);
+    ok(olp && olp->Internal == (ULONG)STATUS_CANCELLED, "Internal status is %lx\n", olp ? olp->Internal : 0);
 
     SetLastError(0xdeadbeef);
     key = 0xdeadbeef;
@@ -5629,8 +8943,8 @@ static void test_completion_port(void)
     io_port = CreateIoCompletionPort((HANDLE)src, previous_port, 125, 0);
     ok(io_port != NULL, "failed to create completion port %u\n", GetLastError());
 
-    WSADuplicateSocket( src, GetCurrentProcessId(), &info );
-    dup = WSASocket(AF_INET, SOCK_STREAM, 0, &info, 0, WSA_FLAG_OVERLAPPED);
+    WSADuplicateSocketA( src, GetCurrentProcessId(), &info );
+    dup = WSASocketA(AF_INET, SOCK_STREAM, 0, &info, 0, WSA_FLAG_OVERLAPPED);
     ok(dup != INVALID_SOCKET, "failed to duplicate socket!\n");
 
     bret = pAcceptEx(dup, dest, buf, sizeof(buf) - 2*(sizeof(struct sockaddr_in) + 16),
@@ -5669,11 +8983,11 @@ static void test_completion_port(void)
 
     bret = GetQueuedCompletionStatus(io_port, &num_bytes, &key, &olp, 100);
     ok(bret == FALSE, "failed to get completion status %u\n", bret);
-    todo_wine ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
-    todo_wine ok(key == 125, "Key is %lu\n", key);
-    todo_wine ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
-    todo_wine ok(olp == &ov, "Overlapped structure is at %p\n", olp);
-    todo_wine ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
+    ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
+    ok(key == 125, "Key is %lu\n", key);
+    ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
+    ok(olp == &ov, "Overlapped structure is at %p\n", olp);
+    ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
 
     SetLastError(0xdeadbeef);
     key = 0xdeadbeef;
@@ -5696,8 +9010,8 @@ static void test_completion_port(void)
     io_port = CreateIoCompletionPort((HANDLE)src, previous_port, 125, 0);
     ok(io_port != NULL, "failed to create completion port %u\n", GetLastError());
 
-    WSADuplicateSocket( src, GetCurrentProcessId(), &info );
-    dup = WSASocket(AF_INET, SOCK_STREAM, 0, &info, 0, WSA_FLAG_OVERLAPPED);
+    WSADuplicateSocketA( src, GetCurrentProcessId(), &info );
+    dup = WSASocketA(AF_INET, SOCK_STREAM, 0, &info, 0, WSA_FLAG_OVERLAPPED);
     ok(dup != INVALID_SOCKET, "failed to duplicate socket!\n");
 
     bret = pAcceptEx(dup, dest, buf, sizeof(buf) - 2*(sizeof(struct sockaddr_in) + 16),
@@ -5725,11 +9039,11 @@ static void test_completion_port(void)
 
     bret = GetQueuedCompletionStatus(io_port, &num_bytes, &key, &olp, 100);
     ok(bret == FALSE, "failed to get completion status %u\n", bret);
-    todo_wine ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
-    todo_wine ok(key == 125, "Key is %lu\n", key);
-    todo_wine ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
-    todo_wine ok(olp == &ov, "Overlapped structure is at %p\n", olp);
-    todo_wine ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
+    ok(GetLastError() == ERROR_OPERATION_ABORTED, "Last error was %d\n", GetLastError());
+    ok(key == 125, "Key is %lu\n", key);
+    ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
+    ok(olp == &ov, "Overlapped structure is at %p\n", olp);
+    ok(olp && (olp->Internal == (ULONG)STATUS_CANCELLED), "Internal status is %lx\n", olp ? olp->Internal : 0);
 
     SetLastError(0xdeadbeef);
     key = 0xdeadbeef;
@@ -5860,6 +9174,8 @@ static void test_completion_port(void)
     iret = send(connector, buf, 1, 0);
     ok(iret == 1, "could not send 1 byte: send %d errno %d\n", iret, WSAGetLastError());
 
+    Sleep(100);
+
     closesocket(dest);
     dest = INVALID_SOCKET;
 
@@ -5935,12 +9251,19 @@ static void test_completion_port(void)
 
     bret = GetQueuedCompletionStatus(io_port, &num_bytes, &key, &olp, 100);
     ok(bret == FALSE, "failed to get completion status %u\n", bret);
-    todo_wine ok((GetLastError() == ERROR_NETNAME_DELETED) || (GetLastError() == ERROR_CONNECTION_ABORTED), "Last error was %d\n", GetLastError());
+    todo_wine ok(GetLastError() == ERROR_NETNAME_DELETED ||
+                 GetLastError() == ERROR_OPERATION_ABORTED ||
+                 GetLastError() == ERROR_CONNECTION_ABORTED ||
+                 GetLastError() == ERROR_PIPE_NOT_CONNECTED /* win 2000 */,
+                 "Last error was %d\n", GetLastError());
     ok(key == 125, "Key is %lu\n", key);
     ok(num_bytes == 0, "Number of bytes transferred is %u\n", num_bytes);
     ok(olp == &ov, "Overlapped structure is at %p\n", olp);
-    todo_wine ok(olp && ((olp->Internal == (ULONG)STATUS_LOCAL_DISCONNECT)
-                      || (olp->Internal == (ULONG)STATUS_CONNECTION_ABORTED)), "Internal status is %lx\n", olp ? olp->Internal : 0);
+    todo_wine ok(olp && (olp->Internal == (ULONG)STATUS_LOCAL_DISCONNECT ||
+                         olp->Internal == (ULONG)STATUS_CANCELLED ||
+                         olp->Internal == (ULONG)STATUS_CONNECTION_ABORTED ||
+                         olp->Internal == (ULONG)STATUS_PIPE_DISCONNECTED /* win 2000 */),
+                         "Internal status is %lx\n", olp ? olp->Internal : 0);
 
     SetLastError(0xdeadbeef);
     key = 0xdeadbeef;
@@ -5964,6 +9287,448 @@ static void test_completion_port(void)
     CloseHandle(previous_port);
 }
 
+#if CORE_12000_IS_FIXED /* CORE-12000 */
+/* WSHIoctl is not supported by wshtcpip.dll and crashes. Test should be fixed also! */
+static void test_address_list_query(void)
+{
+    SOCKET_ADDRESS_LIST *address_list;
+    DWORD bytes_returned, size;
+    unsigned int i;
+    SOCKET s;
+    int ret;
+
+    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    ok(s != INVALID_SOCKET, "Failed to create socket, error %d.\n", WSAGetLastError());
+
+    bytes_returned = 0;
+    ret = WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0, &bytes_returned, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "Got unexpected ret %d.\n", ret);
+    if(WSAGetLastError() == WSAEINVAL)
+    {
+      win_skip("Windows <= NT4 is not supported in this test\n");
+      closesocket(s);
+      return;
+    }
+    ok(WSAGetLastError() == WSAEFAULT, "Got unexpected error %d.\n", WSAGetLastError());
+    ok(bytes_returned >= FIELD_OFFSET(SOCKET_ADDRESS_LIST, Address[0]),
+            "Got unexpected bytes_returned %u.\n", bytes_returned);
+
+    size = bytes_returned;
+    bytes_returned = 0;
+    address_list = HeapAlloc(GetProcessHeap(), 0, size * 2);
+    ret = WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, address_list, size * 2, &bytes_returned, NULL, NULL);
+    ok(!ret, "Got unexpected ret %d, error %d.\n", ret, WSAGetLastError());
+    ok(bytes_returned == size, "Got unexpected bytes_returned %u, expected %u.\n", bytes_returned, size);
+
+    bytes_returned = FIELD_OFFSET(SOCKET_ADDRESS_LIST, Address[address_list->iAddressCount]);
+    for (i = 0; i < address_list->iAddressCount; ++i)
+    {
+        bytes_returned += address_list->Address[i].iSockaddrLength;
+    }
+    ok(size == bytes_returned, "Got unexpected size %u, expected %u.\n", size, bytes_returned);
+
+    ret = WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, address_list, size, NULL, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "Got unexpected ret %d.\n", ret);
+    ok(WSAGetLastError() == WSAEFAULT, "Got unexpected error %d.\n", WSAGetLastError());
+
+    bytes_returned = 0xdeadbeef;
+    ret = WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, size, &bytes_returned, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "Got unexpected ret %d.\n", ret);
+    ok(WSAGetLastError() == WSAEFAULT, "Got unexpected error %d.\n", WSAGetLastError());
+    ok(bytes_returned == size, "Got unexpected bytes_returned %u, expected %u.\n", bytes_returned, size);
+
+    ret = WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, address_list, 1, &bytes_returned, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "Got unexpected ret %d.\n", ret);
+    ok(WSAGetLastError() == WSAEINVAL, "Got unexpected error %d.\n", WSAGetLastError());
+    ok(bytes_returned == 0, "Got unexpected bytes_returned %u.\n", bytes_returned);
+
+    ret = WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, address_list,
+            FIELD_OFFSET(SOCKET_ADDRESS_LIST, Address[0]), &bytes_returned, NULL, NULL);
+    ok(ret == SOCKET_ERROR, "Got unexpected ret %d.\n", ret);
+    ok(WSAGetLastError() == WSAEFAULT, "Got unexpected error %d.\n", WSAGetLastError());
+    ok(bytes_returned == size, "Got unexpected bytes_returned %u, expected %u.\n", bytes_returned, size);
+
+    HeapFree(GetProcessHeap(), 0, address_list);
+    closesocket(s);
+}
+#endif /* CORE-12000 */
+
+static DWORD WINAPI inet_ntoa_thread_proc(void *param)
+{
+    ULONG addr;
+    const char *str;
+    HANDLE *event = param;
+
+    addr = inet_addr("4.3.2.1");
+    ok(addr == htonl(0x04030201), "expected 0x04030201, got %08x\n", addr);
+    str = inet_ntoa(*(struct in_addr *)&addr);
+    ok(!strcmp(str, "4.3.2.1"), "expected 4.3.2.1, got %s\n", str);
+
+    SetEvent(event[0]);
+    WaitForSingleObject(event[1], 3000);
+
+    return 0;
+}
+
+static void test_inet_ntoa(void)
+{
+    ULONG addr;
+    const char *str;
+    HANDLE thread, event[2];
+    DWORD tid;
+
+    addr = inet_addr("1.2.3.4");
+    ok(addr == htonl(0x01020304), "expected 0x01020304, got %08x\n", addr);
+    str = inet_ntoa(*(struct in_addr *)&addr);
+    ok(!strcmp(str, "1.2.3.4"), "expected 1.2.3.4, got %s\n", str);
+
+    event[0] = CreateEventW(NULL, TRUE, FALSE, NULL);
+    event[1] = CreateEventW(NULL, TRUE, FALSE, NULL);
+
+    thread = CreateThread(NULL, 0, inet_ntoa_thread_proc, event, 0, &tid);
+    WaitForSingleObject(event[0], 3000);
+
+    ok(!strcmp(str, "1.2.3.4"), "expected 1.2.3.4, got %s\n", str);
+
+    SetEvent(event[1]);
+    WaitForSingleObject(thread, 3000);
+
+    CloseHandle(event[0]);
+    CloseHandle(event[1]);
+    CloseHandle(thread);
+}
+
+static void test_WSALookupService(void)
+{
+    char buffer[4096], strbuff[128];
+    WSAQUERYSETW *qs = NULL;
+    HANDLE hnd;
+    PNLA_BLOB netdata;
+    int ret;
+    DWORD error, offset, bsize;
+
+    if (!pWSALookupServiceBeginW || !pWSALookupServiceEnd || !pWSALookupServiceNextW)
+    {
+        win_skip("WSALookupServiceBeginW or WSALookupServiceEnd or WSALookupServiceNextW not found\n");
+        return;
+    }
+
+    qs = (WSAQUERYSETW *)buffer;
+    memset(qs, 0, sizeof(*qs));
+
+    /* invalid parameter tests */
+    ret = pWSALookupServiceBeginW(NULL, 0, &hnd);
+    error = WSAGetLastError();
+    ok(ret == SOCKET_ERROR, "WSALookupServiceBeginW should have failed\n");
+todo_wine
+    ok(error == WSAEFAULT, "expected 10014, got %d\n", error);
+
+    ret = pWSALookupServiceBeginW(qs, 0, NULL);
+    error = WSAGetLastError();
+    ok(ret == SOCKET_ERROR, "WSALookupServiceBeginW should have failed\n");
+todo_wine
+    ok(error == WSAEFAULT, "expected 10014, got %d\n", error);
+
+    ret = pWSALookupServiceBeginW(qs, 0, &hnd);
+    error = WSAGetLastError();
+    ok(ret == SOCKET_ERROR, "WSALookupServiceBeginW should have failed\n");
+todo_wine
+    ok(error == WSAEINVAL
+       || broken(error == ERROR_INVALID_PARAMETER) /* == XP */
+       || broken(error == WSAEFAULT) /* == NT */
+       || broken(error == WSASERVICE_NOT_FOUND) /* == 2000 */,
+       "expected 10022, got %d\n", error);
+
+    ret = pWSALookupServiceEnd(NULL);
+    error = WSAGetLastError();
+todo_wine
+    ok(ret == SOCKET_ERROR, "WSALookupServiceEnd should have failed\n");
+todo_wine
+    ok(error == ERROR_INVALID_HANDLE, "expected 6, got %d\n", error);
+
+    /* standard network list query */
+    qs->dwSize = sizeof(*qs);
+    hnd = (HANDLE)0xdeadbeef;
+    ret = pWSALookupServiceBeginW(qs, LUP_RETURN_ALL | LUP_DEEP, &hnd);
+    error = WSAGetLastError();
+    if(ret && error == ERROR_INVALID_PARAMETER)
+    {
+        win_skip("the current WSALookupServiceBeginW test is not supported in win <= 2000\n");
+        return;
+    }
+
+todo_wine
+    ok(!ret, "WSALookupServiceBeginW failed unexpectedly with error %d\n", error);
+todo_wine
+    ok(hnd != (HANDLE)0xdeadbeef, "Handle was not filled\n");
+
+    offset = 0;
+    do
+    {
+        memset(qs, 0, sizeof(*qs));
+        bsize = sizeof(buffer);
+
+        if (pWSALookupServiceNextW(hnd, 0, &bsize, qs) == SOCKET_ERROR)
+        {
+            error = WSAGetLastError();
+            if (error == WSA_E_NO_MORE) break;
+            ok(0, "Error %d happened while listing services\n", error);
+            break;
+        }
+
+        WideCharToMultiByte(CP_ACP, 0, qs->lpszServiceInstanceName, -1,
+                            strbuff, sizeof(strbuff), NULL, NULL);
+        trace("Network Name: %s\n", strbuff);
+
+        /* network data is written in the blob field */
+        if (qs->lpBlob)
+        {
+            /* each network may have multiple NLA_BLOB information structures */
+            do
+            {
+                netdata = (PNLA_BLOB) &qs->lpBlob->pBlobData[offset];
+                switch (netdata->header.type)
+                {
+                    case NLA_RAW_DATA:
+                        trace("\tNLA Data Type: NLA_RAW_DATA\n");
+                        break;
+                    case NLA_INTERFACE:
+                        trace("\tNLA Data Type: NLA_INTERFACE\n");
+                        trace("\t\tType: %d\n", netdata->data.interfaceData.dwType);
+                        trace("\t\tSpeed: %d\n", netdata->data.interfaceData.dwSpeed);
+                        trace("\t\tAdapter Name: %s\n", netdata->data.interfaceData.adapterName);
+                        break;
+                    case NLA_802_1X_LOCATION:
+                        trace("\tNLA Data Type: NLA_802_1X_LOCATION\n");
+                        trace("\t\tInformation: %s\n", netdata->data.locationData.information);
+                        break;
+                    case NLA_CONNECTIVITY:
+                        switch (netdata->data.connectivity.type)
+                        {
+                            case NLA_NETWORK_AD_HOC:
+                                trace("\t\tNetwork Type: AD HOC\n");
+                                break;
+                            case NLA_NETWORK_MANAGED:
+                                trace("\t\tNetwork Type: Managed\n");
+                                break;
+                            case NLA_NETWORK_UNMANAGED:
+                                trace("\t\tNetwork Type: Unmanaged\n");
+                                break;
+                            case NLA_NETWORK_UNKNOWN:
+                                trace("\t\tNetwork Type: Unknown\n");
+                        }
+                        switch (netdata->data.connectivity.internet)
+                        {
+                            case NLA_INTERNET_NO:
+                                trace("\t\tInternet connectivity: No\n");
+                                break;
+                            case NLA_INTERNET_YES:
+                                trace("\t\tInternet connectivity: Yes\n");
+                                break;
+                            case NLA_INTERNET_UNKNOWN:
+                                trace("\t\tInternet connectivity: Unknown\n");
+                                break;
+                        }
+                        break;
+                    case NLA_ICS:
+                        trace("\tNLA Data Type: NLA_ICS\n");
+                        trace("\t\tSpeed: %d\n",
+                               netdata->data.ICS.remote.speed);
+                        trace("\t\tType: %d\n",
+                               netdata->data.ICS.remote.type);
+                        trace("\t\tState: %d\n",
+                               netdata->data.ICS.remote.state);
+                        WideCharToMultiByte(CP_ACP, 0, netdata->data.ICS.remote.machineName, -1,
+                            strbuff, sizeof(strbuff), NULL, NULL);
+                        trace("\t\tMachine Name: %s\n", strbuff);
+                        WideCharToMultiByte(CP_ACP, 0, netdata->data.ICS.remote.sharedAdapterName, -1,
+                            strbuff, sizeof(strbuff), NULL, NULL);
+                        trace("\t\tShared Adapter Name: %s\n", strbuff);
+                        break;
+                    default:
+                        trace("\tNLA Data Type: Unknown\n");
+                        break;
+                }
+            }
+            while (offset);
+        }
+    }
+    while (1);
+
+    ret = pWSALookupServiceEnd(hnd);
+    ok(!ret, "WSALookupServiceEnd failed unexpectedly\n");
+}
+
+static void test_WSAEnumNameSpaceProvidersA(void)
+{
+    LPWSANAMESPACE_INFOA name = NULL;
+    DWORD ret, error, blen = 0, i;
+    if (!pWSAEnumNameSpaceProvidersA)
+    {
+        win_skip("WSAEnumNameSpaceProvidersA not found\n");
+        return;
+    }
+
+    SetLastError(0xdeadbeef);
+    ret = pWSAEnumNameSpaceProvidersA(&blen, name);
+    error = WSAGetLastError();
+todo_wine
+    ok(ret == SOCKET_ERROR, "Expected failure, got %u\n", ret);
+todo_wine
+    ok(error == WSAEFAULT, "Expected 10014, got %u\n", error);
+
+    /* Invalid parameter tests */
+    SetLastError(0xdeadbeef);
+    ret = pWSAEnumNameSpaceProvidersA(NULL, name);
+    error = WSAGetLastError();
+todo_wine
+    ok(ret == SOCKET_ERROR, "Expected failure, got %u\n", ret);
+todo_wine
+    ok(error == WSAEFAULT, "Expected 10014, got %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    ret = pWSAEnumNameSpaceProvidersA(NULL, NULL);
+    error = WSAGetLastError();
+todo_wine
+    ok(ret == SOCKET_ERROR, "Expected failure, got %u\n", ret);
+todo_wine
+    ok(error == WSAEFAULT, "Expected 10014, got %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    ret = pWSAEnumNameSpaceProvidersA(&blen, NULL);
+    error = WSAGetLastError();
+todo_wine
+    ok(ret == SOCKET_ERROR, "Expected failure, got %u\n", ret);
+todo_wine
+    ok(error == WSAEFAULT, "Expected 10014, got %u\n", error);
+
+#ifdef __REACTOS__ /* ROSTESTS-233 */
+    if (!blen)
+    {
+        skip("Failed to get length needed for name space providers.\n");
+        return;
+    }
+#endif
+
+    name = HeapAlloc(GetProcessHeap(), 0, blen);
+    if (!name)
+    {
+        skip("Failed to alloc memory\n");
+        return;
+    }
+
+    ret = pWSAEnumNameSpaceProvidersA(&blen, name);
+todo_wine
+    ok(ret > 0, "Expected more than zero name space providers\n");
+
+    for (i = 0;i < ret; i++)
+    {
+        trace("Name space Identifier (%p): %s\n", name[i].lpszIdentifier,
+              name[i].lpszIdentifier);
+        switch (name[i].dwNameSpace)
+        {
+            case NS_DNS:
+                trace("\tName space ID: NS_DNS (%u)\n", name[i].dwNameSpace);
+                break;
+            case NS_NLA:
+                trace("\tName space ID: NS_NLA (%u)\n", name[i].dwNameSpace);
+                break;
+            default:
+                trace("\tName space ID: Unknown (%u)\n", name[i].dwNameSpace);
+                break;
+        }
+        trace("\tActive:  %d\n", name[i].fActive);
+        trace("\tVersion: %d\n", name[i].dwVersion);
+    }
+
+    HeapFree(GetProcessHeap(), 0, name);
+}
+
+static void test_WSAEnumNameSpaceProvidersW(void)
+{
+    LPWSANAMESPACE_INFOW name = NULL;
+    DWORD ret, error, blen = 0, i;
+    if (!pWSAEnumNameSpaceProvidersW)
+    {
+        win_skip("WSAEnumNameSpaceProvidersW not found\n");
+        return;
+    }
+
+    SetLastError(0xdeadbeef);
+    ret = pWSAEnumNameSpaceProvidersW(&blen, name);
+    error = WSAGetLastError();
+todo_wine
+    ok(ret == SOCKET_ERROR, "Expected failure, got %u\n", ret);
+todo_wine
+    ok(error == WSAEFAULT, "Expected 10014, got %u\n", error);
+
+    /* Invalid parameter tests */
+    SetLastError(0xdeadbeef);
+    ret = pWSAEnumNameSpaceProvidersW(NULL, name);
+    error = WSAGetLastError();
+todo_wine
+    ok(ret == SOCKET_ERROR, "Expected failure, got %u\n", ret);
+todo_wine
+    ok(error == WSAEFAULT, "Expected 10014, got %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    ret = pWSAEnumNameSpaceProvidersW(NULL, NULL);
+    error = WSAGetLastError();
+todo_wine
+    ok(ret == SOCKET_ERROR, "Expected failure, got %u\n", ret);
+todo_wine
+    ok(error == WSAEFAULT, "Expected 10014, got %u\n", error);
+
+    SetLastError(0xdeadbeef);
+    ret = pWSAEnumNameSpaceProvidersW(&blen, NULL);
+    error = WSAGetLastError();
+todo_wine
+    ok(ret == SOCKET_ERROR, "Expected failure, got %u\n", ret);
+todo_wine
+    ok(error == WSAEFAULT, "Expected 10014, got %u\n", error);
+
+#ifdef __REACTOS__ /* ROSTESTS-233 */
+    if (!blen)
+    {
+        skip("Failed to get length needed for name space providers.\n");
+        return;
+    }
+#endif
+
+    name = HeapAlloc(GetProcessHeap(), 0, blen);
+    if (!name)
+    {
+        skip("Failed to alloc memory\n");
+        return;
+    }
+
+    ret = pWSAEnumNameSpaceProvidersW(&blen, name);
+todo_wine
+    ok(ret > 0, "Expected more than zero name space providers\n");
+
+    for (i = 0;i < ret; i++)
+    {
+        trace("Name space Identifier (%p): %s\n", name[i].lpszIdentifier,
+               wine_dbgstr_w(name[i].lpszIdentifier));
+        switch (name[i].dwNameSpace)
+        {
+            case NS_DNS:
+                trace("\tName space ID: NS_DNS (%u)\n", name[i].dwNameSpace);
+                break;
+            case NS_NLA:
+                trace("\tName space ID: NS_NLA (%u)\n", name[i].dwNameSpace);
+                break;
+            default:
+                trace("\tName space ID: Unknown (%u)\n", name[i].dwNameSpace);
+                break;
+        }
+        trace("\tActive:  %d\n", name[i].fActive);
+        trace("\tVersion: %d\n", name[i].dwVersion);
+    }
+
+    HeapFree(GetProcessHeap(), 0, name);
+}
+
 /**************** Main program  ***************/
 
 START_TEST( sock )
@@ -5977,6 +9742,8 @@ START_TEST( sock )
 
     Init();
 
+    test_inet_ntoa();
+    test_inet_pton();
     test_set_getsockopt();
     test_so_reuseaddr();
     test_ip_pktinfo();
@@ -5993,6 +9760,8 @@ START_TEST( sock )
 
     test_getservbyname();
     test_WSASocket();
+    test_WSADuplicateSocket();
+    test_WSAEnumNetworkEvents();
 
     test_WSAAddressToStringA();
     test_WSAAddressToStringW();
@@ -6001,6 +9770,7 @@ START_TEST( sock )
     test_WSAStringToAddressW();
 
     test_errors();
+    test_listen();
     test_select();
     test_accept();
     test_getpeername();
@@ -6009,28 +9779,42 @@ START_TEST( sock )
     test_addr_to_print();
     test_ioctlsocket();
     test_dns();
+    test_gethostbyname();
     test_gethostbyname_hack();
+    test_gethostname();
 
+    test_WSASendMsg();
     test_WSASendTo();
     test_WSARecv();
+    test_WSAPoll();
 
     test_events(0);
     test_events(1);
 
     test_ipv6only();
+    test_TransmitFile();
     test_GetAddrInfoW();
     test_getaddrinfo();
     test_AcceptEx();
     test_ConnectEx();
+    test_DisconnectEx();
 
     test_sioRoutingInterfaceQuery();
+    test_sioAddressListChange();
+
+    test_WSALookupService();
+    test_WSAEnumNameSpaceProvidersA();
+    test_WSAEnumNameSpaceProvidersW();
 
     test_WSAAsyncGetServByPort();
     test_WSAAsyncGetServByName();
 
     test_completion_port();
+#if CORE_12000_IS_FIXED /* FIXME: CORE-12000 */
+    test_address_list_query();
+#endif
 
-    /* this is a io heavy test, do it at the end so the kernel doesn't start dropping packets */
+    /* this is an io heavy test, do it at the end so the kernel doesn't start dropping packets */
     test_send();
     test_synchronous_WSAIoctl();