mirror of
https://github.com/reactos/reactos.git
synced 2024-07-03 19:24:20 +00:00
SEH protect NtReplyWaitReceivePortEx and fix one instance of message type checking to correctly account for kernel LPC messages.
svn path=/trunk/; revision=33428
This commit is contained in:
parent
973109beb4
commit
a907b85b1a
|
@ -160,11 +160,14 @@ NtReplyWaitReceivePortEx(IN HANDLE PortHandle,
|
||||||
{
|
{
|
||||||
PLPCP_PORT_OBJECT Port, ReceivePort, ConnectionPort = NULL;
|
PLPCP_PORT_OBJECT Port, ReceivePort, ConnectionPort = NULL;
|
||||||
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(), WaitMode = PreviousMode;
|
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(), WaitMode = PreviousMode;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
PLPCP_MESSAGE Message;
|
PLPCP_MESSAGE Message;
|
||||||
PETHREAD Thread = PsGetCurrentThread(), WakeupThread;
|
PETHREAD Thread = PsGetCurrentThread(), WakeupThread;
|
||||||
PLPCP_CONNECTION_MESSAGE ConnectMessage;
|
PLPCP_CONNECTION_MESSAGE ConnectMessage;
|
||||||
ULONG ConnectionInfoLength;
|
ULONG ConnectionInfoLength;
|
||||||
|
PORT_MESSAGE CapturedReplyMessage;
|
||||||
|
LARGE_INTEGER CapturedTimeout;
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
LPCTRACE(LPC_REPLY_DEBUG,
|
LPCTRACE(LPC_REPLY_DEBUG,
|
||||||
"Handle: %lx. Messages: %p/%p. Context: %p\n",
|
"Handle: %lx. Messages: %p/%p. Context: %p\n",
|
||||||
|
@ -173,8 +176,42 @@ NtReplyWaitReceivePortEx(IN HANDLE PortHandle,
|
||||||
ReceiveMessage,
|
ReceiveMessage,
|
||||||
PortContext);
|
PortContext);
|
||||||
|
|
||||||
/* If this is a system thread, then let it page out its stack */
|
if (KeGetPreviousMode() == UserMode)
|
||||||
if (Thread->SystemThread) WaitMode = UserMode;
|
{
|
||||||
|
_SEH_TRY
|
||||||
|
{
|
||||||
|
if (ReplyMessage != NULL)
|
||||||
|
{
|
||||||
|
ProbeForRead(ReplyMessage, sizeof(PORT_MESSAGE), sizeof(ULONG));
|
||||||
|
RtlCopyMemory(&CapturedReplyMessage, ReplyMessage, sizeof(PORT_MESSAGE));
|
||||||
|
ReplyMessage = &CapturedReplyMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Timeout != NULL)
|
||||||
|
{
|
||||||
|
ProbeForReadLargeInteger(Timeout);
|
||||||
|
RtlCopyMemory(&CapturedTimeout, Timeout, sizeof(LARGE_INTEGER));
|
||||||
|
Timeout = &CapturedTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PortContext != NULL)
|
||||||
|
ProbeForWritePointer(PortContext);
|
||||||
|
}
|
||||||
|
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
|
||||||
|
{
|
||||||
|
Status = _SEH_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH_END;
|
||||||
|
|
||||||
|
/* Bail out if pointer was invalid */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If this is a system thread, then let it page out its stack */
|
||||||
|
if (Thread->SystemThread) WaitMode = UserMode;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if caller has a reply message */
|
/* Check if caller has a reply message */
|
||||||
if (ReplyMessage)
|
if (ReplyMessage)
|
||||||
|
@ -388,68 +425,76 @@ NtReplyWaitReceivePortEx(IN HANDLE PortHandle,
|
||||||
Thread->LpcReceivedMessageId = Message->Request.MessageId;
|
Thread->LpcReceivedMessageId = Message->Request.MessageId;
|
||||||
Thread->LpcReceivedMsgIdValid = TRUE;
|
Thread->LpcReceivedMsgIdValid = TRUE;
|
||||||
|
|
||||||
/* Check if this was a connection request */
|
_SEH_TRY
|
||||||
if (LpcpGetMessageType(&Message->Request) == LPC_CONNECTION_REQUEST)
|
|
||||||
{
|
{
|
||||||
/* Get the connection message */
|
/* Check if this was a connection request */
|
||||||
ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
|
if (LpcpGetMessageType(&Message->Request) == LPC_CONNECTION_REQUEST)
|
||||||
LPCTRACE(LPC_REPLY_DEBUG,
|
|
||||||
"Request Messages: %p/%p\n",
|
|
||||||
Message,
|
|
||||||
ConnectMessage);
|
|
||||||
|
|
||||||
/* Get its length */
|
|
||||||
ConnectionInfoLength = Message->Request.u1.s1.DataLength -
|
|
||||||
sizeof(LPCP_CONNECTION_MESSAGE);
|
|
||||||
|
|
||||||
/* Return it as the receive message */
|
|
||||||
*ReceiveMessage = Message->Request;
|
|
||||||
|
|
||||||
/* Clear our stack variable so the message doesn't get freed */
|
|
||||||
Message = NULL;
|
|
||||||
|
|
||||||
/* Setup the receive message */
|
|
||||||
ReceiveMessage->u1.s1.TotalLength = (CSHORT)(sizeof(LPCP_MESSAGE) +
|
|
||||||
ConnectionInfoLength);
|
|
||||||
ReceiveMessage->u1.s1.DataLength = (CSHORT)ConnectionInfoLength;
|
|
||||||
RtlCopyMemory(ReceiveMessage + 1,
|
|
||||||
ConnectMessage + 1,
|
|
||||||
ConnectionInfoLength);
|
|
||||||
|
|
||||||
/* Clear the port context if the caller requested one */
|
|
||||||
if (PortContext) *PortContext = NULL;
|
|
||||||
}
|
|
||||||
else if (Message->Request.u2.s2.Type != LPC_REPLY)
|
|
||||||
{
|
|
||||||
/* Otherwise, this is a new message or event */
|
|
||||||
LPCTRACE(LPC_REPLY_DEBUG,
|
|
||||||
"Non-Reply Messages: %p/%p\n",
|
|
||||||
&Message->Request,
|
|
||||||
(&Message->Request) + 1);
|
|
||||||
|
|
||||||
/* Copy it */
|
|
||||||
LpcpMoveMessage(ReceiveMessage,
|
|
||||||
&Message->Request,
|
|
||||||
(&Message->Request) + 1,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
/* Return its context */
|
|
||||||
if (PortContext) *PortContext = Message->PortContext;
|
|
||||||
|
|
||||||
/* And check if it has data information */
|
|
||||||
if (Message->Request.u2.s2.DataInfoOffset)
|
|
||||||
{
|
{
|
||||||
/* It does, save it, and don't free the message below */
|
/* Get the connection message */
|
||||||
LpcpSaveDataInfoMessage(Port, Message, 1);
|
ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
|
||||||
|
LPCTRACE(LPC_REPLY_DEBUG,
|
||||||
|
"Request Messages: %p/%p\n",
|
||||||
|
Message,
|
||||||
|
ConnectMessage);
|
||||||
|
|
||||||
|
/* Get its length */
|
||||||
|
ConnectionInfoLength = Message->Request.u1.s1.DataLength -
|
||||||
|
sizeof(LPCP_CONNECTION_MESSAGE);
|
||||||
|
|
||||||
|
/* Return it as the receive message */
|
||||||
|
*ReceiveMessage = Message->Request;
|
||||||
|
|
||||||
|
/* Clear our stack variable so the message doesn't get freed */
|
||||||
Message = NULL;
|
Message = NULL;
|
||||||
|
|
||||||
|
/* Setup the receive message */
|
||||||
|
ReceiveMessage->u1.s1.TotalLength = (CSHORT)(sizeof(LPCP_MESSAGE) +
|
||||||
|
ConnectionInfoLength);
|
||||||
|
ReceiveMessage->u1.s1.DataLength = (CSHORT)ConnectionInfoLength;
|
||||||
|
RtlCopyMemory(ReceiveMessage + 1,
|
||||||
|
ConnectMessage + 1,
|
||||||
|
ConnectionInfoLength);
|
||||||
|
|
||||||
|
/* Clear the port context if the caller requested one */
|
||||||
|
if (PortContext) *PortContext = NULL;
|
||||||
|
}
|
||||||
|
else if (LpcpGetMessageType(&Message->Request) != LPC_REPLY)
|
||||||
|
{
|
||||||
|
/* Otherwise, this is a new message or event */
|
||||||
|
LPCTRACE(LPC_REPLY_DEBUG,
|
||||||
|
"Non-Reply Messages: %p/%p\n",
|
||||||
|
&Message->Request,
|
||||||
|
(&Message->Request) + 1);
|
||||||
|
|
||||||
|
/* Copy it */
|
||||||
|
LpcpMoveMessage(ReceiveMessage,
|
||||||
|
&Message->Request,
|
||||||
|
(&Message->Request) + 1,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Return its context */
|
||||||
|
if (PortContext) *PortContext = Message->PortContext;
|
||||||
|
|
||||||
|
/* And check if it has data information */
|
||||||
|
if (Message->Request.u2.s2.DataInfoOffset)
|
||||||
|
{
|
||||||
|
/* It does, save it, and don't free the message below */
|
||||||
|
LpcpSaveDataInfoMessage(Port, Message, 1);
|
||||||
|
Message = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This is a reply message, should never happen! */
|
||||||
|
ASSERT(FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
|
||||||
{
|
{
|
||||||
/* This is a reply message, should never happen! */
|
Status = _SEH_GetExceptionCode();
|
||||||
ASSERT(FALSE);
|
|
||||||
}
|
}
|
||||||
|
_SEH_END;
|
||||||
|
|
||||||
/* Check if we have a message pointer here */
|
/* Check if we have a message pointer here */
|
||||||
if (Message)
|
if (Message)
|
||||||
|
|
Loading…
Reference in a new issue