⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reply.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
        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 + -