Sync with trunk r47129
[reactos.git] / subsystems / win32 / win32k / ntuser / message.c
index b42336d..fdd2740 100644 (file)
@@ -165,7 +165,7 @@ MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam)
 }
 
 static NTSTATUS
-PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
+PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolNeeded)
 {
    NCCALCSIZE_PARAMS *UnpackedNcCalcsize;
    NCCALCSIZE_PARAMS *PackedNcCalcsize;
@@ -173,28 +173,34 @@ PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
    CREATESTRUCTW *PackedCs;
    PUNICODE_STRING WindowName;
    PUNICODE_STRING ClassName;
+   POOL_TYPE PoolType;
    UINT Size;
    PCHAR CsData;
 
    *lParamPacked = lParam;
+
+    if (NonPagedPoolNeeded)
+       PoolType = NonPagedPool;
+    else
+       PoolType = PagedPool;
+
    if (WM_NCCALCSIZE == Msg && wParam)
    {
+
       UnpackedNcCalcsize = (NCCALCSIZE_PARAMS *) lParam;
-      if (UnpackedNcCalcsize->lppos != (PWINDOWPOS) (UnpackedNcCalcsize + 1))
+      PackedNcCalcsize = ExAllocatePoolWithTag(PoolType,
+                         sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS),
+                         TAG_MSG);
+
+      if (NULL == PackedNcCalcsize)
       {
-         PackedNcCalcsize = ExAllocatePoolWithTag(PagedPool,
-                            sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS),
-                            TAG_MSG);
-         if (NULL == PackedNcCalcsize)
-         {
-            DPRINT1("Not enough memory to pack lParam\n");
-            return STATUS_NO_MEMORY;
-         }
-         RtlCopyMemory(PackedNcCalcsize, UnpackedNcCalcsize, sizeof(NCCALCSIZE_PARAMS));
-         PackedNcCalcsize->lppos = (PWINDOWPOS) (PackedNcCalcsize + 1);
-         RtlCopyMemory(PackedNcCalcsize->lppos, UnpackedNcCalcsize->lppos, sizeof(WINDOWPOS));
-         *lParamPacked = (LPARAM) PackedNcCalcsize;
+         DPRINT1("Not enough memory to pack lParam\n");
+         return STATUS_NO_MEMORY;
       }
+      RtlCopyMemory(PackedNcCalcsize, UnpackedNcCalcsize, sizeof(NCCALCSIZE_PARAMS));
+      PackedNcCalcsize->lppos = (PWINDOWPOS) (PackedNcCalcsize + 1);
+      RtlCopyMemory(PackedNcCalcsize->lppos, UnpackedNcCalcsize->lppos, sizeof(WINDOWPOS));
+      *lParamPacked = (LPARAM) PackedNcCalcsize;
    }
    else if (WM_CREATE == Msg || WM_NCCREATE == Msg)
    {
@@ -210,7 +216,7 @@ PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
       {
          Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR);
       }
-      PackedCs = ExAllocatePoolWithTag(PagedPool, Size, TAG_MSG);
+      PackedCs = ExAllocatePoolWithTag(PoolType, Size, TAG_MSG);
       if (NULL == PackedCs)
       {
          DPRINT1("Not enough memory to pack lParam\n");
@@ -244,11 +250,28 @@ PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
       *lParamPacked = (LPARAM) PackedCs;
    }
 
+   else if (PoolType == NonPagedPool)
+   {
+      PMSGMEMORY MsgMemoryEntry;
+      PVOID PackedData;
+
+      MsgMemoryEntry = FindMsgMemory(Msg);
+
+      if ((!MsgMemoryEntry) || (MsgMemoryEntry->Size < 0))
+      {
+         /* Keep previous behavior */
+         return STATUS_SUCCESS;
+      }
+      PackedData = ExAllocatePoolWithTag(NonPagedPool, MsgMemorySize(MsgMemoryEntry, wParam, lParam), TAG_MSG);
+      RtlCopyMemory(PackedData, (PVOID)lParam, MsgMemorySize(MsgMemoryEntry, wParam, lParam));
+      *lParamPacked = (LPARAM)PackedData;
+   }
+
    return STATUS_SUCCESS;
 }
 
 static NTSTATUS
-UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
+UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolUsed)
 {
    NCCALCSIZE_PARAMS *UnpackedParams;
    NCCALCSIZE_PARAMS *PackedParams;
@@ -277,6 +300,23 @@ UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
 
       return STATUS_SUCCESS;
    }
+   else if (NonPagedPoolUsed)
+   {
+      PMSGMEMORY MsgMemoryEntry;
+      MsgMemoryEntry = FindMsgMemory(Msg);
+      if (MsgMemoryEntry->Size < 0)
+      {
+         /* Keep previous behavior */
+         return STATUS_INVALID_PARAMETER;
+      }
+
+      if (MsgMemory->Flags == MMS_FLAG_READWRITE)
+      {
+         //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemory->Size);
+      }
+      ExFreePool((PVOID) lParamPacked);
+      return STATUS_SUCCESS;
+   }
 
    ASSERT(FALSE);
 
@@ -394,7 +434,7 @@ IntDispatchMessage(PMSG pMsg)
      lParamBufferSize = MsgMemorySize(MsgMemoryEntry, pMsg->wParam, pMsg->lParam);
   }
 
-  if (! NT_SUCCESS(PackParam(&lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam)))
+  if (! NT_SUCCESS(PackParam(&lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam, FALSE)))
   {
      DPRINT1("Failed to pack message parameters\n");
      return 0;
@@ -408,7 +448,7 @@ IntDispatchMessage(PMSG pMsg)
                                  lParamPacked,
                                  lParamBufferSize);
 
