📄 connect.c
字号:
}
/* Update the base */
ClientView->ViewBase = Port->ClientSectionBase;
}
else
{
/* No section */
SectionToMap = NULL;
}
/* Normalize connection information */
if (ConnectionInfoLength > Port->MaxConnectionInfoLength)
{
/* Use the port's maximum allowed value */
ConnectionInfoLength = Port->MaxConnectionInfoLength;
}
/* Allocate a message from the port zone */
Message = LpcpAllocateFromPortZone();
if (!Message)
{
/* Fail if we couldn't allocate a message */
if (SectionToMap) ObDereferenceObject(SectionToMap);
ObDereferenceObject(ClientPort);
return STATUS_NO_MEMORY;
}
/* Set pointer to the connection message and fill in the CID */
ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
Message->Request.ClientId = Thread->Cid;
/* Check if we have a client view */
if (ClientView)
{
/* Set the view size */
Message->Request.ClientViewSize = ClientView->ViewSize;
/* Copy the client view and clear the server view */
RtlMoveMemory(&ConnectMessage->ClientView,
ClientView,
sizeof(PORT_VIEW));
RtlZeroMemory(&ConnectMessage->ServerView, sizeof(REMOTE_PORT_VIEW));
}
else
{
/* Set the size to 0 and clear the connect message */
Message->Request.ClientViewSize = 0;
RtlZeroMemory(ConnectMessage, sizeof(LPCP_CONNECTION_MESSAGE));
}
/* Set the section and client port. Port is NULL for now */
ConnectMessage->ClientPort = NULL;
ConnectMessage->SectionToMap = SectionToMap;
/* Set the data for the connection request message */
Message->Request.u1.s1.DataLength = sizeof(LPCP_CONNECTION_MESSAGE) +
ConnectionInfoLength;
Message->Request.u1.s1.TotalLength = sizeof(LPCP_MESSAGE) +
Message->Request.u1.s1.DataLength;
Message->Request.u2.s2.Type = LPC_CONNECTION_REQUEST;
/* Check if we have connection information */
if (ConnectionInformation)
{
/* Copy it in */
RtlMoveMemory(ConnectMessage + 1,
ConnectionInformation,
ConnectionInfoLength);
}
/* Acquire the port lock */
KeAcquireGuardedMutex(&LpcpLock);
/* Check if someone already deleted the port name */
if (Port->Flags & LPCP_NAME_DELETED)
{
/* Fail the request */
KeReleaseGuardedMutex(&LpcpLock);
Status = STATUS_OBJECT_NAME_NOT_FOUND;
goto Cleanup;
}
/* Associate no thread yet */
Message->RepliedToThread = NULL;
/* Generate the Message ID and set it */
Message->Request.MessageId = LpcpNextMessageId++;
if (!LpcpNextMessageId) LpcpNextMessageId = 1;
Thread->LpcReplyMessageId = Message->Request.MessageId;
/* Insert the message into the queue and thread chain */
InsertTailList(&Port->MsgQueue.ReceiveHead, &Message->Entry);
InsertTailList(&Port->LpcReplyChainHead, &Thread->LpcReplyChain);
Thread->LpcReplyMessage = Message;
/* Now we can finally reference the client port and link it*/
ObReferenceObject(ClientPort);
ConnectMessage->ClientPort = ClientPort;
/* Release the lock */
KeReleaseGuardedMutex(&LpcpLock);
LPCTRACE(LPC_CONNECT_DEBUG,
"Messages: %p/%p. Ports: %p/%p. Status: %lx\n",
Message,
ConnectMessage,
Port,
ClientPort,
Status);
/* If this is a waitable port, set the event */
if (Port->Flags & LPCP_WAITABLE_PORT) KeSetEvent(&Port->WaitEvent,
1,
FALSE);
/* Release the queue semaphore */
LpcpCompleteWait(Port->MsgQueue.Semaphore);
/* Now wait for a reply */
LpcpConnectWait(&Thread->LpcReplySemaphore, PreviousMode);
/* Check if our wait ended in success */
if (Status != STATUS_SUCCESS) goto Cleanup;
/* Free the connection message */
SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread);
/* Check if we got a message back */
if (Message)
{
/* Check for new return length */
if ((Message->Request.u1.s1.DataLength -
sizeof(LPCP_CONNECTION_MESSAGE)) < ConnectionInfoLength)
{
/* Set new normalized connection length */
ConnectionInfoLength = Message->Request.u1.s1.DataLength -
sizeof(LPCP_CONNECTION_MESSAGE);
}
/* Check if we had connection information */
if (ConnectionInformation)
{
/* Check if we had a length pointer */
if (ConnectionInformationLength)
{
/* Return the length */
*ConnectionInformationLength = ConnectionInfoLength;
}
/* Return the connection information */
RtlMoveMemory(ConnectionInformation,
ConnectMessage + 1,
ConnectionInfoLength );
}
/* Make sure we had a connected port */
if (ClientPort->ConnectedPort)
{
/* Get the message length before the port might get killed */
PortMessageLength = Port->MaxMessageLength;
/* Insert the client port */
Status = ObInsertObject(ClientPort,
NULL,
PORT_ALL_ACCESS,
0,
(PVOID *)NULL,
&Handle);
if (NT_SUCCESS(Status))
{
/* Return the handle */
*PortHandle = Handle;
LPCTRACE(LPC_CONNECT_DEBUG,
"Handle: %lx. Length: %lx\n",
Handle,
PortMessageLength);
/* Check if maximum length was requested */
if (MaxMessageLength) *MaxMessageLength = PortMessageLength;
/* Check if we had a client view */
if (ClientView)
{
/* Copy it back */
RtlMoveMemory(ClientView,
&ConnectMessage->ClientView,
sizeof(PORT_VIEW));
}
/* Check if we had a server view */
if (ServerView)
{
/* Copy it back */
RtlMoveMemory(ServerView,
&ConnectMessage->ServerView,
sizeof(REMOTE_PORT_VIEW));
}
}
}
else
{
/* No connection port, we failed */
if (SectionToMap) ObDereferenceObject(SectionToMap);
/* Check if it's because the name got deleted */
if (Port->Flags & LPCP_NAME_DELETED)
{
/* Set the correct status */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
else
{
/* Otherwise, the caller refused us */
Status = STATUS_PORT_CONNECTION_REFUSED;
}
/* Kill the port */
ObDereferenceObject(ClientPort);
}
/* Free the message */
LpcpFreeToPortZone(Message, FALSE);
return Status;
}
/* No reply message, fail */
if (SectionToMap) ObDereferenceObject(SectionToMap);
ObDereferenceObject(ClientPort);
return STATUS_PORT_CONNECTION_REFUSED;
Cleanup:
/* We failed, free the message */
SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread);
/* Check if the semaphore got signaled */
if (KeReadStateSemaphore(&Thread->LpcReplySemaphore))
{
/* Wait on it */
KeWaitForSingleObject(&Thread->LpcReplySemaphore,
KernelMode,
Executive,
FALSE,
NULL);
}
/* Check if we had a message and free it */
if (Message) LpcpFreeToPortZone(Message, FALSE);
/* Dereference other objects */
if (SectionToMap) ObDereferenceObject(SectionToMap);
ObDereferenceObject(ClientPort);
/* Return status */
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
NtConnectPort(OUT PHANDLE PortHandle,
IN PUNICODE_STRING PortName,
IN PSECURITY_QUALITY_OF_SERVICE Qos,
IN PPORT_VIEW ClientView,
IN PREMOTE_PORT_VIEW ServerView,
OUT PULONG MaxMessageLength,
IN PVOID ConnectionInformation,
OUT PULONG ConnectionInformationLength)
{
/* Call the newer API */
return NtSecureConnectPort(PortHandle,
PortName,
Qos,
ClientView,
NULL,
ServerView,
MaxMessageLength,
ConnectionInformation,
ConnectionInformationLength);
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -