[PATCH v2 4/4] ntoskrnl/tests: Add test for WskAccept().

Paul Gofman pgofman at codeweavers.com
Wed Jun 17 12:22:00 CDT 2020


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/ntoskrnl.exe/tests/Makefile.in |   2 +-
 dlls/ntoskrnl.exe/tests/driver4.c   | 116 ++++++++++++++++++++++++++--
 dlls/ntoskrnl.exe/tests/ntoskrnl.c  |  37 ++++++++-
 3 files changed, 148 insertions(+), 7 deletions(-)

diff --git a/dlls/ntoskrnl.exe/tests/Makefile.in b/dlls/ntoskrnl.exe/tests/Makefile.in
index 06c06671ca1..779d4b28e6d 100644
--- a/dlls/ntoskrnl.exe/tests/Makefile.in
+++ b/dlls/ntoskrnl.exe/tests/Makefile.in
@@ -1,5 +1,5 @@
 TESTDLL   = ntoskrnl.exe
-IMPORTS   = advapi32
+IMPORTS   = advapi32 ws2_32
 
 driver_IMPORTS = winecrt0 ntoskrnl
 driver_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
diff --git a/dlls/ntoskrnl.exe/tests/driver4.c b/dlls/ntoskrnl.exe/tests/driver4.c
index 4336fdb21a4..fd495a26e45 100644
--- a/dlls/ntoskrnl.exe/tests/driver4.c
+++ b/dlls/ntoskrnl.exe/tests/driver4.c
@@ -169,11 +169,19 @@ struct socket_context
 
 static void test_wsk_listen_socket(void)
 {
+    const WSK_PROVIDER_LISTEN_DISPATCH *tcp_dispatch, *udp_dispatch;
     static const WSK_CLIENT_LISTEN_DISPATCH client_listen_dispatch;
-    const WSK_PROVIDER_LISTEN_DISPATCH *dispatch;
+    const WSK_PROVIDER_CONNECTION_DISPATCH *accept_dispatch;
+    WSK_SOCKET *tcp_socket, *udp_socket, *accept_socket;
     struct socket_context context;
+    struct sockaddr_in addr;
+    LARGE_INTEGER timeout;
     NTSTATUS status;
-    WSK_SOCKET *s;
+    KEVENT event;
+    IRP *irp;
+
+    irp = IoAllocateIrp(1, FALSE);
+    KeInitializeEvent(&event, SynchronizationEvent, FALSE);
 
     status = provider_npi.Dispatch->WskSocket(NULL, AF_INET, SOCK_STREAM, IPPROTO_TCP,
             WSK_FLAG_LISTEN_SOCKET, &context, &client_listen_dispatch, NULL, NULL, NULL, NULL);
@@ -197,20 +205,118 @@ static void test_wsk_listen_socket(void)
     ok(wsk_irp->IoStatus.Status == STATUS_SUCCESS, "Got unexpected status %#x.\n", wsk_irp->IoStatus.Status);
     ok(wsk_irp->IoStatus.Information, "Got zero Information.\n");
 
-    s = (WSK_SOCKET *)wsk_irp->IoStatus.Information;
-    dispatch = s->Dispatch;
+    tcp_socket = (WSK_SOCKET *)wsk_irp->IoStatus.Information;
+    tcp_dispatch = tcp_socket->Dispatch;
+
+    IoReuseIrp(wsk_irp, STATUS_UNSUCCESSFUL);
+    IoSetCompletionRoutine(wsk_irp, irp_completion_routine, &irp_complete_event, TRUE, TRUE, TRUE);
+    status = provider_npi.Dispatch->WskSocket(provider_npi.Client, AF_INET, SOCK_DGRAM, IPPROTO_UDP,
+            WSK_FLAG_LISTEN_SOCKET, &context, &client_listen_dispatch, NULL, NULL, NULL, wsk_irp);
+    ok(status == STATUS_PENDING, "Got unexpected status %#x.\n", status);
+    status = KeWaitForSingleObject(&irp_complete_event, Executive, KernelMode, FALSE, NULL);
+    ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status);
+    ok(wsk_irp->IoStatus.Status == STATUS_SUCCESS, "Got unexpected status %#x.\n", wsk_irp->IoStatus.Status);
+    ok(wsk_irp->IoStatus.Information, "Got zero Information.\n");
+
+    udp_socket = (WSK_SOCKET *)wsk_irp->IoStatus.Information;
+    udp_dispatch = udp_socket->Dispatch;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(12345);
+
+    IoReuseIrp(wsk_irp, STATUS_UNSUCCESSFUL);
+    IoSetCompletionRoutine(wsk_irp, irp_completion_routine, &irp_complete_event, TRUE, TRUE, TRUE);
+    wsk_irp->IoStatus.Status = 0xdeadbeef;
+    wsk_irp->IoStatus.Information = 0xdeadbeef;
+    status = udp_dispatch->WskBind(udp_socket, (SOCKADDR *)&addr, 0, wsk_irp);
+    ok(status == STATUS_PENDING, "Got unexpected status %#x.\n", status);
+    status = KeWaitForSingleObject(&irp_complete_event, Executive, KernelMode, FALSE, NULL);
+    ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status);
+    ok(wsk_irp->IoStatus.Status == STATUS_NOT_IMPLEMENTED, "Got unexpected status %#x.\n", wsk_irp->IoStatus.Status);
+    ok(!wsk_irp->IoStatus.Information, "Got unexpected Information %#lx.\n",
+            wsk_irp->IoStatus.Information);
+
+    IoReuseIrp(wsk_irp, STATUS_UNSUCCESSFUL);
+    IoSetCompletionRoutine(wsk_irp, irp_completion_routine, &irp_complete_event, TRUE, TRUE, TRUE);
+    status = udp_dispatch->Basic.WskCloseSocket(udp_socket, wsk_irp);
+    ok(status == STATUS_PENDING, "Got unexpected status %#x.\n", status);
+    status = KeWaitForSingleObject(&irp_complete_event, Executive, KernelMode, FALSE, NULL);
+    ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status);
+    ok(wsk_irp->IoStatus.Status == STATUS_SUCCESS, "Got unexpected status %#x.\n", wsk_irp->IoStatus.Status);
 
     IoReuseIrp(wsk_irp, STATUS_UNSUCCESSFUL);
     IoSetCompletionRoutine(wsk_irp, irp_completion_routine, &irp_complete_event, TRUE, TRUE, TRUE);
     wsk_irp->IoStatus.Status = 0xdeadbeef;
     wsk_irp->IoStatus.Information = 0xdeadbeef;