-  if (! NT_SUCCESS(UnpackParam(lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam)))
+  if (! NT_SUCCESS(UnpackParam(lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam, FALSE)))
   {
      DPRINT1("Failed to unpack message parameters\n");
   }
@@ -1373,7 +1413,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
          lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
       }
 
-      if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam)))
+      if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, FALSE)))
       {
           DPRINT1("Failed to pack message parameters\n");
           RETURN( FALSE);
@@ -1393,7 +1433,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
 
       IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
 
-      if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam)))
+      if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
       {
          DPRINT1("Failed to unpack message parameters\n");
          RETURN( TRUE);
@@ -1503,6 +1543,148 @@ co_IntSendMessageTimeout( HWND hWnd,
    return (LRESULT) TRUE;
 }
 
+LRESULT FASTCALL co_IntSendMessageNoWait(HWND hWnd,
+                                         UINT Msg,
+                                         WPARAM wParam,
+                                         LPARAM lParam)
+{
+   ULONG_PTR Result = 0;
+   co_IntSendMessageWithCallBack(hWnd,
+                                 Msg,
+                                 wParam,
+                                 lParam,
+                                 NULL,
+                                 0,
+                                 &Result);
+   return Result;
+}
+
+LRESULT FASTCALL
+co_IntSendMessageWithCallBack( HWND hWnd,
+                               UINT Msg,
+                               WPARAM wParam,
+                               LPARAM lParam,
+                               SENDASYNCPROC CompletionCallback,
+                               ULONG_PTR CompletionCallbackContext,
+                               ULONG_PTR *uResult)
+{
+   ULONG_PTR Result;
+   PWINDOW_OBJECT Window = NULL;
+   PMSGMEMORY MsgMemoryEntry;
+   INT lParamBufferSize;
+   LPARAM lParamPacked;
+   PTHREADINFO Win32Thread;
+   DECLARE_RETURN(LRESULT);
+   USER_REFERENCE_ENTRY Ref;
+   PUSER_SENT_MESSAGE Message;
+
+   if (!(Window = UserGetWindowObject(hWnd)))
+   {
+       RETURN(FALSE);
+   }
+
+   UserRefObjectCo(Window, &Ref);
+
+   if (Window->state & WINDOWSTATUS_DESTROYING)
+   {
+      /* FIXME - last error? */
+      DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd);
+      RETURN(FALSE);
+   }
+
+   Win32Thread = PsGetCurrentThreadWin32Thread();
+
+   IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
+
+   if (Win32Thread == NULL)
+   {
+     ASSERT(FALSE);
+     RETURN(FALSE);
+   }
+
+   if (Win32Thread->TIF_flags & TIF_INCLEANUP)
+   {
+      /* Never send messages to exiting threads */
+       RETURN(FALSE);
+   }
+
+   /* See if this message type is present in the table */
+   MsgMemoryEntry = FindMsgMemory(Msg);
+   if (NULL == MsgMemoryEntry)
+   {
+      lParamBufferSize = -1;
+   }
+   else
+   {
+      lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
+   }
+
+   if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, Window->pti->MessageQueue != Win32Thread->MessageQueue)))
+   {
+       DPRINT1("Failed to pack message parameters\n");
+       RETURN( FALSE);
+   }
+
+   /* If this is not a callback and it can be sent now, then send it. */
+   if ((Window->pti->MessageQueue == Win32Thread->MessageQueue) && (CompletionCallback == NULL))
+   {
+
+      Result = (ULONG_PTR)co_IntCallWindowProc( Window->Wnd->lpfnWndProc,
+                                               !Window->Wnd->Unicode,
+                                                hWnd,
+                                                Msg,
+                                                wParam,
+                                                lParamPacked,
+                                                lParamBufferSize );
+      if(uResult)
+      {
+         *uResult = Result;
+      }
+   }
+
+   IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
+
+   if (Window->pti->MessageQueue == Win32Thread->MessageQueue)
+   {
+      if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
+      {
+         DPRINT1("Failed to unpack message parameters\n");
+         RETURN(TRUE);
+      }
+      RETURN(TRUE);
+   }
+
+   if(!(Message = ExAllocatePoolWithTag(NonPagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG)))
+   {
+      DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
+      return STATUS_INSUFFICIENT_RESOURCES;
+   }
+
+   Message->Msg.hwnd = hWnd;
+   Message->Msg.message = Msg;
+   Message->Msg.wParam = wParam;
+   Message->Msg.lParam = lParamPacked;
+   Message->CompletionEvent = NULL;
+   Message->Result = 0;
+   Message->SenderQueue = Win32Thread->MessageQueue;
+   IntReferenceMessageQueue(Message->SenderQueue);
+   IntReferenceMessageQueue(Window->pti->MessageQueue);
+   Message->CompletionCallback = CompletionCallback;
+   Message->CompletionCallbackContext = CompletionCallbackContext;
+   Message->HookMessage = MSQ_NORMAL | MSQ_SENTNOWAIT;
+   Message->HasPackedLParam = (lParamBufferSize > 0);
+
+   InsertTailList(&Window->pti->MessageQueue->SentMessagesListHead, &Message->ListEntry);
+   InsertTailList(&Win32Thread->MessageQueue->DispatchingMessagesHead, &Message->DispatchingListEntry);
+   IntDereferenceMessageQueue(Window->pti->MessageQueue);
+   IntDereferenceMessageQueue(Message->SenderQueue);
+
+   RETURN(TRUE);
+
+CLEANUP:
+   if (Window) UserDerefObjectCo(Window);
+   END_CLEANUP;
+}
 
 /* This function posts a message if the destination's message queue belongs to
    another thread, otherwise it sends the message. It does not support broadcast