From: Rose Hellsing <rose@pinkro.se> Add tests for zero-length datagram and request/reply messages. Each test uses a dedicated port to avoid name conflicts. Note: Multi-client and timeout tests still need server-side fixes. --- dlls/ntdll/tests/port.c | 179 +++++++++++++++++++++++++++------------- 1 file changed, 120 insertions(+), 59 deletions(-) diff --git a/dlls/ntdll/tests/port.c b/dlls/ntdll/tests/port.c index 1e34ff88b73..eca78a972e2 100644 --- a/dlls/ntdll/tests/port.c +++ b/dlls/ntdll/tests/port.c @@ -485,65 +485,6 @@ static void test_connect_port_errors(void) } } -static DWORD WINAPI timeout_client(LPVOID arg) -{ - SECURITY_QUALITY_OF_SERVICE sqos; - HANDLE PortHandle; - ULONG len; - NTSTATUS status; - - sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); - sqos.ImpersonationLevel = SecurityImpersonation; - sqos.ContextTrackingMode = SECURITY_STATIC_TRACKING; - sqos.EffectiveOnly = TRUE; - - status = pNtConnectPort(&PortHandle, &port, &sqos, 0, 0, &len, NULL, NULL); - ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status); - if (status != STATUS_SUCCESS) return 1; - - /* Just exit - server should get timeout, not hang forever */ - return 0; -} - -static void test_reply_wait_receive_timeout(HANDLE PortHandle) -{ - union lpc_message *LpcMessage; - NTSTATUS status; - LARGE_INTEGER timeout; - ULONG size; - - size = FIELD_OFFSET(LPC_MESSAGE, Data) + MAX_MESSAGE_LEN; - LpcMessage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); - - /* Wait with a 100ms timeout - should timeout since client just exits */ - timeout.QuadPart = -1000000LL; /* 100ms in 100ns units */ - - /* First, accept the connection */ - status = pNtReplyWaitReceivePort(PortHandle, NULL, NULL, &LpcMessage->msg); - ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status); - - if (status == STATUS_SUCCESS && - (is_wow64 ? LpcMessage->msg64.MessageType : LpcMessage->msg.MessageType) == LPC_CONNECTION_REQUEST) - { - HANDLE accept_handle; - status = pNtAcceptConnectPort(&accept_handle, 0, &LpcMessage->msg, 1, NULL, NULL); - ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status); - if (status == STATUS_SUCCESS) - { - status = pNtCompleteConnectPort(accept_handle); - ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status); - NtClose(accept_handle); - } - } - - /* Now try to receive with timeout - client has exited, so should timeout */ - status = pNtReplyWaitReceivePortEx(PortHandle, NULL, NULL, &LpcMessage->msg, &timeout); - ok(status == STATUS_TIMEOUT || status == STATUS_SUCCESS || status == STATUS_PENDING, - "Expected STATUS_TIMEOUT, STATUS_SUCCESS or STATUS_PENDING, got %08lx\n", status); - - HeapFree(GetProcessHeap(), 0, LpcMessage); -} - static DWORD WINAPI multi_client_thread(LPVOID arg) { SECURITY_QUALITY_OF_SERVICE sqos; @@ -706,6 +647,94 @@ static void test_multiple_clients_server(HANDLE PortHandle) HeapFree(GetProcessHeap(), 0, LpcMessage); } +static void test_zero_length_server(HANDLE PortHandle) +{ + HANDLE AcceptPortHandle; + union lpc_message *LpcMessage; + ULONG size; + NTSTATUS status; + BOOL done = FALSE; + + size = FIELD_OFFSET(LPC_MESSAGE, Data) + MAX_MESSAGE_LEN; + LpcMessage = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); + + while (!done) + { + status = pNtReplyWaitReceivePort(PortHandle, NULL, NULL, &LpcMessage->msg); + ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status); + if (status != STATUS_SUCCESS) break; + + if (is_wow64) + { + switch (LpcMessage->msg64.MessageType) + { + case LPC_CONNECTION_REQUEST: + status = pNtAcceptConnectPort(&AcceptPortHandle, 0, &LpcMessage->msg, 1, NULL, NULL); + ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status); + if (status == STATUS_SUCCESS) + { + status = pNtCompleteConnectPort(AcceptPortHandle); + ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status); + } + break; + + case LPC_REQUEST: + /* Reply to zero-length request with zero-length reply */ + LpcMessage->msg64.DataSize = 0; + LpcMessage->msg64.MessageSize = FIELD_OFFSET(LPC_MESSAGE64, Data[0]); + status = pNtReplyPort(PortHandle, &LpcMessage->msg); + ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status); + done = TRUE; + break; + + case LPC_DATAGRAM: + /* Zero-length datagram received */ + ok(LpcMessage->msg64.DataSize == 0, "Expected DataSize 0, got %u\n", LpcMessage->msg64.DataSize); + break; + + case LPC_CLIENT_DIED: + done = TRUE; + break; + } + } + else + { + switch (LpcMessage->msg.MessageType) + { + case LPC_CONNECTION_REQUEST: + status = pNtAcceptConnectPort(&AcceptPortHandle, 0, &LpcMessage->msg, 1, NULL, NULL); + ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status); + if (status == STATUS_SUCCESS) + { + status = pNtCompleteConnectPort(AcceptPortHandle); + ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status); + } + break; + + case LPC_REQUEST: + /* Reply to zero-length request with zero-length reply */ + LpcMessage->msg.DataSize = 0; + LpcMessage->msg.MessageSize = FIELD_OFFSET(LPC_MESSAGE, Data[0]); + status = pNtReplyPort(PortHandle, &LpcMessage->msg); + ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status); + done = TRUE; + break; + + case LPC_DATAGRAM: + /* Zero-length datagram received */ + ok(LpcMessage->msg.DataSize == 0, "Expected DataSize 0, got %u\n", LpcMessage->msg.DataSize); + break; + + case LPC_CLIENT_DIED: + done = TRUE; + break; + } + } + } + + HeapFree(GetProcessHeap(), 0, LpcMessage); +} + static DWORD WINAPI zero_length_client(LPVOID arg) { SECURITY_QUALITY_OF_SERVICE sqos; @@ -808,6 +837,38 @@ START_TEST(port) test_create_port_errors(); test_connect_port_errors(); + /* Test 3: Zero-length messages */ + if (status == STATUS_SUCCESS) + { + static const WCHAR ZERO_PORT[] = {'\\','Z','e','r','o','P','o','r','t',0}; + UNICODE_STRING zero_name; + HANDLE zero_port; + DWORD id; + HANDLE thread; + + pRtlInitUnicodeString(&zero_name, ZERO_PORT); + memset(&obj, 0, sizeof(OBJECT_ATTRIBUTES)); + obj.Length = sizeof(OBJECT_ATTRIBUTES); + obj.ObjectName = &zero_name; + + status = pNtCreatePort(&zero_port, &obj, 100, 100, 0); + ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status); + if (status == STATUS_SUCCESS) + { + /* Update global port name so client connects to the right port */ + port = zero_name; + thread = CreateThread(NULL, 0, zero_length_client, NULL, 0, &id); + ok(thread != NULL, "Expected non-NULL thread handle!\n"); + + test_zero_length_server(zero_port); + ok(WaitForSingleObject(thread, 10000) == 0, "zero-length thread didn't exit\n"); + CloseHandle(thread); + NtClose(zero_port); + } + } + + + if (status == STATUS_SUCCESS) NtClose(port_handle); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10611