📄 reply.c
字号:
if (WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId)
{
/* It isn't, fail */
LpcpFreeToPortZone(Message, TRUE);
KeReleaseGuardedMutex(&LpcpLock);
ObDereferenceObject(WakeupThread);
ObDereferenceObject(Port);
return STATUS_REPLY_MESSAGE_MISMATCH;
}
/* Copy the message */
LpcpMoveMessage(&Message->Request,
ReplyMessage,
ReplyMessage + 1,
LPC_REPLY,
NULL);
/* Free any data information */
LpcpFreeDataInfoMessage(Port,
ReplyMessage->MessageId,
ReplyMessage->CallbackId);
/* Reference the thread while we use it */
ObReferenceObject(WakeupThread);
Message->RepliedToThread = WakeupThread;
/* Set this as the reply message */
WakeupThread->LpcReplyMessageId = 0;
WakeupThread->LpcReplyMessage = (PVOID)Message;
/* Check if we have messages on the reply chain */
if (!(WakeupThread->LpcExitThreadCalled) &&
!(IsListEmpty(&WakeupThread->LpcReplyChain)))
{
/* Remove us from it and reinitialize it */
RemoveEntryList(&WakeupThread->LpcReplyChain);
InitializeListHead(&WakeupThread->LpcReplyChain);
}
/* Check if this is the message the thread had received */
if ((Thread->LpcReceivedMsgIdValid) &&
(Thread->LpcReceivedMessageId == ReplyMessage->MessageId))
{
/* Clear this data */
Thread->LpcReceivedMessageId = 0;
Thread->LpcReceivedMsgIdValid = FALSE;
}
/* Release the lock and release the LPC semaphore to wake up waiters */
KeReleaseGuardedMutex(&LpcpLock);
LpcpCompleteWait(&WakeupThread->LpcReplySemaphore);
/* Now we can let go of the thread */
ObDereferenceObject(WakeupThread);
}
/* Now wait for someone to reply to us */
LpcpReceiveWait(ReceivePort->MsgQueue.Semaphore, WaitMode);
if (Status != STATUS_SUCCESS) goto Cleanup;
/* Wait done, get the LPC lock */
KeAcquireGuardedMutex(&LpcpLock);
/* Check if we've received nothing */
if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead))
{
/* Check if this was a waitable port and wake it */
if (ReceivePort->Flags & LPCP_WAITABLE_PORT)
{
/* Reset its event */
KeResetEvent(&ReceivePort->WaitEvent);
}
/* Release the lock and fail */
KeReleaseGuardedMutex(&LpcpLock);
ObDereferenceObject(Port);
return STATUS_UNSUCCESSFUL;
}
/* Get the message on the queue */
Message = CONTAINING_RECORD(RemoveHeadList(&ReceivePort->
MsgQueue.ReceiveHead),
LPCP_MESSAGE,
Entry);
/* Check if the queue is empty now */
if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead))
{
/* Check if this was a waitable port */
if (ReceivePort->Flags & LPCP_WAITABLE_PORT)
{
/* Reset its event */
KeResetEvent(&ReceivePort->WaitEvent);
}
}
/* Re-initialize the message's list entry */
InitializeListHead(&Message->Entry);
/* Set this as the received message */
Thread->LpcReceivedMessageId = Message->Request.MessageId;
Thread->LpcReceivedMsgIdValid = TRUE;
/* Done touching global data, release the lock */
KeReleaseGuardedMutex(&LpcpLock);
/* Check if this was a connection request */
if (LpcpGetMessageType(&Message->Request) == LPC_CONNECTION_REQUEST)
{
/* Get the connection message */
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;
/* Setup the receive message */
ReceiveMessage->u1.s1.TotalLength = sizeof(LPCP_MESSAGE) +
ConnectionInfoLength;
ReceiveMessage->u1.s1.DataLength = ConnectionInfoLength;
RtlMoveMemory(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 */
LpcpSaveDataInfoMessage(Port, Message);
Message = NULL;
}
}
else
{
/* This is a reply message, should never happen! */
ASSERT(FALSE);
}
/* If we have a message pointer here, free it */
if (Message) LpcpFreeToPortZone(Message, FALSE);
Cleanup:
/* All done, dereference the port and return the status */
LPCTRACE(LPC_REPLY_DEBUG,
"Port: %p. Status: %p\n",
Port,
Status);
ObDereferenceObject(Port);
return Status;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
NtReplyWaitReceivePort(IN HANDLE PortHandle,
OUT PVOID *PortContext OPTIONAL,
IN PPORT_MESSAGE ReplyMessage OPTIONAL,
OUT PPORT_MESSAGE ReceiveMessage)
{
/* Call the newer API */
return NtReplyWaitReceivePortEx(PortHandle,
PortContext,
ReplyMessage,
ReceiveMessage,
NULL);
}
/*
* @unimplemented
*/
NTSTATUS
NTAPI
NtReplyWaitReplyPort(IN HANDLE PortHandle,
IN PPORT_MESSAGE ReplyMessage)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*
* @unimplemented
*/
NTSTATUS
NTAPI
NtReadRequestData(IN HANDLE PortHandle,
IN PPORT_MESSAGE Message,
IN ULONG Index,
IN PVOID Buffer,
IN ULONG BufferLength,
OUT PULONG Returnlength)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*
* @unimplemented
*/
NTSTATUS
NTAPI
NtWriteRequestData(IN HANDLE PortHandle,
IN PPORT_MESSAGE Message,
IN ULONG Index,
IN PVOID Buffer,
IN ULONG BufferLength,
OUT PULONG ReturnLength)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -