Author: tfaber Date: Sun Mar 5 00:55:50 2017 New Revision: 74069
URL: http://svn.reactos.org/svn/reactos?rev=74069&view=rev Log: [NTOS:LPC] - Implement the early exit case (e.g. on connection refused) in NtAcceptConnectPort CORE-12145
Added: trunk/rostests/apitests/ntdll/NtAcceptConnectPort.c (with props) Modified: trunk/reactos/ntoskrnl/lpc/complete.c trunk/rostests/apitests/ntdll/CMakeLists.txt trunk/rostests/apitests/ntdll/testlist.c
Modified: trunk/reactos/ntoskrnl/lpc/complete.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/complete.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/lpc/complete.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/lpc/complete.c [iso-8859-1] Sun Mar 5 00:55:50 2017 @@ -394,8 +394,12 @@ /* Check if we got here while still having a client thread */ if (ClientThread) { - /* FIXME: Complex cleanup code */ - ASSERT(FALSE); + KeAcquireGuardedMutex(&LpcpLock); + ClientThread->LpcReplyMessage = Message; + LpcpPrepareToWakeClient(ClientThread); + KeReleaseGuardedMutex(&LpcpLock); + LpcpCompleteWait(&ClientThread->LpcReplySemaphore); + ObDereferenceObject(ClientThread); }
/* Dereference the client port if we have one, and the process */
Modified: trunk/rostests/apitests/ntdll/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/ntdll/CMakeLists.... ============================================================================== --- trunk/rostests/apitests/ntdll/CMakeLists.txt [iso-8859-1] (original) +++ trunk/rostests/apitests/ntdll/CMakeLists.txt [iso-8859-1] Sun Mar 5 00:55:50 2017 @@ -1,6 +1,7 @@
list(APPEND SOURCE LdrEnumResources.c + NtAcceptConnectPort.c NtAllocateVirtualMemory.c NtApphelpCacheControl.c NtContinue.c
Added: trunk/rostests/apitests/ntdll/NtAcceptConnectPort.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/ntdll/NtAcceptCon... ============================================================================== --- trunk/rostests/apitests/ntdll/NtAcceptConnectPort.c (added) +++ trunk/rostests/apitests/ntdll/NtAcceptConnectPort.c [iso-8859-1] Sun Mar 5 00:55:50 2017 @@ -0,0 +1,254 @@ +/* + * PROJECT: ReactOS API tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: Test for NtAcceptConnectPort + * PROGRAMMERS: Thomas Faber thomas.faber@reactos.org + */ + +#include <apitest.h> + +#define WIN32_NO_STATUS +#include <ndk/lpcfuncs.h> +#include <ndk/obfuncs.h> +#include <ndk/rtlfuncs.h> +#include <process.h> + +#define TEST_CONNECTION_INFO_SIGNATURE1 0xaabb0123 +#define TEST_CONNECTION_INFO_SIGNATURE2 0xaabb0124 +typedef struct _TEST_CONNECTION_INFO +{ + ULONG Signature; +} TEST_CONNECTION_INFO, *PTEST_CONNECTION_INFO; + +#define TEST_MESSAGE_MESSAGE 0x4455cdef +typedef struct _TEST_MESSAGE +{ + PORT_MESSAGE Header; + ULONG Message; +} TEST_MESSAGE, *PTEST_MESSAGE; + +static UNICODE_STRING PortName = RTL_CONSTANT_STRING(L"\NtdllApitestNtAcceptConnectPortTestPort"); +static UINT ServerThreadId; +static UINT ClientThreadId; +static UCHAR Context; + +UINT +CALLBACK +ServerThread( + _Inout_ PVOID Parameter) +{ + NTSTATUS Status; + TEST_MESSAGE Message; + HANDLE PortHandle; + HANDLE ServerPortHandle = Parameter; + + /* Listen, but refuse the connection */ + RtlZeroMemory(&Message, sizeof(Message)); + Status = NtListenPort(ServerPortHandle, + &Message.Header); + ok_hex(Status, STATUS_SUCCESS); + + ok(Message.Header.u1.s1.TotalLength == RTL_SIZEOF_THROUGH_FIELD(TEST_MESSAGE, Message), + "TotalLength = %u, expected %lu\n", + Message.Header.u1.s1.TotalLength, RTL_SIZEOF_THROUGH_FIELD(TEST_MESSAGE, Message)); + ok(Message.Header.u1.s1.DataLength == sizeof(TEST_CONNECTION_INFO), + "DataLength = %u\n", Message.Header.u1.s1.DataLength); + ok(Message.Header.u2.s2.Type == LPC_CONNECTION_REQUEST, + "Type = %x\n", Message.Header.u2.s2.Type); + ok(Message.Header.ClientId.UniqueProcess == (HANDLE)GetCurrentProcessId(), + "UniqueProcess = %p, expected %lx\n", + Message.Header.ClientId.UniqueProcess, GetCurrentProcessId()); + ok(Message.Header.ClientId.UniqueThread == (HANDLE)ClientThreadId, + "UniqueThread = %p, expected %x\n", + Message.Header.ClientId.UniqueThread, ClientThreadId); + ok(Message.Message == TEST_CONNECTION_INFO_SIGNATURE1, "Message = %lx\n", Message.Message); + + PortHandle = (PVOID)(ULONG_PTR)0x55555555; + Status = NtAcceptConnectPort(&PortHandle, + &Context, + &Message.Header, + FALSE, + NULL, + NULL); + ok_hex(Status, STATUS_SUCCESS); + ok(PortHandle == (PVOID)(ULONG_PTR)0x55555555, "PortHandle = %p\n", PortHandle); + + /* Listen a second time, then accept */ + RtlZeroMemory(&Message, sizeof(Message)); + Status = NtListenPort(ServerPortHandle, + &Message.Header); + ok_hex(Status, STATUS_SUCCESS); + + ok(Message.Header.u1.s1.TotalLength == RTL_SIZEOF_THROUGH_FIELD(TEST_MESSAGE, Message), + "TotalLength = %u, expected %lu\n", + Message.Header.u1.s1.TotalLength, RTL_SIZEOF_THROUGH_FIELD(TEST_MESSAGE, Message)); + ok(Message.Header.u1.s1.DataLength == sizeof(TEST_CONNECTION_INFO), + "DataLength = %u\n", Message.Header.u1.s1.DataLength); + ok(Message.Header.u2.s2.Type == LPC_CONNECTION_REQUEST, + "Type = %x\n", Message.Header.u2.s2.Type); + ok(Message.Header.ClientId.UniqueProcess == (HANDLE)GetCurrentProcessId(), + "UniqueProcess = %p, expected %lx\n", + Message.Header.ClientId.UniqueProcess, GetCurrentProcessId()); + ok(Message.Header.ClientId.UniqueThread == (HANDLE)ClientThreadId, + "UniqueThread = %p, expected %x\n", + Message.Header.ClientId.UniqueThread, ClientThreadId); + ok(Message.Message == TEST_CONNECTION_INFO_SIGNATURE2, "Message = %lx\n", Message.Message); + + Status = NtAcceptConnectPort(&PortHandle, + &Context, + &Message.Header, + TRUE, + NULL, + NULL); + ok_hex(Status, STATUS_SUCCESS); + + Status = NtCompleteConnectPort(PortHandle); + ok_hex(Status, STATUS_SUCCESS); + + RtlZeroMemory(&Message, sizeof(Message)); + Status = NtReplyWaitReceivePort(PortHandle, + NULL, + NULL, + &Message.Header); + ok_hex(Status, STATUS_SUCCESS); + + ok(Message.Header.u1.s1.TotalLength == sizeof(Message), + "TotalLength = %u, expected %Iu\n", + Message.Header.u1.s1.TotalLength, sizeof(Message)); + ok(Message.Header.u1.s1.DataLength == sizeof(Message.Message), + "DataLength = %u\n", Message.Header.u1.s1.DataLength); + ok(Message.Header.u2.s2.Type == LPC_DATAGRAM, + "Type = %x\n", Message.Header.u2.s2.Type); + ok(Message.Header.ClientId.UniqueProcess == (HANDLE)GetCurrentProcessId(), + "UniqueProcess = %p, expected %lx\n", + Message.Header.ClientId.UniqueProcess, GetCurrentProcessId()); + ok(Message.Header.ClientId.UniqueThread == (HANDLE)ClientThreadId, + "UniqueThread = %p, expected %x\n", + Message.Header.ClientId.UniqueThread, ClientThreadId); + ok(Message.Message == TEST_MESSAGE_MESSAGE, "Message = %lx\n", Message.Message); + + Status = NtClose(PortHandle); + ok_hex(Status, STATUS_SUCCESS); + + return 0; +} + +UINT +CALLBACK +ClientThread( + _Inout_ PVOID Parameter) +{ + NTSTATUS Status; + HANDLE PortHandle; + TEST_CONNECTION_INFO ConnectInfo; + ULONG ConnectInfoLength; + SECURITY_QUALITY_OF_SERVICE SecurityQos; + TEST_MESSAGE Message; + + SecurityQos.Length = sizeof(SecurityQos); + SecurityQos.ImpersonationLevel = SecurityIdentification; + SecurityQos.EffectiveOnly = TRUE; + SecurityQos.ContextTrackingMode = SECURITY_STATIC_TRACKING; + + /* Attempt to connect -- will be rejected */ + ConnectInfo.Signature = TEST_CONNECTION_INFO_SIGNATURE1; + ConnectInfoLength = sizeof(ConnectInfo); + PortHandle = (PVOID)(ULONG_PTR)0x55555555; + Status = NtConnectPort(&PortHandle, + &PortName, + &SecurityQos, + NULL, + NULL, + NULL, + &ConnectInfo, + &ConnectInfoLength); + ok_hex(Status, STATUS_PORT_CONNECTION_REFUSED); + ok(PortHandle == (PVOID)(ULONG_PTR)0x55555555, "PortHandle = %p\n", PortHandle); + + /* Try again, this time it will be accepted */ + ConnectInfo.Signature = TEST_CONNECTION_INFO_SIGNATURE2; + ConnectInfoLength = sizeof(ConnectInfo); + Status = NtConnectPort(&PortHandle, + &PortName, + &SecurityQos, + NULL, + NULL, + NULL, + &ConnectInfo, + &ConnectInfoLength); + ok_hex(Status, STATUS_SUCCESS); + if (!NT_SUCCESS(Status)) + { + skip("Failed to connect\n"); + return 0; + } + + RtlZeroMemory(&Message, sizeof(Message)); + Message.Header.u1.s1.TotalLength = sizeof(Message); + Message.Header.u1.s1.DataLength = sizeof(Message.Message); + Message.Message = TEST_MESSAGE_MESSAGE; + Status = NtRequestPort(PortHandle, + &Message.Header); + ok_hex(Status, STATUS_SUCCESS); + + Status = NtClose(PortHandle); + ok_hex(Status, STATUS_SUCCESS); + + return 0; +} + +START_TEST(NtAcceptConnectPort) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE PortHandle; + HANDLE ThreadHandles[2]; + + InitializeObjectAttributes(&ObjectAttributes, + &PortName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtCreatePort(&PortHandle, + &ObjectAttributes, + sizeof(TEST_CONNECTION_INFO), + sizeof(TEST_MESSAGE), + 2 * sizeof(TEST_MESSAGE)); + ok_hex(Status, STATUS_SUCCESS); + if (!NT_SUCCESS(Status)) + { + skip("Failed to create port\n"); + return; + } + + ThreadHandles[0] = (HANDLE)_beginthreadex(NULL, + 0, + ServerThread, + PortHandle, + 0, + &ServerThreadId); + ok(ThreadHandles[0] != NULL, "_beginthreadex failed\n"); + + ThreadHandles[1] = (HANDLE)_beginthreadex(NULL, + 0, + ClientThread, + PortHandle, + 0, + &ClientThreadId); + ok(ThreadHandles[1] != NULL, "_beginthreadex failed\n"); + + Status = NtWaitForMultipleObjects(RTL_NUMBER_OF(ThreadHandles), + ThreadHandles, + WaitAll, + FALSE, + NULL); + ok_hex(Status, STATUS_SUCCESS); + + Status = NtClose(ThreadHandles[0]); + ok_hex(Status, STATUS_SUCCESS); + Status = NtClose(ThreadHandles[1]); + ok_hex(Status, STATUS_SUCCESS); + + Status = NtClose(PortHandle); + ok_hex(Status, STATUS_SUCCESS); +}
Propchange: trunk/rostests/apitests/ntdll/NtAcceptConnectPort.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/rostests/apitests/ntdll/testlist.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/ntdll/testlist.c?... ============================================================================== --- trunk/rostests/apitests/ntdll/testlist.c [iso-8859-1] (original) +++ trunk/rostests/apitests/ntdll/testlist.c [iso-8859-1] Sun Mar 5 00:55:50 2017 @@ -4,6 +4,7 @@ #include <apitest.h>
extern void func_LdrEnumResources(void); +extern void func_NtAcceptConnectPort(void); extern void func_NtAllocateVirtualMemory(void); extern void func_NtApphelpCacheControl(void); extern void func_NtContinue(void); @@ -57,6 +58,7 @@ const struct test winetest_testlist[] = { { "LdrEnumResources", func_LdrEnumResources }, + { "NtAcceptConnectPort", func_NtAcceptConnectPort }, { "NtAllocateVirtualMemory", func_NtAllocateVirtualMemory }, { "NtApphelpCacheControl", func_NtApphelpCacheControl }, { "NtContinue", func_NtContinue },