Zebediah Figura : ws2_32/tests: Add some tests for NtReadFile() and NtWriteFile() on sockets.

Alexandre Julliard julliard at winehq.org
Thu Jul 14 16:59:25 CDT 2022


Module: wine
Branch: master
Commit: cc879c25d7347ceb58da48f6e6317f13268ea63c
URL:    https://gitlab.winehq.org/wine/wine/-/commit/cc879c25d7347ceb58da48f6e6317f13268ea63c

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Sun May 29 12:42:49 2022 -0500

ws2_32/tests: Add some tests for NtReadFile() and NtWriteFile() on sockets.

---

 dlls/ws2_32/tests/afd.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 151 insertions(+), 3 deletions(-)

diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c
index f84e7084a27..22ccdd0adeb 100644
--- a/dlls/ws2_32/tests/afd.c
+++ b/dlls/ws2_32/tests/afd.c
@@ -33,16 +33,16 @@
 
 #define TIMEOUT_INFINITE _I64_MAX
 
-static void tcp_socketpair(SOCKET *src, SOCKET *dst)
+static void tcp_socketpair_flags(SOCKET *src, SOCKET *dst, DWORD flags)
 {
     SOCKET server = INVALID_SOCKET;
     struct sockaddr_in addr;
     int len, ret;
 
-    *src = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
+    *src = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, flags);
     ok(*src != INVALID_SOCKET, "failed to create socket, error %u\n", WSAGetLastError());
 
-    server = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
+    server = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, flags);
     ok(server != INVALID_SOCKET, "failed to create socket, error %u\n", WSAGetLastError());
 
     memset(&addr, 0, sizeof(addr));
@@ -68,6 +68,11 @@ static void tcp_socketpair(SOCKET *src, SOCKET *dst)
     closesocket(server);
 }
 
+static void tcp_socketpair(SOCKET *src, SOCKET *dst)
+{
+    tcp_socketpair_flags(src, dst, WSA_FLAG_OVERLAPPED);
+}
+
 static void set_blocking(SOCKET s, ULONG blocking)
 {
     int ret;
@@ -2575,6 +2580,148 @@ static void test_async_thread_termination(void)
     closesocket(listener);
 }
 
