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/ntuser/message.c?rev=51332&r1=51331&r2=51332&view=diff
==============================================================================
--- 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/ntuser/msgqueue.c?rev=51332&r1=51331&r2=51332&view=diff
==============================================================================
--- 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 */


Reply via email to