Author: mjmartin
Date: Thu Apr 14 01:21:38 2011
New Revision: 51332
URL: http://svn.reactos.org/svn/reactos?rev=51332&view=rev
Log:
[Win32k]
- Fix implementation of message callbacks, now callbacks can be called across processes.
- Fix some comments.
Modified:
trunk/reactos/subsystems/win32/win32k/ntuser/message.c
trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/message.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] Thu Apr 14 01:21:38 2011
@@ -1425,8 +1425,8 @@
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 @@
ObDereferenceObject(Win32Thread->pEThread);
IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
- }
-
-
-
- if ((Window->head.pti->MessageQueue == Win32Thread->MessageQueue) && (CompletionCallback == NULL))
+
+ if (CompletionCallback)
+ {
+ co_IntCallSentMessageCallback(CompletionCallback,
+ hWnd,
+ Msg,
+ CompletionCallbackContext,
+ Result);
+ }
+ }
+
+
+
+ if (Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
{
if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
{
@@ -1470,6 +1479,12 @@
DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
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;
@@ -1482,8 +1497,6 @@
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 @@
InsertTailList(&Window->head.pti->MessageQueue->SentMessagesListHead, &Message->ListEntry);
MsqWakeQueue(Window->head.pti->MessageQueue, QS_SENDMESSAGE, TRUE);
-
IntDereferenceMessageQueue(Window->head.pti->MessageQueue);
RETURN(TRUE);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c [iso-8859-1] Thu Apr 14 01:21:38 2011
@@ -588,6 +588,28 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 */