+static DWORD WINAPI sync_read_file_thread(void *arg)
+{
+    HANDLE server = arg;
+    IO_STATUS_BLOCK io;
+    char buffer[5];
+    NTSTATUS ret;
+
+    memset(buffer, 0xcc, sizeof(buffer));
+    memset(&io, 0xcc, sizeof(io));
+    ret = NtReadFile(server, NULL, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL);
+    ok(!ret, "got status %#lx\n", ret);
+    ok(!io.Status, "got status %#lx\n", io.Status);
+    ok(io.Information == 4, "got size %Iu\n", io.Information);
+    ok(!memcmp(buffer, "data", 4), "got data %s\n", debugstr_an(buffer, io.Information));
+
+    return 0;
+}
+
+static void test_read_write(void)
+{
+    WSANETWORKEVENTS events;
+    IO_STATUS_BLOCK io, io2;
+    SOCKET client, server;
+    LARGE_INTEGER offset;
+    HANDLE event, thread;
+    char buffer[5];
+    NTSTATUS ret;
+
+    event = CreateEventA(NULL, TRUE, FALSE, NULL);
+
+    tcp_socketpair_flags(&client, &server, 0);
+    set_blocking(server, FALSE);
+
+    memset(&io, 0xcc, sizeof(io));
+    ret = NtWriteFile((HANDLE)client, NULL, NULL, NULL, &io, "data", 4, NULL, NULL);
+    ok(!ret, "got status %#lx\n", ret);
+    ok(!io.Status, "got status %#lx\n", io.Status);
+    ok(io.Information == 4, "got size %Iu\n", io.Information);
+
+    memset(buffer, 0xcc, sizeof(buffer));
+    memset(&io, 0xcc, sizeof(io));
+    ret = NtReadFile((HANDLE)server, NULL, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL);
+    ok(!ret, "got status %#lx\n", ret);
+    ok(!io.Status, "got status %#lx\n", io.Status);
+    ok(io.Information == 4, "got size %Iu\n", io.Information);
+    ok(!memcmp(buffer, "data", 4), "got data %s\n", debugstr_an(buffer, io.Information));
+
+    ret = send(server, "data", 4, 0);
+    ok(ret == 4, "got %ld\n", ret);
+
+    ret = WSAEventSelect(client, event, FD_READ);
+    ok(!ret, "got error %lu\n", GetLastError());
+
+    ret = WSAEnumNetworkEvents(client, event, &events);
+    ok(!ret, "got error %lu\n", GetLastError());
+    ok(events.lNetworkEvents == FD_READ, "got events %#lx\n", events.lNetworkEvents);
+
+    memset(buffer, 0xcc, sizeof(buffer));
+    ret = NtReadFile((HANDLE)client, NULL, NULL, NULL, &io, buffer, 1, NULL, NULL);
+    ok(!ret, "got status %#lx\n", ret);
+    ok(io.Information == 1, "got size %Iu\n", io.Information);
+    ok(buffer[0] == 'd', "got data %s\n", debugstr_an(buffer, io.Information));
+
+    ret = WSAEnumNetworkEvents(client, event, &events);
+    ok(!ret, "got error %lu\n", GetLastError());
+    todo_wine ok(events.lNetworkEvents == FD_READ, "got events %#lx\n", events.lNetworkEvents);
+
+    memset(buffer, 0xcc, sizeof(buffer));
+    ret = NtReadFile((HANDLE)client, NULL, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL);
+    ok(!ret, "got status %#lx\n", ret);
+    ok(io.Information == 3, "got size %Iu\n", io.Information);
+    ok(!memcmp(buffer, "ata", 3), "got data %s\n", debugstr_an(buffer, io.Information));
+
+    /* NtReadFile always blocks, even when the socket is non-overlapped and nonblocking */
+
+    thread = CreateThread(NULL, 0, sync_read_file_thread, (void *)server, 0, NULL);
+    ret = WaitForSingleObject(thread, 100);
+    ok(ret == WAIT_TIMEOUT, "got %ld\n", ret);
+
+    ret = NtWriteFile((HANDLE)client, NULL, NULL, NULL, &io, "data", 4, NULL, NULL);
+    ok(!ret, "got status %#lx\n", ret);
+
+    ret = WaitForSingleObject(thread, 1000);
+    ok(!ret, "got %ld\n", ret);
+    CloseHandle(thread);
+
+    closesocket(server);
+    closesocket(client);
+
+    tcp_socketpair(&client, &server);
+
+    ret = NtReadFile((HANDLE)server, event, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL);
+    todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got status %#lx\n", ret);
+    if (ret == STATUS_PENDING)
+    {
+        CancelIo((HANDLE)server);
+        ret = WaitForSingleObject(event, 100);
+        ok(!ret, "wait timed out\n");
+    }
+
+    offset.QuadPart = -1;
+    ret = NtReadFile((HANDLE)server, event, NULL, NULL, &io, buffer, sizeof(buffer), &offset, NULL);
+    todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got status %#lx\n", ret);
+    if (ret == STATUS_PENDING)
+    {
+        CancelIo((HANDLE)server);
+        ret = WaitForSingleObject(event, 100);
+        ok(!ret, "wait timed out\n");
+    }
+
+    memset(buffer, 0xcc, sizeof(buffer));
+    memset(&io, 0xcc, sizeof(io));
+    offset.QuadPart = 1;
+    ret = NtReadFile((HANDLE)server, event, NULL, NULL, &io, buffer, sizeof(buffer), &offset, NULL);
+    ok(ret == STATUS_PENDING, "got status %#lx\n", ret);
+
+    ret = NtWriteFile((HANDLE)client, NULL, NULL, NULL, &io2, "data", 4, NULL, NULL);
+    todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got status %#lx\n", ret);
+
+    offset.QuadPart = -3;
+    ret = NtWriteFile((HANDLE)client, NULL, NULL, NULL, &io2, "data", 4, &offset, NULL);
+    todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got status %#lx\n", ret);
+
+    memset(&io2, 0xcc, sizeof(io2));
+    offset.QuadPart = 2;
+    ret = NtWriteFile((HANDLE)client, NULL, NULL, NULL, &io2, "data", 4, &offset, NULL);
+    ok(!ret, "got status %#lx\n", ret);
+    ok(!io2.Status, "got status %#lx\n", io2.Status);
+    ok(io2.Information == 4, "got size %Iu\n", io2.Information);
+
+    ret = WaitForSingleObject(event, 1000);
+    ok(!ret, "wait timed out\n");
+    ok(!io.Status, "got status %#lx\n", io.Status);
+    ok(io.Information == 4, "got size %Iu\n", io.Information);
+    ok(!memcmp(buffer, "data", 4), "got data %s\n", debugstr_an(buffer, io.Information));
+
+    closesocket(server);
+    closesocket(client);
+
+    CloseHandle(event);
+}
+
 START_TEST(afd)
 {
     WSADATA data;
@@ -2593,6 +2740,7 @@ START_TEST(afd)
     test_bind();
     test_getsockname();
     test_async_thread_termination();
+    test_read_write();
 
     WSACleanup();
 }




More information about the wine-cvs mailing list