- 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).

svn path=/trunk/; revision=24670
This commit is contained in:
Alex Ionescu
2006-10-30 14:44:05 +00:00
parent 2624bc881d
commit ed9d7c1816
+228 -2
View File
@@ -29,8 +29,234 @@ NtAcceptConnectPort(OUT PHANDLE PortHandle,
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;
}
/*