diff --git a/dlls/ntoskrnl.exe/tests/driver.h b/dlls/ntoskrnl.exe/tests/driver.h index 3bfc4bd80ac..58a92d4838e 100644 --- a/dlls/ntoskrnl.exe/tests/driver.h +++ b/dlls/ntoskrnl.exe/tests/driver.h @@ -57,3 +57,4 @@ static inline char *drv_strrchr( const char *str, char ch ) } #define SERVER_LISTEN_PORT 9374 +#define CLIENT_LISTEN_PORT 9375 diff --git a/dlls/ntoskrnl.exe/tests/driver4.c b/dlls/ntoskrnl.exe/tests/driver4.c index 5307674de38..dad1d6a04fd 100644 --- a/dlls/ntoskrnl.exe/tests/driver4.c +++ b/dlls/ntoskrnl.exe/tests/driver4.c @@ -376,6 +376,88 @@ static void test_wsk_listen_socket(void) ExFreePool(buffer2); } +static void test_wsk_connect_socket(void) +{ + const WSK_PROVIDER_CONNECTION_DISPATCH *connect_dispatch; + struct socket_context context; + struct sockaddr_in addr; + LARGE_INTEGER timeout; + WSK_SOCKET *socket; + NTSTATUS status; + + timeout.QuadPart = -1000 * 10000; + + 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 = provider_npi.Dispatch->WskSocket(provider_npi.Client, AF_INET, SOCK_STREAM, IPPROTO_TCP, + WSK_FLAG_CONNECTION_SOCKET, &context, &connect_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"); + + socket = (WSK_SOCKET *)wsk_irp->IoStatus.Information; + connect_dispatch = socket->Dispatch; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(CLIENT_LISTEN_PORT); + addr.sin_addr.s_addr = htonl(0x7f000001); + + IoReuseIrp(wsk_irp, STATUS_UNSUCCESSFUL); + IoSetCompletionRoutine(wsk_irp, irp_completion_routine, &irp_complete_event, TRUE, TRUE, TRUE); + status = connect_dispatch->WskConnect(socket, (SOCKADDR *)&addr, 0, wsk_irp); + ok(status == STATUS_INVALID_DEVICE_STATE, "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_INVALID_DEVICE_STATE, "Got unexpected status %#x.\n", wsk_irp->IoStatus.Status); + ok(!wsk_irp->IoStatus.Information, "Got unexpected Information %#lx.\n", + wsk_irp->IoStatus.Information); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + + 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 = connect_dispatch->WskBind(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); + + addr.sin_port = htons(CLIENT_LISTEN_PORT); + addr.sin_addr.s_addr = htonl(0x7f000001); + + IoReuseIrp(wsk_irp, STATUS_UNSUCCESSFUL); + IoSetCompletionRoutine(wsk_irp, irp_completion_routine, &irp_complete_event, TRUE, TRUE, TRUE); + status = connect_dispatch->WskConnect(socket, (SOCKADDR *)&addr, 0, wsk_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 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); + wsk_irp->IoStatus.Status = 0xdeadbeef; + wsk_irp->IoStatus.Information = 0xdeadbeef; + status = connect_dispatch->Basic.WskCloseSocket(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); +} + static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack) { ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; @@ -402,6 +484,7 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st netio_init(); test_wsk_get_address_info(); test_wsk_listen_socket(); + test_wsk_connect_socket(); if (winetest_debug) { diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 5555095bd22..b4ef9d0dcb7 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -518,39 +518,58 @@ static DWORD WINAPI wsk_test_thread(void *parameter) { static const char test_send_string[] = "Client test string 1."; static const WORD version = MAKEWORD(2, 2); + SOCKET s_listen, s_accept, s_connect; struct sockaddr_in addr; char buffer[256]; int ret, err; WSADATA data; - SOCKET s; + int opt_val; 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()); + s_connect = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(s_connect != INVALID_SOCKET, "Error creating socket, WSAGetLastError() %u.\n", WSAGetLastError()); + + s_listen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(s_listen != INVALID_SOCKET, "Error creating socket, WSAGetLastError() %u.\n", WSAGetLastError()); + + opt_val = 1; + setsockopt(s_listen, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt_val, sizeof(opt_val)); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_port = htons(SERVER_LISTEN_PORT); + addr.sin_port = htons(CLIENT_LISTEN_PORT); addr.sin_addr.s_addr = htonl(0x7f000001); + ret = bind(s_listen, (struct sockaddr *)&addr, sizeof(addr)); + ok(!ret, "Got unexpected ret %d, WSAGetLastError() %u.\n", ret, WSAGetLastError()); - ret = connect(s, (struct sockaddr *)&addr, sizeof(addr)); + ret = listen(s_listen, SOMAXCONN); + ok(!ret, "Got unexpected ret %d, WSAGetLastError() %u.\n", ret, WSAGetLastError()); + + addr.sin_port = htons(SERVER_LISTEN_PORT); + + ret = connect(s_connect, (struct sockaddr *)&addr, sizeof(addr)); while (ret && ((err = WSAGetLastError()) == WSAECONNREFUSED || err == WSAECONNABORTED)) { SwitchToThread(); - ret = connect(s, (struct sockaddr *)&addr, sizeof(addr)); + ret = connect(s_connect, (struct sockaddr *)&addr, sizeof(addr)); } ok(!ret, "Error connecting, WSAGetLastError() %u.\n", WSAGetLastError()); - ret = send(s, test_send_string, sizeof(test_send_string), 0); + ret = send(s_connect, test_send_string, sizeof(test_send_string), 0); ok(ret == sizeof(test_send_string), "Got unexpected ret %d.\n", ret); - ret = recv(s, buffer, sizeof(buffer), 0); + ret = recv(s_connect, buffer, sizeof(buffer), 0); ok(ret == sizeof(buffer), "Got unexpected ret %d.\n", ret); ok(!strcmp(buffer, "Server test string 1."), "Received unexpected data.\n"); - closesocket(s); + s_accept = accept(s_listen, NULL, NULL); + ok(s_accept != INVALID_SOCKET, "Error creating socket, WSAGetLastError() %u.\n", WSAGetLastError()); + + closesocket(s_accept); + closesocket(s_connect); + closesocket(s_listen); return TRUE; }