-    status = dispatch->Basic.WskCloseSocket(s, wsk_irp);
+    status = tcp_dispatch->WskBind(tcp_socket, (SOCKADDR *)&addr, 0, wsk_irp);
     ok(status == STATUS_PENDING, "Got unexpected status %#x.\n", status);
     status = KeWaitForSingleObject(&irp_complete_event, Executive, KernelMode, FALSE, NULL);
     ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status);
     ok(wsk_irp->IoStatus.Status == STATUS_SUCCESS, "Got unexpected status %#x.\n", wsk_irp->IoStatus.Status);
     ok(!wsk_irp->IoStatus.Information, "Got unexpected Information %#lx.\n",
             wsk_irp->IoStatus.Information);
+
+    timeout.QuadPart = -1000 * 10000;
+
+    IoReuseIrp(wsk_irp, STATUS_UNSUCCESSFUL);
+    IoSetCompletionRoutine(wsk_irp, irp_completion_routine, &irp_complete_event, TRUE, TRUE, TRUE);
+    status = tcp_dispatch->WskAccept(tcp_socket, 0, NULL, NULL, NULL, NULL, wsk_irp);
+    ok(status == STATUS_PENDING, "Got unexpected status %#x.\n", status);
+
+    if (0)
+    {
+        /* Queuing another WskAccept in parallel with different irp results in Windows hang. */
+        IoReuseIrp(irp, STATUS_UNSUCCESSFUL);
+        IoSetCompletionRoutine(irp, irp_completion_routine, &event, TRUE, TRUE, TRUE);
+        status = tcp_dispatch->WskAccept(tcp_socket, 0, NULL, NULL, NULL, NULL, irp);
+        ok(status == STATUS_PENDING, "Got unexpected status %#x.\n", status);
+    }
+
+    status = KeWaitForSingleObject(&irp_complete_event, Executive, KernelMode, FALSE, &timeout);
+    ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status);
+    ok(wsk_irp->IoStatus.Status == STATUS_SUCCESS, "Got unexpected status %#x.\n", wsk_irp->IoStatus.Status);
+    ok(wsk_irp->IoStatus.Information, "Got zero Information.\n");
+
+    if (status == STATUS_SUCCESS && wsk_irp->IoStatus.Status == STATUS_SUCCESS)
+    {
+        accept_socket = (WSK_SOCKET *)wsk_irp->IoStatus.Information;
+        accept_dispatch = accept_socket->Dispatch;
+
+        IoReuseIrp(wsk_irp, STATUS_UNSUCCESSFUL);
+        IoSetCompletionRoutine(wsk_irp, irp_completion_routine, &irp_complete_event, TRUE, TRUE, TRUE);
+        status = accept_dispatch->Basic.WskCloseSocket(accept_socket, wsk_irp);
+        ok(status == STATUS_PENDING, "Got unexpected status %#x.\n", status);
+        status = KeWaitForSingleObject(&irp_complete_event, Executive, KernelMode, FALSE, NULL);
+        ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status);
+        ok(wsk_irp->IoStatus.Status == STATUS_SUCCESS, "Got unexpected status %#x.\n", wsk_irp->IoStatus.Status);
+        ok(!wsk_irp->IoStatus.Information, "Got unexpected Information %#lx.\n",
+                wsk_irp->IoStatus.Information);
+    }
+
+    /* WskAccept to be aborted by WskCloseSocket(). */
+    IoReuseIrp(irp, STATUS_UNSUCCESSFUL);
+    IoSetCompletionRoutine(irp, irp_completion_routine, &event, TRUE, TRUE, TRUE);
+    status = tcp_dispatch->WskAccept(tcp_socket, 0, NULL, NULL, NULL, NULL, irp);
+    ok(status == STATUS_PENDING, "Got unexpected status %#x.\n", status);
+
+    IoReuseIrp(wsk_irp, STATUS_UNSUCCESSFUL);
+    IoSetCompletionRoutine(wsk_irp, irp_completion_routine, &irp_complete_event, TRUE, TRUE, TRUE);
+    wsk_irp->IoStatus.Status = 0xdeadbeef;
+    wsk_irp->IoStatus.Information = 0xdeadbeef;
+    status = tcp_dispatch->Basic.WskCloseSocket(tcp_socket, wsk_irp);
+    ok(status == STATUS_PENDING, "Got unexpected status %#x.\n", status);
+    status = KeWaitForSingleObject(&irp_complete_event, Executive, KernelMode, FALSE, NULL);
+    ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status);
+    ok(wsk_irp->IoStatus.Status == STATUS_SUCCESS, "Got unexpected status %#x.\n", wsk_irp->IoStatus.Status);
+    ok(!wsk_irp->IoStatus.Information, "Got unexpected Information %#lx.\n",
+            wsk_irp->IoStatus.Information);
+
+    status = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, &timeout);
+    ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status);
+    ok(irp->IoStatus.Status == STATUS_CANCELLED, "Got unexpected status %#x.\n", irp->IoStatus.Status);
+    ok(!irp->IoStatus.Information, "Got unexpected Information %#lx.\n", irp->IoStatus.Information);
+    IoFreeIrp(irp);
 }
 
 static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack)
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
index c2afee3dfe9..4cdcda7d3ea 100644
--- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
@@ -27,6 +27,7 @@
 #include "winsvc.h"
 #include "winioctl.h"
 #include "winternl.h"
