📄 connect.c
字号:
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/lpc/connect.c
* PURPOSE: Local Procedure Call: Connection Management
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#include "lpc.h"
#define NDEBUG
#include <internal/debug.h>
/* PRIVATE FUNCTIONS *********************************************************/
PVOID
NTAPI
LpcpFreeConMsg(IN OUT PLPCP_MESSAGE *Message,
IN OUT PLPCP_CONNECTION_MESSAGE *ConnectMessage,
IN PETHREAD CurrentThread)
{
PVOID SectionToMap;
/* Acquire the LPC lock */
KeAcquireGuardedMutex(&LpcpLock);
/* Check if the reply chain is not empty */
if (!IsListEmpty(&CurrentThread->LpcReplyChain))
{
/* Remove this entry and re-initialize it */
RemoveEntryList(&CurrentThread->LpcReplyChain);
InitializeListHead(&CurrentThread->LpcReplyChain);
}
/* Check if there's a reply message */
if (CurrentThread->LpcReplyMessage)
{
/* Get the message */
*Message = CurrentThread->LpcReplyMessage;
/* Clear message data */
CurrentThread->LpcReceivedMessageId = 0;
CurrentThread->LpcReplyMessage = NULL;
/* Get the connection message and clear the section */
*ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(*Message + 1);
SectionToMap = (*ConnectMessage)->SectionToMap;
(*ConnectMessage)->SectionToMap = NULL;
}
else
{
/* No message to return */
*Message = NULL;
SectionToMap = NULL;
}
/* Release the lock and return the section */
KeReleaseGuardedMutex(&LpcpLock);
return SectionToMap;
}
/* PUBLIC FUNCTIONS **********************************************************/
/*
* @implemented
*/
NTSTATUS
NTAPI
NtSecureConnectPort(OUT PHANDLE PortHandle,
IN PUNICODE_STRING PortName,
IN PSECURITY_QUALITY_OF_SERVICE Qos,
IN OUT PPORT_VIEW ClientView OPTIONAL,
IN PSID ServerSid OPTIONAL,
IN OUT PREMOTE_PORT_VIEW ServerView OPTIONAL,
OUT PULONG MaxMessageLength OPTIONAL,
IN OUT PVOID ConnectionInformation OPTIONAL,
IN OUT PULONG ConnectionInformationLength OPTIONAL)
{
ULONG ConnectionInfoLength = 0;
PLPCP_PORT_OBJECT Port, ClientPort;
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
HANDLE Handle;
PVOID SectionToMap;
PLPCP_MESSAGE Message;
PLPCP_CONNECTION_MESSAGE ConnectMessage;
PETHREAD Thread = PsGetCurrentThread();
ULONG PortMessageLength;
LARGE_INTEGER SectionOffset;
PTOKEN Token;
PTOKEN_USER TokenUserInfo;
PAGED_CODE();
LPCTRACE(LPC_CONNECT_DEBUG,
"Name: %wZ. Qos: %p. Views: %p/%p. Sid: %p\n",
PortName,
Qos,
ClientView,
ServerView,
ServerSid);
/* Validate client view */
if ((ClientView) && (ClientView->Length != sizeof(PORT_VIEW)))
{
/* Fail */
return STATUS_INVALID_PARAMETER;
}
/* Validate server view */
if ((ServerView) && (ServerView->Length != sizeof(REMOTE_PORT_VIEW)))
{
/* Fail */
return STATUS_INVALID_PARAMETER;
}
/* Check if caller sent connection information length */
if (ConnectionInformationLength)
{
/* Retrieve the input length */
ConnectionInfoLength = *ConnectionInformationLength;
}
/* Get the port */
Status = ObReferenceObjectByName(PortName,
0,
NULL,
PORT_ALL_ACCESS,
LpcPortObjectType,
PreviousMode,
NULL,
(PVOID *)&Port);
if (!NT_SUCCESS(Status)) return Status;
/* This has to be a connection port */
if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT)
{
/* It isn't, so fail */
ObDereferenceObject(Port);
return STATUS_INVALID_PORT_HANDLE;
}
/* Check if we have a SID */
if (ServerSid)
{
/* Make sure that we have a server */
if (Port->ServerProcess)
{
/* Get its token and query user information */
Token = PsReferencePrimaryToken(Port->ServerProcess);
//Status = SeQueryInformationToken(Token, TokenUser, (PVOID*)&TokenUserInfo);
// FIXME: Need SeQueryInformationToken
Status = STATUS_SUCCESS;
TokenUserInfo = ExAllocatePool(PagedPool, sizeof(TOKEN_USER));
TokenUserInfo->User.Sid = ServerSid;
PsDereferencePrimaryToken(Token);
/* Check for success */
if (NT_SUCCESS(Status))
{
/* Compare the SIDs */
if (!RtlEqualSid(ServerSid, TokenUserInfo->User.Sid))
{
/* Fail */
Status = STATUS_SERVER_SID_MISMATCH;
}
/* Free token information */
ExFreePool(TokenUserInfo);
}
}
else
{
/* Invalid SID */
Status = STATUS_SERVER_SID_MISMATCH;
}
/* Check if SID failed */
if (!NT_SUCCESS(Status))
{
/* Quit */
ObDereferenceObject(Port);
return Status;
}
}
/* Create the client port */
Status = ObCreateObject(PreviousMode,
LpcPortObjectType,
NULL,
PreviousMode,
NULL,
sizeof(LPCP_PORT_OBJECT),
0,
0,
(PVOID *)&ClientPort);
if (!NT_SUCCESS(Status))
{
/* Failed, dereference the server port and return */
ObDereferenceObject(Port);
return Status;
}
/* Setup the client port */
RtlZeroMemory(ClientPort, sizeof(LPCP_PORT_OBJECT));
ClientPort->Flags = LPCP_CLIENT_PORT;
ClientPort->ConnectionPort = Port;
ClientPort->MaxMessageLength = Port->MaxMessageLength;
ClientPort->SecurityQos = *Qos;
InitializeListHead(&ClientPort->LpcReplyChainHead);
InitializeListHead(&ClientPort->LpcDataInfoChainHead);
/* Check if we have dynamic security */
if (Qos->ContextTrackingMode == SECURITY_DYNAMIC_TRACKING)
{
/* Remember that */
ClientPort->Flags |= LPCP_SECURITY_DYNAMIC;
}
else
{
/* Create our own client security */
Status = SeCreateClientSecurity(Thread,
Qos,
FALSE,
&ClientPort->StaticSecurity);
if (!NT_SUCCESS(Status))
{
/* Security failed, dereference and return */
ObDereferenceObject(ClientPort);
return Status;
}
}
/* Initialize the port queue */
Status = LpcpInitializePortQueue(ClientPort);
if (!NT_SUCCESS(Status))
{
/* Failed */
ObDereferenceObject(ClientPort);
return Status;
}
/* Check if we have a client view */
if (ClientView)
{
/* Get the section handle */
Status = ObReferenceObjectByHandle(ClientView->SectionHandle,
SECTION_MAP_READ |
SECTION_MAP_WRITE,
MmSectionObjectType,
PreviousMode,
(PVOID*)&SectionToMap,
NULL);
if (!NT_SUCCESS(Status))
{
/* Fail */
ObDereferenceObject(Port);
return Status;
}
/* Set the section offset */
SectionOffset.QuadPart = ClientView->SectionOffset;
/* Map it */
Status = MmMapViewOfSection(SectionToMap,
PsGetCurrentProcess(),
&Port->ClientSectionBase,
0,
0,
&SectionOffset,
&ClientView->ViewSize,
ViewUnmap,
0,
PAGE_READWRITE);
/* Update the offset */
ClientView->SectionOffset = SectionOffset.LowPart;
/* Check for failure */
if (!NT_SUCCESS(Status))
{
/* Fail */
ObDereferenceObject(SectionToMap);
ObDereferenceObject(Port);
return Status;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -