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/ntu... ============================================================================== --- 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/ntu... ============================================================================== --- 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 */