[ros-diffs] [ion] 24670: - Implement NtAcceptConnectPort. This is a naive implementation that doesn't support memory-mapped LPC yet (since it's not used by SMSS). Such LPC messages will hit an ASSERT for now (when they do, I'll implement the missing functionalitY).

ion at svn.reactos.org ion at svn.reactos.org
Mon Oct 30 15:44:06 CET 2006


Author: ion
Date: Mon Oct 30 17:44:05 2006
New Revision: 24670

URL: http://svn.reactos.org/svn/reactos?rev=24670&view=rev
Log:
- Implement NtAcceptConnectPort. This is a naive implementation that doesn't support memory-mapped LPC yet (since it's not used by SMSS). Such LPC messages will hit an ASSERT for now (when they do, I'll implement the missing functionalitY).

Modified:
    trunk/reactos/ntoskrnl/lpc/ntlpc/complete.c

Modified: trunk/reactos/ntoskrnl/lpc/ntlpc/complete.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/ntlpc/complete.c?rev=24670&r1=24669&r2=24670&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/ntlpc/complete.c (original)
+++ trunk/reactos/ntoskrnl/lpc/ntlpc/complete.c Mon Oct 30 17:44:05 2006
@@ -29,8 +29,234 @@
                     IN PPORT_VIEW ClientView,
                     IN PREMOTE_PORT_VIEW ServerView)
 {
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
+    PLPCP_PORT_OBJECT ConnectionPort, ServerPort, ClientPort;
+    PVOID ClientSectionToMap = NULL;
+    HANDLE Handle;
+    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+    NTSTATUS Status;
+    ULONG ConnectionInfoLength;
+    PLPCP_MESSAGE Msg;
+    PLPCP_CONNECTION_MESSAGE ConnectMsg;
+    PEPROCESS ClientProcess;
+    PETHREAD ClientThread;
+    PAGED_CODE();
+    LPCTRACE(LPC_COMPLETE_DEBUG,
+             "Context: %p. Message: %p. Accept: %lx. Views: %p/%p\n",
+             PortContext,
+             ReplyMessage,
+             AcceptConnection,
+             ClientView,
+             ServerView);
+
+    /* Validate the size of the server view */
+    if ((ServerView) && (ServerView->Length != sizeof(PORT_VIEW)))
+    {
+        /* Invalid size */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Validate the size of the client view */
+    if ((ClientView) && (ClientView->Length != sizeof(REMOTE_PORT_VIEW)))
+    {
+        /* Invalid size */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Get the client process and thread */
+    Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId,
+                                        &ClientProcess,
+                                        &ClientThread);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Acquire the LPC Lock */
+    KeAcquireGuardedMutex(&LpcpLock);
+
+    /* Make sure that the client wants a reply, and this is the right one */
+    if (!(ClientThread->LpcReplyMessage) ||
+        !(ReplyMessage->MessageId) ||
+        (ClientThread->LpcReplyMessageId != ReplyMessage->MessageId))
+    {
+        /* Not the reply asked for, or no reply wanted, fail */
+        KeReleaseGuardedMutex(&LpcpLock);
+        ObDereferenceObject(ClientProcess);
+        ObDereferenceObject(ClientThread);
+        return STATUS_REPLY_MESSAGE_MISMATCH;
+    }
+
+    /* Now get the message and connection message */
+    Msg = ClientThread->LpcReplyMessage;
+    ConnectMsg = (PLPCP_CONNECTION_MESSAGE)(Msg + 1);
+
+    /* Get the client and connection port as well */
+    ClientPort = ConnectMsg->ClientPort;
+    ConnectionPort = ClientPort->ConnectionPort;
+
+    /* Make sure that the reply is being sent to the proper server process */
+    if (ConnectionPort->ServerProcess != PsGetCurrentProcess())
+    {
+        /* It's not, so fail */
+        KeReleaseGuardedMutex(&LpcpLock);
+        ObDereferenceObject(ClientProcess);
+        ObDereferenceObject(ClientThread);
+        return STATUS_REPLY_MESSAGE_MISMATCH;
+    }
+
+    /* At this point, don't let other accept attempts happen */
+    ClientThread->LpcReplyMessage = NULL;
+    ClientThread->LpcReplyMessageId = 0;
+
+    /* Clear the client port for now as well, then release the lock */
+    ConnectMsg->ClientPort = NULL;
+    KeReleaseGuardedMutex(&LpcpLock);
+
+    /* Get the connection information length */
+    ConnectionInfoLength = ReplyMessage->u1.s1.DataLength;
+    if (ConnectionInfoLength > ConnectionPort->MaxConnectionInfoLength)
+    {
+        /* Normalize it since it's too large */
+        ConnectionInfoLength = ConnectionPort->MaxConnectionInfoLength;
+    }
+
+    /* Set the sizes of our reply message */
+    Msg->Request.u1.s1.DataLength = sizeof(LPCP_CONNECTION_MESSAGE) +
+                                    ConnectionInfoLength;
+    Msg->Request.u1.s1.TotalLength = sizeof(LPCP_MESSAGE) +
+                                     Msg->Request.u1.s1.DataLength;
+
+    /* Setup the reply message */
+    Msg->Request.u2.s2.Type = LPC_REPLY;
+    Msg->Request.u2.s2.DataInfoOffset = 0;
+    Msg->Request.ClientId = ReplyMessage->ClientId;
+    Msg->Request.MessageId = ReplyMessage->MessageId;
+    Msg->Request.ClientViewSize = 0;
+    RtlMoveMemory(ConnectMsg + 1, ReplyMessage + 1, ConnectionInfoLength);
+
+    /* At this point, if the caller refused the connection, go to cleanup */
+    if (!AcceptConnection) goto Cleanup;
+
+    /* Otherwise, create the actual port */
+    Status = ObCreateObject(PreviousMode,
+                            LpcPortObjectType,
+                            NULL,
+                            PreviousMode,
+                            NULL,
+                            sizeof(LPCP_PORT_OBJECT),
+                            0,
+                            0,
+                            (PVOID*)&ServerPort);
+    if (!NT_SUCCESS(Status)) goto Cleanup;
+
+    /* Set it up */
+    RtlZeroMemory(ServerPort, sizeof(LPCP_PORT_OBJECT));
+    ServerPort->PortContext = PortContext;
+    ServerPort->Flags = LPCP_COMMUNICATION_PORT;
+    ServerPort->MaxMessageLength = ConnectionPort->MaxMessageLength;
+    InitializeListHead(&ServerPort->LpcReplyChainHead);
+    InitializeListHead(&ServerPort->LpcDataInfoChainHead);
+
+    /* Reference the connection port until we're fully setup */
+    ObReferenceObject(ConnectionPort);
+
+    /* Link the ports together */
+    ServerPort->ConnectionPort = ConnectionPort;
+    ServerPort->ConnectedPort = ClientPort;
+    ClientPort->ConnectedPort = ServerPort;
+
+    /* Also set the creator CID */
+    ServerPort->Creator = PsGetCurrentThread()->Cid;
+    ClientPort->Creator = Msg->Request.ClientId;
+
+    /* Get the section associated and then clear it, while inside the lock */
+    KeAcquireGuardedMutex(&LpcpLock);
+    ClientSectionToMap = ConnectMsg->SectionToMap;
+    ConnectMsg->SectionToMap = NULL;
+    KeReleaseGuardedMutex(&LpcpLock);
+
+    /* Now check if there's a client section */
+    if (ClientSectionToMap)
+    {
+        /* FIXME: TODO */
+        ASSERT(FALSE);
+    }
+
+    /* Check if there's a server section */
+    if (ServerView)
+    {
+        /* FIXME: TODO */
+        ASSERT(FALSE);
+    }
+
+    /* Reference the server port until it's fully inserted */
+    ObReferenceObject(ServerPort);
+
+    /* Insert the server port in the namespace */
+    Status = ObInsertObject(ServerPort,
+                            NULL,
+                            PORT_ALL_ACCESS,
+                            0,
+                            NULL,
+                            &Handle);
+    if (!NT_SUCCESS(Status))
+    {
+        /* We failed, remove the extra reference and cleanup */
+        ObDereferenceObject(ServerPort);
+        goto Cleanup;
+    }
+
+    /* Check if the caller gave a client view */
+    if (ClientView)
+    {
+        /* Fill it out */
+        ClientView->ViewBase = ConnectMsg->ClientView.ViewRemoteBase;
+        ClientView->ViewSize = ConnectMsg->ClientView.ViewSize;
+    }
+
+    /* Return the handle to user mode */
+    *PortHandle = Handle;
+    LPCTRACE(LPC_COMPLETE_DEBUG,
+             "Handle: %lx. Messages: %p/%p. Ports: %p/%p/%p\n",
+             Handle,
+             Msg,
+             ConnectMsg,
+             ServerPort,
+             ClientPort,
+             ConnectionPort);
+
+    /* If there was no port context, use the handle by default */
+    if (!PortContext) ServerPort->PortContext = Handle;
+    ServerPort->ClientThread = ClientThread;
+
+    /* Set this message as the LPC Reply message while holding the lock */
+    KeAcquireGuardedMutex(&LpcpLock);
+    ClientThread->LpcReplyMessage = Msg;
+    KeReleaseGuardedMutex(&LpcpLock);
+
+    /* Clear the thread pointer so it doesn't get cleaned later */
+    ClientThread = NULL;
+
+    /* Remove the extra reference we had added */
+    ObDereferenceObject(ServerPort);
+
+Cleanup:
+    /* If there was a section, dereference it */
+    if (ClientSectionToMap) ObDereferenceObject(ClientSectionToMap);
+
+    /* Check if we got here while still having a client thread */
+    if (ClientThread)
+    {
+        /* FIXME: Complex cleanup code */
+        ASSERT(FALSE);
+    }
+
+    /* Dereference the client port if we have one, and the process */
+    LPCTRACE(LPC_COMPLETE_DEBUG,
+             "Status: %lx. Thread: %p. Process: [%.16s]\n",
+             Status,
+             ClientThread,
+             ClientProcess->ImageFileName);
+    if (ClientPort) ObDereferenceObject(ClientPort);
+    ObDereferenceObject(ClientProcess);
+    return Status;
 }
 
 /*




More information about the Ros-diffs mailing list