- Fix implementation of message callbacks,  now callbacks can be called across processes. 
- Fix some comments.

svn path=/trunk/; revision=51332
This commit is contained in:
Michael Martin 2011-04-14 01:21:38 +00:00
parent 1968375672
commit 3203ddd6e1
2 changed files with 79 additions and 21 deletions

View file

@ -1425,8 +1425,8 @@ co_IntSendMessageWithCallBack( HWND hWnd,
RETURN( FALSE);
}
/* If this is not a callback and it can be sent now, then send it. */
if ((Window->head.pti->MessageQueue == Win32Thread->MessageQueue) && (CompletionCallback == NULL))
/* If it can be sent now, then send it. */
if (Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
{
if (Win32Thread->TIF_flags & TIF_INCLEANUP)
{
@ -1452,11 +1452,20 @@ co_IntSendMessageWithCallBack( HWND hWnd,
ObDereferenceObject(Win32Thread->pEThread);
IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
if (CompletionCallback)
{
co_IntCallSentMessageCallback(CompletionCallback,
hWnd,
Msg,
CompletionCallbackContext,
Result);
}
}
if ((Window->head.pti->MessageQueue == Win32Thread->MessageQueue) && (CompletionCallback == NULL))
if (Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
{
if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
{
@ -1471,6 +1480,12 @@ co_IntSendMessageWithCallBack( HWND hWnd,
RETURN( FALSE);
}
IntReferenceMessageQueue(Window->head.pti->MessageQueue);
/* Take reference on this MessageQueue if its a callback. It will be released
when message is processed or removed from target hwnd MessageQueue */
if (CompletionCallback)
IntReferenceMessageQueue(Win32Thread->MessageQueue);
Message->Msg.hwnd = hWnd;
Message->Msg.message = Msg;
Message->Msg.wParam = wParam;
@ -1482,8 +1497,6 @@ co_IntSendMessageWithCallBack( HWND hWnd,
Message->SenderQueue = NULL; // mjmartin, you are right! This is null.
Message->CallBackSenderQueue = Win32Thread->MessageQueue;
Message->DispatchingListEntry.Flink = NULL;
IntReferenceMessageQueue(Window->head.pti->MessageQueue);
Message->CompletionCallback = CompletionCallback;
Message->CompletionCallbackContext = CompletionCallbackContext;
Message->HookMessage = MSQ_NORMAL;
@ -1492,7 +1505,6 @@ co_IntSendMessageWithCallBack( HWND hWnd,
InsertTailList(&Window->head.pti->MessageQueue->SentMessagesListHead, &Message->ListEntry);
MsqWakeQueue(Window->head.pti->MessageQueue, QS_SENDMESSAGE, TRUE);
IntDereferenceMessageQueue(Window->head.pti->MessageQueue);
RETURN(TRUE);

View file

@ -588,6 +588,28 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
Message->Msg.wParam,
Message->Msg.lParam);
}
else if ((Message->CompletionCallback)
&& (Message->CallBackSenderQueue == MessageQueue))
{ /* Call the callback routine */
if (Message->QS_Flags & QS_SMRESULT)
{
co_IntCallSentMessageCallback(Message->CompletionCallback,
Message->Msg.hwnd,
Message->Msg.message,
Message->CompletionCallbackContext,
Message->lResult);
/* Set callback to NULL to prevent reentry */
Message->CompletionCallback = NULL;
}
else
{
/* The message has not been processed yet, reinsert it. */
RemoveEntryList(&Message->ListEntry);
InsertTailList(&Message->CallBackSenderQueue->SentMessagesListHead, &Message->ListEntry);
DPRINT("Callback Message not processed yet. Requeuing the message\n");
return (FALSE);
}
}
else
{ /* Call the window procedure. */
Result = co_IntSendMessage( Message->Msg.hwnd,
@ -600,6 +622,22 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
to be cleaned up on thread termination anymore */
RemoveEntryList(&Message->ListEntry);
/* If the message is a callback, insert it in the callback senders MessageQueue */
if (Message->CompletionCallback)
{
if (Message->CallBackSenderQueue)
{
Message->lResult = Result;
Message->QS_Flags |= QS_SMRESULT;
/* insert it in the callers message queue */
InsertTailList(&Message->CallBackSenderQueue->SentMessagesListHead, &Message->ListEntry);
MsqWakeQueue(Message->CallBackSenderQueue, QS_SENDMESSAGE, TRUE);
IntDereferenceMessageQueue(Message->CallBackSenderQueue);
}
return (TRUE);
}
/* remove the message from the dispatching list if needed, so lock the sender's message queue */
if (Message->SenderQueue)
{
@ -635,19 +673,10 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
KeSetEvent(Message->CompletionEvent, IO_NO_INCREMENT, FALSE);
}
/* Call the callback if the message was sent with SendMessageCallback */
if (Message->CompletionCallback != NULL)
{
co_IntCallSentMessageCallback(Message->CompletionCallback,
Message->Msg.hwnd,
Message->Msg.message,
Message->CompletionCallbackContext,
Result);
}
/* Only if the message has a sender was the queue referenced */
/* if the message has a sender */
if (Message->SenderQueue)
{
/* dereference our and the sender's message queue */
IntDereferenceMessageQueue(Message->SenderQueue);
IntDereferenceMessageQueue(MessageQueue);
}
@ -710,6 +739,11 @@ MsqRemoveWindowMessagesFromQueue(PVOID pWindow)
RemoveEntryList(&SentMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, SentMessage->QS_Flags);
/* if it is a callback and this queue is not the sender queue, dereference queue */
if ((SentMessage->CompletionCallback) && (SentMessage->CallBackSenderQueue != MessageQueue))
{
IntDereferenceMessageQueue(SentMessage->CallBackSenderQueue);
}
/* Only if the message has a sender was the queue referenced */
if ((SentMessage->SenderQueue)
&& (SentMessage->DispatchingListEntry.Flink != NULL))
@ -729,7 +763,7 @@ MsqRemoveWindowMessagesFromQueue(PVOID pWindow)
ExFreePool((PVOID)SentMessage->Msg.lParam);
}
/* Only if the message has a sender was the queue referenced */
/* if the message has a sender */
if (SentMessage->SenderQueue)
{
/* dereference our and the sender's message queue */
@ -1573,8 +1607,14 @@ MsqCleanupMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
ListEntry);
/* if it is a callback and this queue is not the sender queue, dereference queue */
if ((CurrentSentMessage->CompletionCallback) && (CurrentSentMessage->CallBackSenderQueue != MessageQueue))
{
IntDereferenceMessageQueue(CurrentSentMessage->CallBackSenderQueue);
}
DPRINT("Notify the sender and remove a message from the queue that had not been dispatched\n");
/* Only if the message has a sender was the queue referenced */
/* Only if the message has a sender was the message in the DispatchingList */
if ((CurrentSentMessage->SenderQueue)
&& (CurrentSentMessage->DispatchingListEntry.Flink != NULL))
{
@ -1593,7 +1633,7 @@ MsqCleanupMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
}
/* Only if the message has a sender was the queue referenced */
/* if the message has a sender */
if (CurrentSentMessage->SenderQueue)
{
/* dereference our and the sender's message queue */
@ -1613,6 +1653,12 @@ MsqCleanupMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
ListEntry);
/* if it is a callback and this queue is not the sender queue, dereference queue */
if ((CurrentSentMessage->CompletionCallback) && (CurrentSentMessage->CallBackSenderQueue != MessageQueue))
{
IntDereferenceMessageQueue(CurrentSentMessage->CallBackSenderQueue);
}
/* remove the message from the dispatching list */
if(CurrentSentMessage->DispatchingListEntry.Flink != NULL)
{
@ -1633,7 +1679,7 @@ MsqCleanupMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
}
/* Only if the message has a sender was the queue referenced */
/* if the message has a sender */
if (CurrentSentMessage->SenderQueue)
{
/* dereference our and the sender's message queue */