mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-29 12:23:30 +00:00
- 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:
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user