+#include "winsock2.h"
 #include "wine/test.h"
 #include "wine/heap.h"
 
@@ -513,10 +514,42 @@ static void test_driver3(void)
     DeleteFileA(filename);
 }
 
-void test_driver4(void)
+static DWORD WINAPI wsk_test_thread(void *parameter)
+{
+    static const WORD version = MAKEWORD(2, 2);
+    struct sockaddr_in addr;
+    int ret, err;
+    WSADATA data;
+    SOCKET s;
+
+    ret = WSAStartup(version, &data);
+    ok(!ret, "WSAStartup() failed, ret %u.\n", ret);
+
+    s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    ok(s != INVALID_SOCKET, "Error creating socket, WSAGetLastError() %u.\n", WSAGetLastError());
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(12345);
+    addr.sin_addr.s_addr = htonl(0x7f000001);
+
+    ret = connect(s, (struct sockaddr *)&addr, sizeof(addr));
+    while (ret && ((err = WSAGetLastError()) == WSAECONNREFUSED || err == WSAECONNABORTED))
+    {
+        SwitchToThread();
+        ret = connect(s, (struct sockaddr *)&addr, sizeof(addr));
+    }
+    ok(!ret, "Error connecting, WSAGetLastError() %u.\n", WSAGetLastError());
+
+    closesocket(s);
+    return TRUE;
+}
+
+static void test_driver4(void)
 {
     char filename[MAX_PATH];
     SC_HANDLE service;
+    HANDLE hthread;
     DWORD written;
     BOOL ret;
 
@@ -532,7 +565,9 @@ void test_driver4(void)
     device = CreateFileA("\\\\.\\WineTestDriver4", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
     ok(device != INVALID_HANDLE_VALUE, "failed to open device: %u\n", GetLastError());
 
+    hthread = CreateThread(NULL, 0, wsk_test_thread, NULL, 0, NULL);
     main_test();
+    WaitForSingleObject(hthread, INFINITE);
 
     ret = DeviceIoControl(device, IOCTL_WINETEST_DETACH, NULL, 0, NULL, 0, &written, NULL);
     ok(ret, "DeviceIoControl failed: %u\n", GetLastError());
-- 
2.26.2




More information about the wine-devel mailing list