Commit in reactos on MAIN
include/win32k/ntuser.h+39-31.128 -> 1.129
lib/user32/include/message.h+14added 1.1
lib/user32/misc/ddeclient.c+1-11.1 -> 1.2
               /ddeserver.c+2-11.1 -> 1.2
               /dllmain.c+21.39 -> 1.40
lib/user32/windows/message.c+905-1861.38 -> 1.39
                  /window.c+1-481.112 -> 1.113
subsys/win32k/include/msgqueue.h+3-21.34 -> 1.35
                     /painting.h+2-11.13 -> 1.14
subsys/win32k/ntuser/keyboard.c+4-41.27 -> 1.28
                    /message.c+493-3711.59 -> 1.60
                    /msgqueue.c+9-71.90 -> 1.91
                    /painting.c+18-121.80 -> 1.81
                    /timer.c+2-21.30 -> 1.31
+1495-638
1 added + 13 modified, total 14 files
Implement DDE Execute:
- Do required translations (KernelMode -> UserMode format, ASCII/Unicode)
  in GetMessage
- Call window proc directly from DispatchMessage instead of via callback
- Apply message filter to WM_PAINT and WM_NCPAINT messages
- Implement marshalling of pointer lParams for PostMessage

reactos/include/win32k
ntuser.h 1.128 -> 1.129
diff -u -r1.128 -r1.129
--- ntuser.h	29 Apr 2004 20:26:34 -0000	1.128
+++ ntuser.h	29 Apr 2004 21:13:15 -0000	1.129
@@ -384,9 +384,17 @@
 BOOLEAN STDCALL
 NtUserDestroyWindow(HWND Wnd);
 
+typedef struct tagNTUSERDISPATCHMESSAGEINFO
+{
+  BOOL HandledByKernel;
+  BOOL Ansi;
+  WNDPROC Proc;
+  MSG Msg;
+} NTUSERDISPATCHMESSAGEINFO, *PNTUSERDISPATCHMESSAGEINFO;
+
 LRESULT
 STDCALL
-NtUserDispatchMessage(CONST MSG* lpmsg);
+NtUserDispatchMessage(PNTUSERDISPATCHMESSAGEINFO MsgInfo);
 
 BOOL
 STDCALL
@@ -734,10 +742,16 @@
 NtUserGetListBoxInfo(
   DWORD Unknown0);
 
+typedef struct tagNTUSERGETMESSAGEINFO
+{
+  MSG Msg;
+  ULONG LParamSize;
+} NTUSERGETMESSAGEINFO, *PNTUSERGETMESSAGEINFO;
+
 BOOL
 STDCALL
 NtUserGetMessage(
-  LPMSG lpMsg,
+  PNTUSERGETMESSAGEINFO MsgInfo,
   HWND hWnd,
   UINT wMsgFilterMin,
   UINT wMsgFilterMax);
@@ -1036,7 +1050,7 @@
 BOOL
 STDCALL
 NtUserPeekMessage(
-  LPMSG lpMsg,
+  PNTUSERGETMESSAGEINFO MsgInfo,
   HWND hWnd,
   UINT wMsgFilterMin,
   UINT wMsgFilterMax,
@@ -1717,6 +1731,28 @@
   LONG idObject,
   SETSCROLLBARINFO *info);
 
+/* lParam of DDE messages */
+typedef struct tagKMDDEEXECUTEDATA
+{
+  HWND Sender;
+  HGLOBAL ClientMem;
+  /* BYTE Data[DataSize] */
+} KMDDEEXECUTEDATA, *PKMDDEEXECUTEDATA; 
+
+typedef struct tagKMDDELPARAM
+{
+  BOOL Packed;
+  union
+    {
+      struct
+        {
+          UINT uiLo;
+          UINT uiHi;
+        } Packed;
+      LPARAM Unpacked;
+    } Value;
+} KMDDELPARAM, *PKMDDELPARAM;
+
 #endif /* __WIN32K_NTUSER_H */
 
 /* EOF */

reactos/lib/user32/include
message.h added at 1.1
diff -N message.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ message.h	29 Apr 2004 21:13:16 -0000	1.1
@@ -0,0 +1,14 @@
+/* $Id: message.h,v 1.1 2004/04/29 21:13:16 gvg Exp $
+ *
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     ReactOS user32.dll
+ * FILE:        include/message.h
+ * PURPOSE:     Message management definitions
+ */
+
+#ifndef LIB_USER32_INCLUDE_MESSAGE_H
+#define LIB_USER32_INCLUDE_MESSAGE_H
+
+BOOL FASTCALL MessageInit(VOID);
+
+#endif /* LIB_USER32_INCLUDE_MESSAGE_H */

reactos/lib/user32/misc
ddeclient.c 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- ddeclient.c	8 Dec 2003 18:21:24 -0000	1.1
+++ ddeclient.c	29 Apr 2004 21:13:16 -0000	1.2
@@ -1340,7 +1340,7 @@
     }
 
     return (IsWindowUnicode(hwnd)) ?
-	DefWindowProcA(hwnd, iMsg, wParam, lParam) : DefWindowProcW(hwnd, iMsg, wParam, lParam);
+	DefWindowProcW(hwnd, iMsg, wParam, lParam) : DefWindowProcA(hwnd, iMsg, wParam, lParam);
 }
 
 /*****************************************************************

reactos/lib/user32/misc
ddeserver.c 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- ddeserver.c	8 Dec 2003 18:21:24 -0000	1.1
+++ ddeserver.c	29 Apr 2004 21:13:16 -0000	1.2
@@ -994,7 +994,8 @@
     }
     if (iMsg < WM_DDE_FIRST || iMsg > WM_DDE_LAST)
     {
-	return DefWindowProcA(hwndServer, iMsg, wParam, lParam);
+	return IsWindowUnicode(hwndServer) ? DefWindowProcW(hwndServer, iMsg, wParam, lParam) :
+                                             DefWindowProcA(hwndServer, iMsg, wParam, lParam);
     }
 
     EnterCriticalSection(&WDML_CritSect);

reactos/lib/user32/misc
dllmain.c 1.39 -> 1.40
diff -u -r1.39 -r1.40
--- dllmain.c	9 Apr 2004 21:22:18 -0000	1.39
+++ dllmain.c	29 Apr 2004 21:13:16 -0000	1.40
@@ -6,6 +6,7 @@
 #include <user32/accel.h>
 #include <window.h>
 #include <menu.h>
+#include <message.h>
 #define _WIN32K_KAPI_H
 #include <user32.h>
 #include <strpool.h>
@@ -73,6 +74,7 @@
   User32TlsIndex = TlsAlloc();
 
   MenuInit();
+  MessageInit();
 
   InitializeCriticalSection(&U32AccelCacheLock);
   InitializeCriticalSection(&gcsMPH);

reactos/lib/user32/windows
message.c 1.38 -> 1.39
diff -u -r1.38 -r1.39
--- message.c	10 Apr 2004 00:54:35 -0000	1.38
+++ message.c	29 Apr 2004 21:13:16 -0000	1.39
@@ -1,4 +1,4 @@
-/* $Id: message.c,v 1.38 2004/04/10 00:54:35 navaraf Exp $
+/* $Id: message.c,v 1.39 2004/04/29 21:13:16 gvg Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS user32.dll
@@ -12,96 +12,329 @@
 #include <user32.h>
 #include <string.h>
 #include <debug.h>
+#include <user32/callback.h>
+#include <message.h>
 #define NTOS_MODE_USER
 #include <ntos.h>
 
-/*
- * @implemented
- */
-LPARAM
-STDCALL
-GetMessageExtraInfo(VOID)
-{
-  return (LPARAM)NtUserCallNoParam(NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO);
-}
+/* DDE message exchange
+ * 
+ * - Session initialization
+ *   Client sends a WM_DDE_INITIATE message, usually a broadcast message. lParam of
+ *   this message contains a pair of global atoms, the Application and Topic atoms.
+ *   The client must destroy the atoms.
+ *   Server window proc handles the WM_DDE_INITIATE message and if the Application
+ *   and Topic atoms are recognized sends a WM_DDE_ACK message to the client. lParam
+ *   of the reply message contains another pair of global atoms (Application and
+ *   Topic again), which must be destroyed by the server.
+ *
+ * - Execute
+ *   Client posts a WM_DDE_EXECUTE message to the server window. lParam of that message
+ *   is a global memory handle containing the string to execute. After the command has
+ *   been executed the server posts a WM_DDE_ACK message to the client, which contains
+ *   a packed lParam which in turn contains that global memory handle. The client takes
+ *   ownership of both the packed lParam (meaning it needs to call FreeDDElParam() on
+ *   it and the global memory handle.
+ *   This might work nice and easy in Win3.1, but things are more complicated for NT.
+ *   Global memory handles in NT are not really global, they're still local to the
+ *   process. So, what happens under the hood is that PostMessage must handle the
+ *   WM_DDE_EXECUTE message specially. It will obtain the contents of the global memory
+ *   area, repack that into a new structure together with the original memory handle
+ *   and pass that off to the win32k. Win32k will marshall that data over to the target
+ *   (server) process where it will be unpacked and stored in a newly allocated global
+ *   memory area. The handle of that area will then be sent to the window proc, after
+ *   storing it together with the "original" (client) handle in a table.
+ *   The server will eventually post the WM_DDE_ACK response, containing the global
+ *   memory handle it received. PostMessage must then lookup that memory handle (only
+ *   valid in the server process) and replace it with the corresponding client memory
+ *   handle. To avoid memory leaks, the server-side global memory block must be freed.
+ *   Also, the WM_DDE_ACK lParam (a PackDDElParam() result) is unpacked and the
+ *   individual components are handed to win32k.sys to post to the client side. Since
+ *   the server side app hands over ownership of the packed lParam when it calls
+ *   PostMessage(), the packed lParam needs to be freed on the server side too.
+ *   When the WM_DDE_ACK message (containing the client-side global memory handle)
+ *   arrives at the client side a new lParam is PackDDElParam()'ed and this is handed
+ *   to the client side window proc which is expected to free/reuse it.
+ */
+
+/* since the WM_DDE_ACK response to a WM_DDE_EXECUTE message should contain the handle
+ * to the memory handle, we keep track (in the server side) of all pairs of handle
+ * used (the client passes its value and the content of the memory handle), and
+ * the server stored both values (the client, and the local one, created after the
+ * content). When a ACK message is generated, the list of pair is searched for a
+ * matching pair, so that the client memory handle can be returned.
+ */
+typedef struct tagDDEPAIR
+{
+  HGLOBAL     ClientMem;
+  HGLOBAL     ServerMem;
+} DDEPAIR, *PDDEPAIR;
+
+static PDDEPAIR DdePairs = NULL;
+static unsigned DdeNumAlloc = 0;
+static unsigned DdeNumUsed = 0;
+static CRITICAL_SECTION DdeCrst;
+
+static BOOL FASTCALL
+DdeAddPair(HGLOBAL ClientMem, HGLOBAL ServerMem)
+{
+  unsigned i;
+
+  EnterCriticalSection(&DdeCrst);
+
+  /* now remember the pair of hMem on both sides */
+  if (DdeNumUsed == DdeNumAlloc)
+    {
+#define GROWBY  4
+      PDDEPAIR New;
+      if (NULL != DdePairs)
+        {
+          New = HeapReAlloc(GetProcessHeap(), 0, DdePairs,
+                            (DdeNumAlloc + GROWBY) * sizeof(DDEPAIR));
+        }
+      else
+        {
+          New = HeapAlloc(GetProcessHeap(), 0, 
+                          (DdeNumAlloc + GROWBY) * sizeof(DDEPAIR));
+        }
 
+      if (NULL == New)
+        {
+          LeaveCriticalSection(&DdeCrst);
+          return FALSE;
+        }
+      DdePairs = New;
+      /* zero out newly allocated part */
+      memset(&DdePairs[DdeNumAlloc], 0, GROWBY * sizeof(DDEPAIR));
+      DdeNumAlloc += GROWBY;
+#undef GROWBY
+    }
 
-/*
- * @implemented
- */
-DWORD
-STDCALL
-GetMessagePos(VOID)
-{
-  PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
-  return(MAKELONG(ThreadData->LastMessage.pt.x, ThreadData->LastMessage.pt.y));
-}
+  for (i = 0; i < DdeNumAlloc; i++)
+    {
+      if (NULL == DdePairs[i].ServerMem)
+        {
+          DdePairs[i].ClientMem = ClientMem;
+          DdePairs[i].ServerMem = ServerMem;
+          DdeNumUsed++;
+          break;
+        }
+    }
+  LeaveCriticalSection(&DdeCrst);
 
+  return TRUE;
+}
 
-/*
- * @implemented
- */
-LONG STDCALL
-GetMessageTime(VOID)
+static HGLOBAL FASTCALL
+DdeGetPair(HGLOBAL ServerMem)
 {
-  PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
-  return(ThreadData->LastMessage.time);
-}
+  unsigned i;
+  HGLOBAL Ret = NULL;
 
+  EnterCriticalSection(&DdeCrst);
+  for (i = 0; i < DdeNumAlloc; i++)
+    {
+      if (DdePairs[i].ServerMem == ServerMem)
+        {
+          /* free this pair */
+          DdePairs[i].ServerMem = 0;
+          DdeNumUsed--;
+          Ret = DdePairs[i].ClientMem;
+          break;
+        }
+    }
+  LeaveCriticalSection(&DdeCrst);
 
-/*
- * @unimplemented
- */
-BOOL
-STDCALL
-InSendMessage(VOID)
-{
-  /* return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE) != ISMEX_NOSEND); */
-  UNIMPLEMENTED;
-  return FALSE;
+  return Ret;
 }
 
-
-/*
- * @unimplemented
- */
-DWORD
-STDCALL
-InSendMessageEx(
-  LPVOID lpReserved)
+static BOOL FASTCALL
+MsgiUMToKMMessage(PMSG UMMsg, PMSG KMMsg, BOOL Posted)
 {
-  /* return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE); */
-  UNIMPLEMENTED;
-  return 0;
+  *KMMsg = *UMMsg;
+
+  switch (UMMsg->message)
+    {
+      case WM_DDE_ACK:
+        {
+          PKMDDELPARAM DdeLparam;
+          DdeLparam = HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDELPARAM));
+          if (NULL == DdeLparam)
+            {
+              return FALSE;
+            }
+          if (Posted)
+            {
+              DdeLparam->Packed = TRUE;
+              if (! UnpackDDElParam(UMMsg->message, UMMsg->lParam,
+                                    &DdeLparam->Value.Packed.uiLo,
+                                    &DdeLparam->Value.Packed.uiHi))
+                {
+                  return FALSE;
+                }
+              if (0 != HIWORD(DdeLparam->Value.Packed.uiHi))
+                {
+                  /* uiHi should contain a hMem from WM_DDE_EXECUTE */
+                  HGLOBAL h = DdeGetPair((HGLOBAL) DdeLparam->Value.Packed.uiHi);
+                  if (NULL != h)
+                    {
+                      GlobalFree((HGLOBAL) DdeLparam->Value.Packed.uiHi);
+                      DdeLparam->Value.Packed.uiHi = (UINT) h;
+                    }
+                }
+              FreeDDElParam(UMMsg->message, UMMsg->lParam);
+            }
+          else
+            {
+              DdeLparam->Packed = FALSE;
+              DdeLparam->Value.Unpacked = UMMsg->lParam;
+            }
+          KMMsg->lParam = (LPARAM) DdeLparam;
+        }
+        break;
+      case WM_DDE_EXECUTE:
+        {
+          SIZE_T Size;
+          PKMDDEEXECUTEDATA KMDdeExecuteData;
+          PVOID Data;
+          
+          Size = GlobalSize((HGLOBAL) UMMsg->lParam);
+          Data = GlobalLock((HGLOBAL) UMMsg->lParam);
+          if (NULL == Data)
+            {
+              SetLastError(ERROR_INVALID_HANDLE);
+              return FALSE;
+            }
+          KMDdeExecuteData = HeapAlloc(GetProcessHeap(), 0, sizeof(KMDDEEXECUTEDATA) + Size);
+          if (NULL == KMDdeExecuteData)
+            {
+              SetLastError(ERROR_OUTOFMEMORY);
+              return FALSE;
+            }
+          KMDdeExecuteData->Sender = (HWND) UMMsg->wParam;
+          KMDdeExecuteData->ClientMem = (HGLOBAL) UMMsg->lParam;
+          memcpy((PVOID) (KMDdeExecuteData + 1), Data, Size);
+          KMMsg->wParam = sizeof(KMDDEEXECUTEDATA) + Size;
+          KMMsg->lParam = (LPARAM) KMDdeExecuteData;
+          GlobalUnlock((HGLOBAL) UMMsg->lParam);
+        }
+        break;
+      default:
+        break;
+    }
+
+  return TRUE;
 }
 
+static VOID FASTCALL
+MsgiUMToKMCleanup(PMSG UMMsg, PMSG KMMsg)
+{
+  switch (KMMsg->message)
+    {
+      case WM_DDE_ACK:
+      case WM_DDE_EXECUTE:
+        HeapFree(GetProcessHeap(), 0, (LPVOID) KMMsg->lParam);
+        break;
+      default:
+        break;
+    }
 
-/*
- * @unimplemented
- */
-BOOL
-STDCALL
-ReplyMessage(
-  LRESULT lResult)
+  return;
+}
+
+static BOOL FASTCALL
+MsgiUMToKMReply(PMSG UMMsg, PMSG KMMsg, LRESULT *Result)
 {
-  UNIMPLEMENTED;
-  return FALSE;
+  MsgiUMToKMCleanup(UMMsg, KMMsg);
+
+  return TRUE;
 }
 
+static BOOL FASTCALL
+MsgiKMToUMMessage(PMSG KMMsg, PMSG UMMsg)
+{
+  *UMMsg = *KMMsg;
 
-/*
- * @implemented
- */
-LPARAM
-STDCALL
-SetMessageExtraInfo(
-  LPARAM lParam)
+  switch (UMMsg->message)
+    {
+      case WM_DDE_ACK:
+        {
+          PKMDDELPARAM DdeLparam = (PKMDDELPARAM) KMMsg->lParam;
+          if (DdeLparam->Packed)
+            {
+              UMMsg->lParam = PackDDElParam(KMMsg->message,
+                                            DdeLparam->Value.Packed.uiLo,
+                                            DdeLparam->Value.Packed.uiHi);
+            }
+          else
+            {
+              UMMsg->lParam = DdeLparam->Value.Unpacked;
+            }
+          break;
+        }
+      case WM_DDE_EXECUTE:
+        {
+          PKMDDEEXECUTEDATA KMDdeExecuteData;
+          HGLOBAL GlobalData;
+          PVOID Data;
+
+          KMDdeExecuteData = (PKMDDEEXECUTEDATA) KMMsg->lParam;
+          GlobalData = GlobalAlloc(GMEM_MOVEABLE, KMMsg->wParam - sizeof(KMDDEEXECUTEDATA));
+          if (NULL == GlobalData)
+            {
+              return FALSE;
+            }
+          Data = GlobalLock(GlobalData);
+          if (NULL == Data)
+            {
+              GlobalFree(GlobalData);
+              return FALSE;
+            }
+          memcpy(Data, (PVOID) (KMDdeExecuteData + 1), KMMsg->wParam - sizeof(KMDDEEXECUTEDATA));
+          GlobalUnlock(GlobalData);
+          if (! DdeAddPair(KMDdeExecuteData->ClientMem, GlobalData))
+            {
+              GlobalFree(GlobalData);
+              return FALSE;
+            }
+          UMMsg->wParam = (WPARAM) KMDdeExecuteData->Sender;
+          UMMsg->lParam = (LPARAM) GlobalData;
+        }
+        break;
+      default:
+        break;
+    }
+
+  return TRUE;
+}
+
+static VOID FASTCALL
+MsgiKMToUMCleanup(PMSG KMMsg, PMSG UMMsg)
 {
-  return NtUserSetMessageExtraInfo(lParam);
+  switch (KMMsg->message)
+    {
+      case WM_DDE_EXECUTE:
+#ifdef TODO
+        HeapFree(GetProcessHeap(), 0, (LPVOID) KMMsg->lParam);
+        GlobalUnlock((HGLOBAL) UMMsg->lParam);
+#endif
+        break;
+      default:
+        break;
+    }
+
+  return;
 }
 
+static BOOL FASTCALL
+MsgiKMToUMReply(PMSG KMMsg, PMSG UMMsg, LRESULT *Result)
+{
+  MsgiKMToUMCleanup(KMMsg, UMMsg);
+
+  return TRUE;
+}
 
-BOOL
+static BOOL FASTCALL
 MsgiAnsiToUnicodeMessage(LPMSG UnicodeMsg, LPMSG AnsiMsg)
 {
   *UnicodeMsg = *AnsiMsg;
@@ -196,7 +429,7 @@
 }
 
 
-BOOL
+static BOOL FASTCALL
 MsgiAnsiToUnicodeCleanup(LPMSG UnicodeMsg, LPMSG AnsiMsg)
 {
   switch (AnsiMsg->message)
@@ -269,7 +502,7 @@
 }
 
 
-BOOL
+static BOOL FASTCALL
 MsgiAnsiToUnicodeReply(LPMSG UnicodeMsg, LPMSG AnsiMsg, LRESULT *Result)
 {
   switch (AnsiMsg->message)
@@ -304,104 +537,341 @@
 }
 
 
-VOID STATIC
-User32ConvertToAsciiMessage(UINT* Msg, WPARAM* wParam, LPARAM* lParam)
+static BOOL FASTCALL
+MsgiUnicodeToAnsiMessage(LPMSG AnsiMsg, LPMSG UnicodeMsg)
 {
-  switch((*Msg))
+  *AnsiMsg = *UnicodeMsg;
+
+  switch(UnicodeMsg->message)
     {
-    case WM_CREATE:
-    case WM_NCCREATE:
-      {
-	CREATESTRUCTA* CsA;
-	CREATESTRUCTW* CsW;
-	UNICODE_STRING UString;
-	ANSI_STRING AString;
-
-	CsW = (CREATESTRUCTW*)(*lParam);
-	CsA = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA));
-	memcpy(CsA, CsW, sizeof(CREATESTRUCTW));
-
-	RtlInitUnicodeString(&UString, CsW->lpszName);
-	RtlUnicodeStringToAnsiString(&AString, &UString, TRUE);
-	CsA->lpszName = AString.Buffer;
-	if (HIWORD((ULONG)CsW->lpszClass) != 0)
-	  {
-	    RtlInitUnicodeString(&UString, CsW->lpszClass);
-	    RtlUnicodeStringToAnsiString(&AString, &UString, TRUE);
-	    CsA->lpszClass = AString.Buffer;
-	  }
-	(*lParam) = (LPARAM)CsA;
-	break;
-      }
-    case WM_SETTEXT:
-      {
-	ANSI_STRING AnsiString;
-	UNICODE_STRING UnicodeString;
-	RtlInitUnicodeString(&UnicodeString, (PWSTR) *lParam);
-	if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString,
-	                                            &UnicodeString,
-	                                            TRUE)))
-	  {
-	    *lParam = (LPARAM) AnsiString.Buffer;
-	  }
-	break;
-      }
+      case WM_CREATE:
+      case WM_NCCREATE:
+        {
+          CREATESTRUCTA* CsA;
+          CREATESTRUCTW* CsW;
+          UNICODE_STRING UString;
+          ANSI_STRING AString;
+          NTSTATUS Status;
+
+          CsW = (CREATESTRUCTW*)(UnicodeMsg->lParam);
+          CsA = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(CREATESTRUCTA));
+          if (NULL == CsA)
+            {
+              return FALSE;
+            }
+          memcpy(CsA, CsW, sizeof(CREATESTRUCTW));
+
+          RtlInitUnicodeString(&UString, CsW->lpszName);
+          Status = RtlUnicodeStringToAnsiString(&AString, &UString, TRUE);
+          if (! NT_SUCCESS(Status))
+            {
+              RtlFreeHeap(GetProcessHeap(), 0, CsA);
+              return FALSE;
+            }
+          CsA->lpszName = AString.Buffer;
+          if (HIWORD((ULONG)CsW->lpszClass) != 0)
+            {
+              RtlInitUnicodeString(&UString, CsW->lpszClass);
+              Status = RtlUnicodeStringToAnsiString(&AString, &UString, TRUE);
+              if (! NT_SUCCESS(Status))
+                {
+                  RtlInitAnsiString(&AString, CsA->lpszName);
+                  RtlFreeAnsiString(&AString);
+                  RtlFreeHeap(GetProcessHeap(), 0, CsA);
+                  return FALSE;
+                }
+              CsA->lpszClass = AString.Buffer;
+            }
+          UnicodeMsg->lParam = (LPARAM)CsA;
+          break;
+        }
+      case WM_SETTEXT:
+        {
+          ANSI_STRING AnsiString;
+          UNICODE_STRING UnicodeString;
+          RtlInitUnicodeString(&UnicodeString, (PWSTR) UnicodeMsg->lParam);
+          if (! NT_SUCCESS(RtlUnicodeStringToAnsiString(&AnsiString,
+                                                        &UnicodeString,
+                                                        TRUE)))
+            {
+              return FALSE;
+            }
+          AnsiMsg->lParam = (LPARAM) AnsiString.Buffer;
+          break;
+	}
+    }
+
+  return TRUE;
+}
+
+
+static BOOL FASTCALL
+MsgiUnicodeToAnsiCleanup(LPMSG AnsiMsg, LPMSG UnicodeMsg)
+{
+  switch(UnicodeMsg->message)
+    {
+      case WM_GETTEXT:
+      case WM_SETTEXT:
+        {
+          ANSI_STRING AString;
+          RtlInitAnsiString(&AString, (PSTR) AnsiMsg->lParam);
+          RtlFreeAnsiString(&AString);
+          break;
+        }
+      case WM_CREATE:
+      case WM_NCCREATE:
+        {
+          CREATESTRUCTA* Cs;
+          ANSI_STRING AString;
+
+          Cs = (CREATESTRUCTA*) AnsiMsg->lParam;
+          RtlInitAnsiString(&AString, Cs->lpszName);
+          RtlFreeAnsiString(&AString);
+          if (HIWORD((ULONG)Cs->lpszClass) != 0)
+            {
+              RtlInitAnsiString(&AString, Cs->lpszClass);
+              RtlFreeAnsiString(&AString);
+            }
+          RtlFreeHeap(GetProcessHeap(), 0, Cs);
+          break;
+        }
     }
+
+  return TRUE;
 }
 
 
-VOID STATIC
-User32FreeAsciiConvertedMessage(UINT Msg, WPARAM wParam, LPARAM lParam)
+static BOOL FASTCALL
+MsgiUnicodeToAnsiReply(LPMSG AnsiMsg, LPMSG UnicodeMsg, LRESULT *Result)
 {
-  switch(Msg)
+  switch (UnicodeMsg->message)
     {
     case WM_GETTEXT:
+    case WM_ASKCBFORMATNAME:
       {
-	ANSI_STRING AnsiString;
-	UNICODE_STRING UnicodeString;
-	LPSTR TempString;
-	LPSTR InString;
-	InString = (LPSTR)lParam;
-	TempString = RtlAllocateHeap(GetProcessHeap(), 0, strlen(InString) + 1);
-	strcpy(TempString, InString);
-	RtlInitAnsiString(&AnsiString, TempString);
-	UnicodeString.Length = wParam * sizeof(WCHAR);
-	UnicodeString.MaximumLength = wParam * sizeof(WCHAR);
-	UnicodeString.Buffer = (PWSTR)lParam;
-	if (! NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicodeString,
-	                                              &AnsiString,
-	                                              FALSE)))
-	  {
-	    if (1 <= wParam)
-	      {
-		UnicodeString.Buffer[0] = L'\0';
-	      }
-	  }
-	RtlFreeHeap(GetProcessHeap(), 0, TempString);
-	break;
+        LPSTR Buffer = (LPSTR) AnsiMsg->lParam;
+        LPWSTR UBuffer = (LPWSTR) UnicodeMsg->lParam;
+        if (0 < AnsiMsg->wParam &&
+            ! MultiByteToWideChar(CP_ACP, 0, Buffer, -1, UBuffer, UnicodeMsg->wParam))
+          {
+            UBuffer[AnsiMsg->wParam - 1] = L'\0';
+          }
+        break;
       }
-    case WM_SETTEXT:
+
+    case WM_GETTEXTLENGTH:
+    case CB_GETLBTEXTLEN:
+    case LB_GETTEXTLEN:
       {
-	ANSI_STRING AnsiString;
-	RtlInitAnsiString(&AnsiString, (PSTR) lParam);
-	RtlFreeAnsiString(&AnsiString);
-	break;
+        /* FIXME: There may be one DBCS char for each Unicode char */
+        *Result /= sizeof(WCHAR);
+        break;
       }
-    case WM_CREATE:
-    case WM_NCCREATE:
-      {
-	CREATESTRUCTA* Cs;
+    }
 
-	Cs = (CREATESTRUCTA*)lParam;
-	RtlFreeHeap(GetProcessHeap(), 0, (LPSTR)Cs->lpszName);
-	if (HIWORD((ULONG)Cs->lpszClass) != 0)
-	  {
-            RtlFreeHeap(GetProcessHeap(), 0, (LPSTR)Cs->lpszClass);
-	  }
-	RtlFreeHeap(GetProcessHeap(), 0, Cs);
-	break;
-      }
+  MsgiUnicodeToAnsiCleanup(UnicodeMsg, AnsiMsg);
+
+  return TRUE;
+}
+
+typedef struct tagMSGCONVERSION
+{
+  BOOL InUse;
+  BOOL Ansi;
+  MSG KMMsg;
+  MSG UnicodeMsg;
+  MSG AnsiMsg;
+  PMSG FinalMsg;
+  ULONG LParamSize;
+} MSGCONVERSION, *PMSGCONVERSION;
+
+static PMSGCONVERSION MsgConversions = NULL;
+static unsigned MsgConversionNumAlloc = 0;
+static unsigned MsgConversionNumUsed = 0;
+static CRITICAL_SECTION MsgConversionCrst;
+
+static BOOL FASTCALL
+MsgConversionAdd(PMSGCONVERSION Conversion)
+{
+  unsigned i;
+
+  EnterCriticalSection(&MsgConversionCrst);
+
+  if (MsgConversionNumUsed == MsgConversionNumAlloc)
+    {
+#define GROWBY  4
+      PMSGCONVERSION New;
+      if (NULL != MsgConversions)
+        {
+          New = HeapReAlloc(GetProcessHeap(), 0, MsgConversions,
+                            (MsgConversionNumAlloc + GROWBY) * sizeof(MSGCONVERSION));
+        }
+      else
+        {
+          New = HeapAlloc(GetProcessHeap(), 0, 
+                          (MsgConversionNumAlloc + GROWBY) * sizeof(MSGCONVERSION));
+        }
+
+      if (NULL == New)
+        {
+          LeaveCriticalSection(&MsgConversionCrst);
+          return FALSE;
+        }
+      MsgConversions = New;
+      /* zero out newly allocated part */
+      memset(MsgConversions + MsgConversionNumAlloc, 0, GROWBY * sizeof(MSGCONVERSION));
+      MsgConversionNumAlloc += GROWBY;
+#undef GROWBY
+    }
+
+  for (i = 0; i < MsgConversionNumAlloc; i++)
+    {
+      if (! MsgConversions[i].InUse)
+        {
+          MsgConversions[i] = *Conversion;
+          MsgConversions[i].InUse = TRUE;
+          MsgConversionNumUsed++;
+          break;
+        }
+    }
+  LeaveCriticalSection(&MsgConversionCrst);
+
+  return TRUE;
+}
+
+static void FASTCALL
+MsgConversionCleanup(CONST MSG *Msg, BOOL Ansi, BOOL CheckMsgContents, LRESULT *Result)
+{
+  BOOL Found;
+  PMSGCONVERSION Conversion;
+  LRESULT Dummy;
+
+  EnterCriticalSection(&MsgConversionCrst);
+  for (Conversion = MsgConversions;
+       Conversion < MsgConversions + MsgConversionNumAlloc;
+       Conversion++)
+    {
+      if (Conversion->InUse &&
+          ((Ansi && Conversion->Ansi) ||
+           (! Ansi && ! Conversion->Ansi)))
+        {
+          Found = (Conversion->FinalMsg == Msg);
+          if (! Found && CheckMsgContents)
+            {
+              if (Ansi)
+                {
+                  Found = (0 == memcmp(Msg, &Conversion->AnsiMsg, sizeof(MSG)));
+                }
+              else
+                {
+                  Found = (0 == memcmp(Msg, &Conversion->UnicodeMsg, sizeof(MSG)));
+                }
+            }
+          if (Found)
+            {
+              if (Ansi)
+                {
+                  MsgiUnicodeToAnsiReply(&Conversion->AnsiMsg, &Conversion->UnicodeMsg,
+                                         NULL == Result ? &Dummy : Result);
+                }
+              MsgiKMToUMReply(&Conversion->KMMsg, &Conversion->UnicodeMsg,
+                              NULL == Result ? &Dummy : Result);
+              if (0 != Conversion->LParamSize)
+                {
+                  NtFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &Conversion->KMMsg.lParam,
+                                      &Conversion->LParamSize, MEM_DECOMMIT);
+                }
+              Conversion->InUse = FALSE;
+              MsgConversionNumUsed--;
+            }
+        }
     }
+  LeaveCriticalSection(&MsgConversionCrst);
+}
+
+/*
+ * @implemented
+ */
+LPARAM
+STDCALL
+GetMessageExtraInfo(VOID)
+{
+  return (LPARAM)NtUserCallNoParam(NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO);
+}
+
+
+/*
+ * @implemented
+ */
+DWORD
+STDCALL
+GetMessagePos(VOID)
+{
+  PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
+  return(MAKELONG(ThreadData->LastMessage.pt.x, ThreadData->LastMessage.pt.y));
+}
+
+
+/*
+ * @implemented
+ */
+LONG STDCALL
+GetMessageTime(VOID)
+{
+  PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
+  return(ThreadData->LastMessage.time);
+}
+
+
+/*
+ * @unimplemented
+ */
+BOOL
+STDCALL
+InSendMessage(VOID)
+{
+  /* return(NtUserGetThreadState(THREADSTATE_INSENDMESSAGE) != ISMEX_NOSEND); */
+  UNIMPLEMENTED;
+  return FALSE;
+}
+
+
+/*
+ * @unimplemented
+ */
+DWORD
+STDCALL
+InSendMessageEx(
+  LPVOID lpReserved)
+{
+  /* return NtUserGetThreadState(THREADSTATE_INSENDMESSAGE); */
+  UNIMPLEMENTED;
+  return 0;
+}
+
+
+/*
+ * @unimplemented
+ */
+BOOL
+STDCALL
+ReplyMessage(
+  LRESULT lResult)
+{
+  UNIMPLEMENTED;
+  return FALSE;
+}
+
+
+/*
+ * @implemented
+ */
+LPARAM
+STDCALL
+SetMessageExtraInfo(
+  LPARAM lParam)
+{
+  return NtUserSetMessageExtraInfo(lParam);
 }
 
 LRESULT FASTCALL
@@ -412,13 +882,25 @@
                    WPARAM wParam,
                    LPARAM lParam)
 {
+  MSG AnsiMsg;
+  MSG UnicodeMsg;
   LRESULT Result;
 
   if (IsAnsiProc)
     {
-      User32ConvertToAsciiMessage(&Msg, &wParam, &lParam);
-      Result = WndProc(hWnd, Msg, wParam, lParam);
-      User32FreeAsciiConvertedMessage(Msg, wParam, lParam);
+      UnicodeMsg.hwnd = hWnd;
+      UnicodeMsg.message = Msg;
+      UnicodeMsg.wParam = wParam;
+      UnicodeMsg.lParam = lParam;
+      if (! MsgiUnicodeToAnsiMessage(&AnsiMsg, &UnicodeMsg))
+        {
+          return FALSE;
+        }
+      Result = WndProc(AnsiMsg.hwnd, AnsiMsg.message, AnsiMsg.wParam, AnsiMsg.lParam);
+      if (! MsgiUnicodeToAnsiReply(&AnsiMsg, &UnicodeMsg, &Result))
+        {
+          return FALSE;
+        }
       return Result;
     }
   else
@@ -525,7 +1007,21 @@
 LRESULT STDCALL
 DispatchMessageA(CONST MSG *lpmsg)
 {
-  return(NtUserDispatchMessage(lpmsg));
+  NTUSERDISPATCHMESSAGEINFO Info;
+  LRESULT Result;
+
+  Info.Ansi = TRUE;
+  Info.Msg = *lpmsg;
+  Result = NtUserDispatchMessage(&Info);
+  if (! Info.HandledByKernel)
+    {
+      /* We need to send the message ourselves */
+      Result = IntCallWindowProcA(Info.Ansi, Info.Proc, Info.Msg.hwnd,
+                                  Info.Msg.message, Info.Msg.wParam, Info.Msg.lParam);
+    }
+  MsgConversionCleanup(lpmsg, TRUE, TRUE, &Result);
+
+  return Result;
 }
 
 
@@ -535,7 +1031,21 @@
 LRESULT STDCALL
 DispatchMessageW(CONST MSG *lpmsg)
 {
-  return(NtUserDispatchMessage((LPMSG)lpmsg));
+  NTUSERDISPATCHMESSAGEINFO Info;
+  LRESULT Result;
+
+  Info.Ansi = FALSE;
+  Info.Msg = *lpmsg;
+  Result = NtUserDispatchMessage(&Info);
+  if (! Info.HandledByKernel)
+    {
+      /* We need to send the message ourselves */
+      Result = IntCallWindowProcW(Info.Ansi, Info.Proc, Info.Msg.hwnd,
+                                  Info.Msg.message, Info.Msg.wParam, Info.Msg.lParam);
+    }
+  MsgConversionCleanup(lpmsg, FALSE, TRUE, &Result);
+
+  return Result;
 }
 
 
@@ -549,14 +1059,38 @@
 	    UINT wMsgFilterMax)
 {
   BOOL Res;
+  MSGCONVERSION Conversion;
+  NTUSERGETMESSAGEINFO Info;
   PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
 
-  Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
+  MsgConversionCleanup(lpMsg, TRUE, FALSE, NULL);
+  Res = NtUserGetMessage(&Info, hWnd, wMsgFilterMin, wMsgFilterMax);
+  if (-1 == (int) Res)
+    {
+      return Res;
+    }
+  Conversion.LParamSize = Info.LParamSize;
+  Conversion.KMMsg = Info.Msg;
+
+  if (! MsgiKMToUMMessage(&Conversion.KMMsg, &Conversion.UnicodeMsg))
+    {
+      return (BOOL) -1;
+    }
+  if (! MsgiUnicodeToAnsiMessage(&Conversion.AnsiMsg, &Conversion.UnicodeMsg))
+    {
+      MsgiKMToUMCleanup(&Info.Msg, &Conversion.UnicodeMsg);
+      return (BOOL) -1;
+    }
+  *lpMsg = Conversion.AnsiMsg;
+  Conversion.Ansi = TRUE;
+  Conversion.FinalMsg = lpMsg;
+  MsgConversionAdd(&Conversion);
   if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
     {
-      ThreadData->LastMessage = *lpMsg;
+      ThreadData->LastMessage = Info.Msg;
     }
-  return(Res);
+
+  return Res;
 }
 
 
@@ -570,14 +1104,33 @@
 	    UINT wMsgFilterMax)
 {
   BOOL Res;
+  MSGCONVERSION Conversion;
+  NTUSERGETMESSAGEINFO Info;
   PUSER32_THREAD_DATA ThreadData = User32GetThreadData();
 
-  Res = NtUserGetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
+  MsgConversionCleanup(lpMsg, FALSE, FALSE, NULL);
+  Res = NtUserGetMessage(&Info, hWnd, wMsgFilterMin, wMsgFilterMax);
+  if (-1 == (int) Res)
+    {
+      return Res;
+    }
+  Conversion.LParamSize = Info.LParamSize;
+  Conversion.KMMsg = Info.Msg;
+
+  if (! MsgiKMToUMMessage(&Conversion.KMMsg, &Conversion.UnicodeMsg))
+    {
+      return (BOOL) -1;
+    }
+  *lpMsg = Conversion.UnicodeMsg;
+  Conversion.Ansi = FALSE;
+  Conversion.FinalMsg = lpMsg;
+  MsgConversionAdd(&Conversion);
   if (Res && lpMsg->message != WM_PAINT && lpMsg->message != WM_QUIT)
     {
-      ThreadData->LastMessage = *lpMsg;
+      ThreadData->LastMessage = Info.Msg;
     }
-  return(Res);
+
+  return Res;
 }
[truncated at 1000 lines; 314 more skipped]

reactos/lib/user32/windows
window.c 1.112 -> 1.113
diff -u -r1.112 -r1.113
--- window.c	15 Apr 2004 23:36:02 -0000	1.112
+++ window.c	29 Apr 2004 21:13:16 -0000	1.113
@@ -1,4 +1,4 @@
-/* $Id: window.c,v 1.112 2004/04/15 23:36:02 weiden Exp $
+/* $Id: window.c,v 1.113 2004/04/29 21:13:16 gvg Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS user32.dll
@@ -48,53 +48,6 @@
 }
 
 
-NTSTATUS STDCALL
-User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
-{
-  PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs;
-  LPARAM lParam;
-
-  /* Make sure we don't try to access mem beyond what we were given */
-  if (ArgumentLength < sizeof(WINDOWPROC_CALLBACK_ARGUMENTS))
-    {
-      return STATUS_INFO_LENGTH_MISMATCH;
-    }
-
-  CallbackArgs = (PWINDOWPROC_CALLBACK_ARGUMENTS) Arguments;
-  /* Check if lParam is really a pointer and adjust it if it is */
-  if (0 <= CallbackArgs->lParamBufferSize)
-    {
-      if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS)
-                            + CallbackArgs->lParamBufferSize)
-        {
-          return STATUS_INFO_LENGTH_MISMATCH;
-        }
-      lParam = (LPARAM) ((char *) CallbackArgs + sizeof(WINDOWPROC_CALLBACK_ARGUMENTS));
-    }
-  else
-    {
-      if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS))
-        {
-          return STATUS_INFO_LENGTH_MISMATCH;
-        }
-      lParam = CallbackArgs->lParam;
-    }
-
-  if (WM_NCCALCSIZE == CallbackArgs->Msg && CallbackArgs->wParam)
-    {
-      NCCALCSIZE_PARAMS *Params = (NCCALCSIZE_PARAMS *) lParam;
-      Params->lppos = (PWINDOWPOS) (Params + 1);
-    }
-
-
-  CallbackArgs->Result = IntCallWindowProcW(CallbackArgs->IsAnsiProc, CallbackArgs->Proc,
-                                            CallbackArgs->Wnd, CallbackArgs->Msg,
-                                            CallbackArgs->wParam, lParam);
-
-  return ZwCallbackReturn(CallbackArgs, ArgumentLength, STATUS_SUCCESS);
-}
-
-
 /*
  * @unimplemented
  */

reactos/subsys/win32k/include
msgqueue.h 1.34 -> 1.35
diff -u -r1.34 -r1.35
--- msgqueue.h	16 Apr 2004 18:53:53 -0000	1.34
+++ msgqueue.h	29 Apr 2004 21:13:16 -0000	1.35
@@ -11,6 +11,7 @@
 typedef struct _USER_MESSAGE
 {
   LIST_ENTRY ListEntry;
+  BOOLEAN FreeLParam;
   MSG Msg;
 } USER_MESSAGE, *PUSER_MESSAGE;
 
@@ -103,12 +104,12 @@
 	       HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
                UINT uTimeout, BOOL Block, ULONG_PTR *uResult);
 PUSER_MESSAGE FASTCALL
-MsqCreateMessage(LPMSG Msg);
+MsqCreateMessage(LPMSG Msg, BOOLEAN FreeLParam);
 VOID FASTCALL
 MsqDestroyMessage(PUSER_MESSAGE Message);
 VOID FASTCALL
 MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue,
-	       MSG* Msg);
+	       MSG* Msg, BOOLEAN FreeLParam);
 VOID FASTCALL
 MsqPostQuitMessage(PUSER_MESSAGE_QUEUE MessageQueue, ULONG ExitCode);
 BOOLEAN STDCALL

reactos/subsys/win32k/include
painting.h 1.13 -> 1.14
diff -u -r1.13 -r1.14
--- painting.h	24 Feb 2004 13:27:02 -0000	1.13
+++ painting.h	29 Apr 2004 21:13:16 -0000	1.14
@@ -12,7 +12,8 @@
 BOOL FASTCALL
 IntRedrawWindow(PWINDOW_OBJECT Wnd, const RECT* UpdateRect, HRGN UpdateRgn, ULONG Flags);
 BOOL FASTCALL
-IntGetPaintMessage(HWND hWnd, PW32THREAD Thread, MSG *Message, BOOL Remove);
+IntGetPaintMessage(HWND hWnd, UINT MsgFilterMin, UINT MsgFilterMax, PW32THREAD Thread,
+                   MSG *Message, BOOL Remove);
 BOOL STDCALL
 NtUserValidateRgn(HWND hWnd, HRGN hRgn);
 

reactos/subsys/win32k/ntuser
keyboard.c 1.27 -> 1.28
diff -u -r1.27 -r1.28
--- keyboard.c	15 Mar 2004 19:06:35 -0000	1.27
+++ keyboard.c	29 Apr 2004 21:13:16 -0000	1.28
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: keyboard.c,v 1.27 2004/03/15 19:06:35 dwelch Exp $
+/* $Id: keyboard.c,v 1.28 2004/04/29 21:13:16 gvg Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -659,14 +659,14 @@
 	  NewMsg.wParam = dead_char;
 	  NewMsg.lParam = lpMsg->lParam;
 	  dead_char = 0;
-	  MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg);
+	  MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg, FALSE);
 	}
       
       NewMsg.hwnd = lpMsg->hwnd;
       NewMsg.wParam = wp[0];
       NewMsg.lParam = lpMsg->lParam;
       DPRINT( "CHAR='%c' %04x %08x\n", wp[0], wp[0], lpMsg->lParam );
-      MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg);
+      MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg, FALSE);
       Result = TRUE;
     }
   else if (UState == -1)
@@ -677,7 +677,7 @@
       NewMsg.wParam = wp[0];
       NewMsg.lParam = lpMsg->lParam;
       dead_char = wp[0];
-      MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg);
+      MsqPostMessage(PsGetWin32Thread()->MessageQueue, &NewMsg, FALSE);
       Result = TRUE;
     }
 

reactos/subsys/win32k/ntuser
message.c 1.59 -> 1.60
diff -u -r1.59 -r1.60
--- message.c	15 Apr 2004 23:36:03 -0000	1.59
+++ message.c	29 Apr 2004 21:13:16 -0000	1.60
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: message.c,v 1.59 2004/04/15 23:36:03 weiden Exp $
+/* $Id: message.c,v 1.60 2004/04/29 21:13:16 gvg Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -70,91 +70,242 @@
   return STATUS_SUCCESS;
 }
 
-LRESULT FASTCALL
-IntDispatchMessage(MSG* Msg)
-{
-  LRESULT Result;
-  PWINDOW_OBJECT WindowObject;
-  /* Process timer messages. */
-  if (Msg->message == WM_TIMER)
+#define MMS_SIZE_WPARAM      -1
+#define MMS_SIZE_WPARAMWCHAR -2
+#define MMS_SIZE_LPARAMSZ    -3
+#define MMS_SIZE_SPECIAL     -4
+#define MMS_FLAG_READ        0x01
+#define MMS_FLAG_WRITE       0x02
+#define MMS_FLAG_READWRITE   (MMS_FLAG_READ | MMS_FLAG_WRITE)
+typedef struct tagMSGMEMORY
+  {
+    UINT Message;
+    UINT Size;
+    INT Flags;
+  } MSGMEMORY, *PMSGMEMORY;
+
+static MSGMEMORY MsgMemory[] =
+  {
+    { WM_CREATE, sizeof(CREATESTRUCTW), MMS_FLAG_READWRITE },
+    { WM_DDE_ACK, sizeof(KMDDELPARAM), MMS_FLAG_READ },
+    { WM_DDE_EXECUTE, MMS_SIZE_WPARAM, MMS_FLAG_READ },
+    { WM_GETMINMAXINFO, sizeof(MINMAXINFO), MMS_FLAG_READWRITE },
+    { WM_GETTEXT, MMS_SIZE_WPARAMWCHAR, MMS_FLAG_WRITE },
+    { WM_NCCALCSIZE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE },
+    { WM_NCCREATE, sizeof(CREATESTRUCTW), MMS_FLAG_READWRITE },
+    { WM_SETTEXT, MMS_SIZE_LPARAMSZ, MMS_FLAG_READ },
+    { WM_STYLECHANGED, sizeof(STYLESTRUCT), MMS_FLAG_READ },
+    { WM_STYLECHANGING, sizeof(STYLESTRUCT), MMS_FLAG_READWRITE },
+    { WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READ },
+    { WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE },
+  };
+
+static PMSGMEMORY FASTCALL
+FindMsgMemory(UINT Msg)
+  {
+  PMSGMEMORY MsgMemoryEntry;
+
+  /* See if this message type is present in the table */
+  for (MsgMemoryEntry = MsgMemory;
+       MsgMemoryEntry < MsgMemory + sizeof(MsgMemory) / sizeof(MSGMEMORY);
+       MsgMemoryEntry++)
     {
-      if (Msg->lParam)
-	{
-	  LARGE_INTEGER LargeTickCount;
-	  /* FIXME: Call hooks. */
+      if (Msg == MsgMemoryEntry->Message)
+        {
+          return MsgMemoryEntry;
+        }
+    }
 
-	  /* FIXME: Check for continuing validity of timer. */
-	  
-          KeQueryTickCount(&LargeTickCount);
-	  return IntCallWindowProc((WNDPROC)Msg->lParam,
-                                      FALSE,
-                                      Msg->hwnd,
-                                      Msg->message,
-                                      Msg->wParam,
-                                      (LPARAM)LargeTickCount.u.LowPart,
-                                      -1);
-	}
+  return NULL;
+}
+
+static UINT FASTCALL
+MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam)
+{
+  if (MMS_SIZE_WPARAM == MsgMemoryEntry->Size)
+    {
+      return (UINT) wParam;
+    }
+  else if (MMS_SIZE_WPARAMWCHAR == MsgMemoryEntry->Size)
+    {
+      return (UINT) (wParam * sizeof(WCHAR));
+    }
+  else if (MMS_SIZE_LPARAMSZ == MsgMemoryEntry->Size)
+    {
+      return (UINT) ((wcslen((PWSTR) lParam) + 1) * sizeof(WCHAR));
+    }
+  else if (MMS_SIZE_SPECIAL == MsgMemoryEntry->Size)
+    {
+      switch(MsgMemoryEntry->Message)
+        {
+        case WM_NCCALCSIZE:
+          return wParam ? sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS) : sizeof(RECT);
+          break;
+        default:
+          assert(FALSE);
+          return 0;
+          break;
+        }
+    }
+  else
+    {
+      return MsgMemoryEntry->Size;
     }
+}
 
-  if( Msg->hwnd == 0 ) return 0;
+static FASTCALL NTSTATUS
+PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+  NCCALCSIZE_PARAMS *UnpackedParams;
+  NCCALCSIZE_PARAMS *PackedParams;
 
-  /* Get the window object. */
-  WindowObject = IntGetWindowObject(Msg->hwnd);
-  if(!WindowObject)
+  *lParamPacked = lParam;
+  if (WM_NCCALCSIZE == Msg && wParam)
     {
-      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
-      return 0;
+      UnpackedParams = (NCCALCSIZE_PARAMS *) lParam;
+      if (UnpackedParams->lppos != (PWINDOWPOS) (UnpackedParams + 1))
+        {
+          PackedParams = ExAllocatePoolWithTag(PagedPool,
+                                               sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS),
+                                               TAG_MSG);
+          if (NULL == PackedParams)
+            {
+              DPRINT1("Not enough memory to pack lParam\n");
+              return STATUS_NO_MEMORY;
+            }
+          RtlCopyMemory(PackedParams, UnpackedParams, sizeof(NCCALCSIZE_PARAMS));
+          PackedParams->lppos = (PWINDOWPOS) (PackedParams + 1);
+          RtlCopyMemory(PackedParams->lppos, UnpackedParams->lppos, sizeof(WINDOWPOS));
+          *lParamPacked = (LPARAM) PackedParams;
+        }
     }
-  if(WindowObject->OwnerThread != PsGetCurrentThread())
-  {
-    IntReleaseWindowObject(WindowObject);
-    DPRINT1("Window doesn't belong to the calling thread!\n");
-    return 0;
-  }
-  /* FIXME: Call hook procedures. */
 
-  /* Call the window procedure. */
-  if (0xFFFF0000 != ((DWORD) WindowObject->WndProcW & 0xFFFF0000))
+  return STATUS_SUCCESS;
+}
+
+static FASTCALL NTSTATUS
+UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+  NCCALCSIZE_PARAMS *UnpackedParams;
+  NCCALCSIZE_PARAMS *PackedParams;
+  PWINDOWPOS UnpackedWindowPos;
+
+  if (lParamPacked == lParam)
     {
-      Result = IntCallWindowProc(WindowObject->WndProcW,
-                                 FALSE,
-                                 Msg->hwnd,
-                                 Msg->message,
-                                 Msg->wParam,
-                                 Msg->lParam,
-                                 -1);
+      return STATUS_SUCCESS;
     }
-  else
+
+  if (WM_NCCALCSIZE == Msg && wParam)
     {
-      Result = IntCallWindowProc(WindowObject->WndProcA,
-                                 TRUE,
-                                 Msg->hwnd,
-                                 Msg->message,
-                                 Msg->wParam,
-                                 Msg->lParam,
-                                 -1);
+      PackedParams = (NCCALCSIZE_PARAMS *) lParamPacked;
+      UnpackedParams = (NCCALCSIZE_PARAMS *) lParam;
+      UnpackedWindowPos = UnpackedParams->lppos;
+      RtlCopyMemory(UnpackedParams, PackedParams, sizeof(NCCALCSIZE_PARAMS));
+      UnpackedParams->lppos = UnpackedWindowPos;
+      RtlCopyMemory(UnpackedWindowPos, PackedParams + 1, sizeof(WINDOWPOS));
+      ExFreePool((PVOID) lParamPacked);
+
+      return STATUS_SUCCESS;
     }
-  
-  IntReleaseWindowObject(WindowObject);
-  
-  return Result;
+
+  assert(FALSE);
+
+  return STATUS_INVALID_PARAMETER;
 }
 
 
 LRESULT STDCALL
-NtUserDispatchMessage(CONST MSG* UnsafeMsg)
+NtUserDispatchMessage(PNTUSERDISPATCHMESSAGEINFO UnsafeMsgInfo)
 {
   NTSTATUS Status;
-  MSG Msg;
+  NTUSERDISPATCHMESSAGEINFO MsgInfo;
+  PWINDOW_OBJECT WindowObject;
+  LRESULT Result;
 
-  Status = MmCopyFromCaller(&Msg, (PVOID) UnsafeMsg, sizeof(MSG));
+  Status = MmCopyFromCaller(&MsgInfo, UnsafeMsgInfo, sizeof(NTUSERDISPATCHMESSAGEINFO));
   if (! NT_SUCCESS(Status))
     {
-    SetLastNtError(Status);
-    return 0;
+      SetLastNtError(Status);
+      return 0;
+    }
+
+  /* Process timer messages. */
+  if (WM_TIMER == MsgInfo.Msg.message && 0 != MsgInfo.Msg.lParam)
+    {
+      LARGE_INTEGER LargeTickCount;
+      /* FIXME: Call hooks. */
+
+      /* FIXME: Check for continuing validity of timer. */
+
+      MsgInfo.HandledByKernel = FALSE;
+      KeQueryTickCount(&LargeTickCount);
+      MsgInfo.Proc = (WNDPROC) MsgInfo.Msg.lParam;
+      MsgInfo.Msg.lParam = (LPARAM)LargeTickCount.u.LowPart;
+    }
+  else if (NULL == MsgInfo.Msg.hwnd)
+    {
+      MsgInfo.HandledByKernel = TRUE;
+      Result = 0;
+    }
+  else
+    {
+      /* Get the window object. */
+      WindowObject = IntGetWindowObject(MsgInfo.Msg.hwnd);
+      if (NULL == WindowObject)
+        {
+          SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+          MsgInfo.HandledByKernel = TRUE;
+          Result = 0;
+        }
+      else
+        {
+          if (WindowObject->OwnerThread != PsGetCurrentThread())
+            {
+              IntReleaseWindowObject(WindowObject);
+              DPRINT1("Window doesn't belong to the calling thread!\n");
+              MsgInfo.HandledByKernel = TRUE;
+              Result = 0;
+            }
+          else
+            {
+              /* FIXME: Call hook procedures. */
+
+              MsgInfo.HandledByKernel = FALSE;
+              Result = 0;
+              if (0xFFFF0000 != ((DWORD) WindowObject->WndProcW & 0xFFFF0000))
+                {
+                  if (0xFFFF0000 != ((DWORD) WindowObject->WndProcA & 0xFFFF0000))
+                    {
+                      /* Both Unicode and Ansi winprocs are real, use whatever
+                         usermode prefers */
+                      MsgInfo.Proc = (MsgInfo.Ansi ? WindowObject->WndProcA
+                                      : WindowObject->WndProcW);
+                    }
+                  else
+                    {
+                      /* Real Unicode winproc */
+                      MsgInfo.Ansi = FALSE;
+                      MsgInfo.Proc = WindowObject->WndProcW;
+                    }
+                }
+              else
+                {
+                  /* Must have real Ansi winproc */
+                  MsgInfo.Ansi = TRUE;
+                  MsgInfo.Proc = WindowObject->WndProcA;
+                }
+            }
+          IntReleaseWindowObject(WindowObject);
+        }
+    }
+  Status = MmCopyToCaller(UnsafeMsgInfo, &MsgInfo, sizeof(NTUSERDISPATCHMESSAGEINFO));
+  if (! NT_SUCCESS(Status))
+    {
+      SetLastNtError(Status);
+      return 0;
     }
   
-  return IntDispatchMessage(&Msg);
+  return Result;
 }
 
 
@@ -336,7 +487,7 @@
  * Internal version of PeekMessage() doing all the work
  */
 BOOL FASTCALL
-IntPeekMessage(LPMSG Msg,
+IntPeekMessage(PUSER_MESSAGE Msg,
                 HWND Wnd,
                 UINT MsgFilterMin,
                 UINT MsgFilterMax,
@@ -372,10 +523,11 @@
   {
     /* According to the PSDK, WM_QUIT messages are always returned, regardless
        of the filter specified */
-    Msg->hwnd = NULL;
-    Msg->message = WM_QUIT;
-    Msg->wParam = ThreadQueue->QuitExitCode;
-    Msg->lParam = 0;
+    Msg->Msg.hwnd = NULL;
+    Msg->Msg.message = WM_QUIT;
+    Msg->Msg.wParam = ThreadQueue->QuitExitCode;
+    Msg->Msg.lParam = 0;
+    Msg->FreeLParam = FALSE;
     if (RemoveMessages)
     {
       ThreadQueue->QuitPosted = FALSE;
@@ -393,7 +545,7 @@
                            &Message);
   if (Present)
   {
-    RtlCopyMemory(Msg, &Message->Msg, sizeof(MSG));
+    RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
     if (RemoveMessages)
     {
       MsqDestroyMessage(Message);
@@ -411,7 +563,7 @@
                            &Message);
   if (Present)
   {
-    RtlCopyMemory(Msg, &Message->Msg, sizeof(MSG));
+    RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
     if (RemoveMessages)
     {
       MsqDestroyMessage(Message);
@@ -423,8 +575,9 @@
   while (MsqDispatchOneSentMessage(ThreadQueue));
 
   /* Check for paint messages. */
-  if (IntGetPaintMessage(Wnd, PsGetWin32Thread(), Msg, RemoveMessages))
+  if (IntGetPaintMessage(Wnd, MsgFilterMin, MsgFilterMax, PsGetWin32Thread(), &Msg->Msg, RemoveMessages))
   {
+    Msg->FreeLParam = FALSE;
     return TRUE;
   }
   
@@ -438,12 +591,12 @@
     {
       PWINDOW_OBJECT MsgWindow = NULL;;
       
-      if(Msg->hwnd && (MsgWindow = IntGetWindowObject(Msg->hwnd)) &&
-         Msg->message >= WM_MOUSEFIRST && Msg->message <= WM_MOUSELAST)
+      if(Msg->Msg.hwnd && (MsgWindow = IntGetWindowObject(Msg->Msg.hwnd)) &&
+         Msg->Msg.message >= WM_MOUSEFIRST && Msg->Msg.message <= WM_MOUSELAST)
       {
         USHORT HitTest;
         
-        if(IntTranslateMouseMessage(ThreadQueue, Msg, &HitTest, TRUE))
+        if(IntTranslateMouseMessage(ThreadQueue, &Msg->Msg, &HitTest, TRUE))
           /* FIXME - check message filter again, if the message doesn't match anymore,
                      search again */
         {
@@ -453,10 +606,10 @@
         }
         if(ThreadQueue->CaptureWindow == NULL)
         {
-          IntSendHitTestMessages(ThreadQueue, Msg);
-          if((Msg->message != WM_MOUSEMOVE && Msg->message != WM_NCMOUSEMOVE) &&
-             IS_BTN_MESSAGE(Msg->message, DOWN) &&
-             IntActivateWindowMouse(ThreadQueue, Msg, MsgWindow, &HitTest))
+          IntSendHitTestMessages(ThreadQueue, &Msg->Msg);
+          if((Msg->Msg.message != WM_MOUSEMOVE && Msg->Msg.message != WM_NCMOUSEMOVE) &&
+             IS_BTN_MESSAGE(Msg->Msg.message, DOWN) &&
+             IntActivateWindowMouse(ThreadQueue, &Msg->Msg, MsgWindow, &HitTest))
           {
             IntReleaseWindowObject(MsgWindow);
             /* eat the message, search again */
@@ -466,7 +619,7 @@
       }
       else
       {
-        IntSendHitTestMessages(ThreadQueue, Msg);
+        IntSendHitTestMessages(ThreadQueue, &Msg->Msg);
       }
       
       if(MsgWindow)
@@ -478,8 +631,8 @@
     }
     
     USHORT HitTest;
-    if((Msg->hwnd && Msg->message >= WM_MOUSEFIRST && Msg->message <= WM_MOUSELAST) &&
-       IntTranslateMouseMessage(ThreadQueue, Msg, &HitTest, FALSE))
+    if((Msg->Msg.hwnd && Msg->Msg.message >= WM_MOUSEFIRST && Msg->Msg.message <= WM_MOUSELAST) &&
+       IntTranslateMouseMessage(ThreadQueue, &Msg->Msg, &HitTest, FALSE))
       /* FIXME - check message filter again, if the message doesn't match anymore,
                  search again */
     {
@@ -494,43 +647,88 @@
 }
 
 BOOL STDCALL
-NtUserPeekMessage(LPMSG UnsafeMsg,
+NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
                   HWND Wnd,
                   UINT MsgFilterMin,
                   UINT MsgFilterMax,
                   UINT RemoveMsg)
 {
-  MSG SafeMsg;
   NTSTATUS Status;
   BOOL Present;
+  NTUSERGETMESSAGEINFO Info;
   PWINDOW_OBJECT Window;
+  PMSGMEMORY MsgMemoryEntry;
+  PVOID UserMem;
+  UINT Size;
+  USER_MESSAGE Msg;
 
   /* Validate input */
   if (NULL != Wnd)
     {
       Window = IntGetWindowObject(Wnd);
-      if(!Window)
-        Wnd = NULL;
+      if (NULL == Window)
+        {
+          Wnd = NULL;
+        }
       else
-        IntReleaseWindowObject(Window);
+        {
+          IntReleaseWindowObject(Window);
+        }
     }
+
   if (MsgFilterMax < MsgFilterMin)
     {
       MsgFilterMin = 0;
       MsgFilterMax = 0;
     }
 
-  Present = IntPeekMessage(&SafeMsg, Wnd, MsgFilterMin, MsgFilterMax, RemoveMsg);
+  Present = IntPeekMessage(&Msg, Wnd, MsgFilterMin, MsgFilterMax, RemoveMsg);
   if (Present)
     {
-      Status = MmCopyToCaller(UnsafeMsg, &SafeMsg, sizeof(MSG));
+      Info.Msg = Msg.Msg;
+      /* See if this message type is present in the table */
+      MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
+      if (NULL == MsgMemoryEntry)
+        {
+          /* Not present, no copying needed */
+          Info.LParamSize = 0;
+        }
+      else
+        {
+          /* Determine required size */
+          Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam,
+                               Info.Msg.lParam);
+          /* Allocate required amount of user-mode memory */
+          Info.LParamSize = Size;
+          UserMem = NULL;
+          Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem, 0,
+                                           &Info.LParamSize, MEM_COMMIT, PAGE_READWRITE);
+          if (! NT_SUCCESS(Status))
+            {
+              SetLastNtError(Status);
+              return (BOOL) -1;
+            }
+          /* Transfer lParam data to user-mode mem */
+          Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Size);
+          if (! NT_SUCCESS(Status))
+            {
+              ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &UserMem,
+                                  &Info.LParamSize, MEM_DECOMMIT);
+              SetLastNtError(Status);
+              return (BOOL) -1;
+            }
+          Info.Msg.lParam = (LPARAM) UserMem;
+        }
+      if (Msg.FreeLParam && 0 != Msg.Msg.lParam)
+        {
+          ExFreePool((void *) Msg.Msg.lParam);
+        }
+      Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO));
       if (! NT_SUCCESS(Status))
-	{
-	  /* There is error return documented for PeekMessage().
-             Do the best we can */
-	  SetLastNtError(Status);
-	  return FALSE;
-	}
+        {
+          SetLastNtError(Status);
+          return (BOOL) -1;
+        }
     }
 
   return Present;
@@ -543,7 +741,7 @@
 {
   PUSER_MESSAGE_QUEUE ThreadQueue;
   NTSTATUS Status;
-  MSG Msg;
+  USER_MESSAGE Msg;
 
   ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
 
@@ -565,7 +763,7 @@
 }
 
 BOOL STDCALL
-NtUserGetMessage(LPMSG UnsafeMsg,
+NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
 		 HWND Wnd,
 		 UINT MsgFilterMin,
 		 UINT MsgFilterMax)
@@ -581,9 +779,13 @@
  */
 {
   BOOL GotMessage;
-  MSG SafeMsg;
+  NTUSERGETMESSAGEINFO Info;
   NTSTATUS Status;
   PWINDOW_OBJECT Window;
+  PMSGMEMORY MsgMemoryEntry;
+  PVOID UserMem;
+  UINT Size;
+  USER_MESSAGE Msg;
 
   /* Validate input */
   if (NULL != Wnd)
@@ -602,10 +804,49 @@
 
   do
     {
-      GotMessage = IntPeekMessage(&SafeMsg, Wnd, MsgFilterMin, MsgFilterMax, PM_REMOVE);
+      GotMessage = IntPeekMessage(&Msg, Wnd, MsgFilterMin, MsgFilterMax, PM_REMOVE);
       if (GotMessage)
 	{
-	  Status = MmCopyToCaller(UnsafeMsg, &SafeMsg, sizeof(MSG));
+          Info.Msg = Msg.Msg;
+          /* See if this message type is present in the table */
+          MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
+          if (NULL == MsgMemoryEntry)
+            {
+              /* Not present, no copying needed */
+              Info.LParamSize = 0;
+            }
+          else
+            {
+              /* Determine required size */
+              Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam,
+                                   Info.Msg.lParam);
+              /* Allocate required amount of user-mode memory */
+              Info.LParamSize = Size;
+              UserMem = NULL;
+              Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem, 0,
+                                               &Info.LParamSize, MEM_COMMIT, PAGE_READWRITE);
+
+              if (! NT_SUCCESS(Status))
+                {
+                  SetLastNtError(Status);
+                  return (BOOL) -1;
+                }
+              /* Transfer lParam data to user-mode mem */
+              Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Size);
+              if (! NT_SUCCESS(Status))
+                {
+                  ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &UserMem,
+                                      &Info.LParamSize, MEM_DECOMMIT);
+                  SetLastNtError(Status);
+                  return (BOOL) -1;
+                }
+              Info.Msg.lParam = (LPARAM) UserMem;
+            }
+          if (Msg.FreeLParam && 0 != Msg.Msg.lParam)
+            {
+              ExFreePool((void *) Msg.Msg.lParam);
+            }
+	  Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO));
 	  if (! NT_SUCCESS(Status))
 	    {
 	      SetLastNtError(Status);
@@ -619,7 +860,7 @@
     }
   while (! GotMessage);
 
-  return WM_QUIT != SafeMsg.message;
+  return WM_QUIT != Info.Msg.message;
 }
 
 DWORD
@@ -638,28 +879,124 @@
   return 0;
 }
 
-BOOL STDCALL
-NtUserPostMessage(HWND hWnd,
-		  UINT Msg,
-		  WPARAM wParam,
-		  LPARAM lParam)
+static NTSTATUS FASTCALL
+CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEntry)
 {
-  PWINDOW_OBJECT Window;
-  MSG Mesg;
-  LARGE_INTEGER LargeTickCount;
+  NTSTATUS Status;
+  
+  PVOID KernelMem;
+  UINT Size;
 
-  if (WM_QUIT == Msg)
+  *KernelModeMsg = *UserModeMsg;
+
+  /* See if this message type is present in the table */
+  if (NULL == MsgMemoryEntry)
     {
-      MsqPostQuitMessage(PsGetWin32Thread()->MessageQueue, wParam);
+      /* Not present, no copying needed */
+      return STATUS_SUCCESS;
     }
-  else if (hWnd == HWND_BROADCAST)
-    {
-      HWND *List;
-      PWINDOW_OBJECT DesktopWindow;
-      ULONG i;
 
-      DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
-      List = IntWinListChildren(DesktopWindow);
+  /* Determine required size */
+  Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
+
+  if (0 != Size)
+    {
+      /* Allocate kernel mem */
+      KernelMem = ExAllocatePoolWithTag(PagedPool, Size, TAG_MSG);
+      if (NULL == KernelMem)
+        {
+          DPRINT1("Not enough memory to copy message to kernel mem\n");
+          return STATUS_NO_MEMORY;
+        }
+      KernelModeMsg->lParam = (LPARAM) KernelMem;
+
+      /* Copy data if required */
+      if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_READ))
+        {
+          Status = MmCopyFromCaller(KernelMem, (PVOID) UserModeMsg->lParam, Size);
+          if (! NT_SUCCESS(Status))
+            {
+              DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
+              ExFreePool(KernelMem);
+              return Status;
+            }
+        }
+      else
+        {
+          /* Make sure we don't pass any secrets to usermode */
+          RtlZeroMemory(KernelMem, Size);
+        }
+    }
+  else
+    {
+      KernelModeMsg->lParam = 0;
+    }
+
+  return STATUS_SUCCESS;
+}
+
+static NTSTATUS FASTCALL
+CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
+{
+  NTSTATUS Status;
+  PMSGMEMORY MsgMemoryEntry;
+  UINT Size;
+
+  /* See if this message type is present in the table */
+  MsgMemoryEntry = FindMsgMemory(UserModeMsg->message);
+  if (NULL == MsgMemoryEntry)
+    {
+      /* Not present, no copying needed */
+      return STATUS_SUCCESS;
+    }
+
+  /* Determine required size */
+  Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
+
+  if (0 != Size)
+    {
+      /* Copy data if required */
+      if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_WRITE))
+        {
+          Status = MmCopyToCaller((PVOID) UserModeMsg->lParam, (PVOID) KernelModeMsg->lParam, Size);
+          if (! NT_SUCCESS(Status))
+            {
+              DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
+              ExFreePool((PVOID) KernelModeMsg->lParam);
+              return Status;
+            }
+        }
+
+      ExFreePool((PVOID) KernelModeMsg->lParam);
+    }
+
+  return STATUS_SUCCESS;
+}
+
+BOOL STDCALL
+NtUserPostMessage(HWND Wnd,
+		  UINT Msg,
+		  WPARAM wParam,
+		  LPARAM lParam)
+{
+  PWINDOW_OBJECT Window;
+  MSG UserModeMsg, KernelModeMsg;
+  LARGE_INTEGER LargeTickCount;
+  NTSTATUS Status;
+  PMSGMEMORY MsgMemoryEntry;
+
+  if (WM_QUIT == Msg)
+    {
+      MsqPostQuitMessage(PsGetWin32Thread()->MessageQueue, wParam);
+    }
+  else if (Wnd == HWND_BROADCAST)
+    {
+      HWND *List;
+      PWINDOW_OBJECT DesktopWindow;
+      ULONG i;
+
+      DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
+      List = IntWinListChildren(DesktopWindow);
       IntReleaseWindowObject(DesktopWindow);
       if (List != NULL)
         {
@@ -670,21 +1007,30 @@
     }
   else
     {
-      Window = IntGetWindowObject(hWnd);
-      if (!Window)
+      Window = IntGetWindowObject(Wnd);
+      if (NULL == Window)
+        {
+          SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+          return FALSE;
+        }
+
+      UserModeMsg.hwnd = Wnd;
+      UserModeMsg.message = Msg;
+      UserModeMsg.wParam = wParam;
+      UserModeMsg.lParam = lParam;
+      MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
+      Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
+      if (! NT_SUCCESS(Status))
         {
-	      SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+          SetLastWin32Error(ERROR_INVALID_PARAMETER);
           return FALSE;
         }
-      Mesg.hwnd = hWnd;
-      Mesg.message = Msg;
-      Mesg.wParam = wParam;
-      Mesg.lParam = lParam;
-      Mesg.pt.x = PsGetWin32Process()->WindowStation->SystemCursor.x;
-      Mesg.pt.y = PsGetWin32Process()->WindowStation->SystemCursor.y;
+      KernelModeMsg.pt.x = PsGetWin32Process()->WindowStation->SystemCursor.x;
+      KernelModeMsg.pt.y = PsGetWin32Process()->WindowStation->SystemCursor.y;
       KeQueryTickCount(&LargeTickCount);
-      Mesg.time = LargeTickCount.u.LowPart;
-      MsqPostMessage(Window->MessageQueue, &Mesg);
+      KernelModeMsg.time = LargeTickCount.u.LowPart;
+      MsqPostMessage(Window->MessageQueue, &KernelModeMsg,
+                     NULL != MsgMemoryEntry && 0 != KernelModeMsg.lParam);
       IntReleaseWindowObject(Window);
     }
 
@@ -697,11 +1043,11 @@
 			WPARAM wParam,
 			LPARAM lParam)
 {
-  MSG Mesg;
-
+  MSG UserModeMsg, KernelModeMsg;
   PETHREAD peThread;
   PW32THREAD pThread;
   NTSTATUS Status;
+  PMSGMEMORY MsgMemoryEntry;
 
   Status = PsLookupThreadByThreadId((void *)idThread,&peThread);
   
@@ -712,11 +1058,20 @@
 	ObDereferenceObject( peThread );
 	return FALSE;
       }
-    Mesg.hwnd = 0;
-    Mesg.message = Msg;
-    Mesg.wParam = wParam;
-    Mesg.lParam = lParam;
-    MsqPostMessage(pThread->MessageQueue, &Mesg);
+
+    UserModeMsg.hwnd = NULL;
+    UserModeMsg.message = Msg;
+    UserModeMsg.wParam = wParam;
+    UserModeMsg.lParam = lParam;
+    MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
+    Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
+    if (! NT_SUCCESS(Status))
+      {
+        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        return FALSE;
+      }
+    MsqPostMessage(pThread->MessageQueue, &KernelModeMsg,
+                   NULL != MsgMemoryEntry && 0 != KernelModeMsg.lParam);
     ObDereferenceObject( peThread );
     return TRUE;
   } else {
@@ -733,147 +1088,6 @@
   return 0;
 }
 
-#define MMS_SIZE_WPARAM      -1
-#define MMS_SIZE_WPARAMWCHAR -2
-#define MMS_SIZE_LPARAMSZ    -3
-#define MMS_SIZE_SPECIAL     -4
-#define MMS_FLAG_READ        0x01
-#define MMS_FLAG_WRITE       0x02
-#define MMS_FLAG_READWRITE   (MMS_FLAG_READ | MMS_FLAG_WRITE)
-typedef struct tagMSGMEMORY
-  {
-    UINT Message;
-    UINT Size;
-    INT Flags;
-  } MSGMEMORY, *PMSGMEMORY;
-
-static MSGMEMORY MsgMemory[] =
-  {
-    { WM_CREATE, sizeof(CREATESTRUCTW), MMS_FLAG_READWRITE },
-    { WM_GETMINMAXINFO, sizeof(MINMAXINFO), MMS_FLAG_READWRITE },
-    { WM_GETTEXT, MMS_SIZE_WPARAMWCHAR, MMS_FLAG_WRITE },
-    { WM_NCCALCSIZE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE },
-    { WM_NCCREATE, sizeof(CREATESTRUCTW), MMS_FLAG_READWRITE },
-    { WM_SETTEXT, MMS_SIZE_LPARAMSZ, MMS_FLAG_READ },
-    { WM_STYLECHANGED, sizeof(STYLESTRUCT), MMS_FLAG_READ },
-    { WM_STYLECHANGING, sizeof(STYLESTRUCT), MMS_FLAG_READWRITE },
-    { WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READ },
-    { WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE },
-  };
-
-static PMSGMEMORY FASTCALL
-FindMsgMemory(UINT Msg)
-  {
-  PMSGMEMORY MsgMemoryEntry;
-
-  /* See if this message type is present in the table */
-  for (MsgMemoryEntry = MsgMemory;
-       MsgMemoryEntry < MsgMemory + sizeof(MsgMemory) / sizeof(MSGMEMORY);
-       MsgMemoryEntry++)
-    {
-      if (Msg == MsgMemoryEntry->Message)
-        {
-          return MsgMemoryEntry;
-        }
-    }
-
-  return NULL;
-}
-
-static UINT FASTCALL
-MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam)
-{
-  if (MMS_SIZE_WPARAM == MsgMemoryEntry->Size)
-    {
-      return (UINT) wParam;
-    }
-  else if (MMS_SIZE_WPARAMWCHAR == MsgMemoryEntry->Size)
-    {
-      return (UINT) (wParam * sizeof(WCHAR));
-    }
-  else if (MMS_SIZE_LPARAMSZ == MsgMemoryEntry->Size)
-    {
-      return (UINT) ((wcslen((PWSTR) lParam) + 1) * sizeof(WCHAR));
-    }
-  else if (MMS_SIZE_SPECIAL == MsgMemoryEntry->Size)
-    {
-      switch(MsgMemoryEntry->Message)
-        {
-        case WM_NCCALCSIZE:
-          return wParam ? sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS) : sizeof(RECT);
-          break;
-        default:
-          assert(FALSE);
-          return 0;
-          break;
-        }
-    }
-  else
-    {
-      return MsgMemoryEntry->Size;
-    }
-}
-
-static NTSTATUS FASTCALL
-PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
-{
-  NCCALCSIZE_PARAMS *UnpackedParams;
-  NCCALCSIZE_PARAMS *PackedParams;
-
-  *lParamPacked = lParam;
-  if (WM_NCCALCSIZE == Msg && wParam)
-    {
-      UnpackedParams = (NCCALCSIZE_PARAMS *) lParam;
-      if (UnpackedParams->lppos != (PWINDOWPOS) (UnpackedParams + 1))
-        {
-          PackedParams = ExAllocatePoolWithTag(PagedPool,
-                                               sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS),
-                                               TAG_MSG);
-          if (NULL == PackedParams)
-            {
-              DPRINT1("Not enough memory to pack lParam\n");
-              return STATUS_NO_MEMORY;
-            }
-          RtlCopyMemory(PackedParams, UnpackedParams, sizeof(NCCALCSIZE_PARAMS));
-          PackedParams->lppos = (PWINDOWPOS) (PackedParams + 1);
-          RtlCopyMemory(PackedParams->lppos, UnpackedParams->lppos, sizeof(WINDOWPOS));
-          *lParamPacked = (LPARAM) PackedParams;
-        }
-    }
-
-  return STATUS_SUCCESS;
-}
-
-static FASTCALL NTSTATUS
-UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
-{
-  NCCALCSIZE_PARAMS *UnpackedParams;
-  NCCALCSIZE_PARAMS *PackedParams;
-  PWINDOWPOS UnpackedWindowPos;
-
-  if (lParamPacked == lParam)
-    {
-      return STATUS_SUCCESS;
-    }
-
-  if (WM_NCCALCSIZE == Msg && wParam)
-    {
-      PackedParams = (NCCALCSIZE_PARAMS *) lParamPacked;
-      UnpackedParams = (NCCALCSIZE_PARAMS *) lParam;
-      UnpackedWindowPos = UnpackedParams->lppos;
-      RtlCopyMemory(UnpackedParams, PackedParams, sizeof(NCCALCSIZE_PARAMS));
-      UnpackedParams->lppos = UnpackedWindowPos;
-      RtlCopyMemory(UnpackedWindowPos, PackedParams + 1, sizeof(WINDOWPOS));
-      ExFreePool((PVOID) lParamPacked);
-
-      return STATUS_SUCCESS;
-    }
-
-  assert(FALSE);
-
-  return STATUS_INVALID_PARAMETER;
-}
-
 LRESULT FASTCALL
 IntSendMessage(HWND hWnd,
                UINT Msg,
@@ -1030,62 +1244,6 @@
   return (LRESULT) TRUE;
 }
 
-static NTSTATUS FASTCALL
-CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg)
-{
-  NTSTATUS Status;
-  PMSGMEMORY MsgMemoryEntry;
-  PVOID KernelMem;
[truncated at 1000 lines; 116 more skipped]

reactos/subsys/win32k/ntuser
msgqueue.c 1.90 -> 1.91
diff -u -r1.90 -r1.91
--- msgqueue.c	16 Apr 2004 18:53:53 -0000	1.90
+++ msgqueue.c	29 Apr 2004 21:13:16 -0000	1.91
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: msgqueue.c,v 1.90 2004/04/16 18:53:53 weiden Exp $
+/* $Id: msgqueue.c,v 1.91 2004/04/29 21:13:16 gvg Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -493,6 +493,7 @@
       UserMsg = ExAllocateFromPagedLookasideList(&MessageLookasideList);
       /* What to do if out of memory? For now we just panic a bit in debug */
       ASSERT(UserMsg);
+      UserMsg->FreeLParam = FALSE;
       UserMsg->Msg = Msg;
       InsertTailList(&HardwareMessageQueueHead, &UserMsg->ListEntry);
       IntLockSystemMessageQueue(OldIrql);
@@ -597,7 +598,7 @@
   FocusMessageQueue = IntGetFocusMessageQueue();
   if( !IntGetScreenDC() ) {
     if( W32kGetPrimitiveMessageQueue() ) {
-      MsqPostMessage(W32kGetPrimitiveMessageQueue(), &Msg);
+      MsqPostMessage(W32kGetPrimitiveMessageQueue(), &Msg, FALSE);
     }
   } else {
     if (FocusMessageQueue == NULL)
@@ -610,7 +611,7 @@
       {
 	Msg.hwnd = FocusMessageQueue->FocusWindow;
         DPRINT("Msg.hwnd = %x\n", Msg.hwnd);
-	MsqPostMessage(FocusMessageQueue, &Msg);
+	MsqPostMessage(FocusMessageQueue, &Msg, FALSE);
       }
     else
       {
@@ -665,7 +666,7 @@
 //      Mesg.pt.y = PsGetWin32Process()->WindowStation->SystemCursor.y;
 //      KeQueryTickCount(&LargeTickCount);
 //      Mesg.time = LargeTickCount.u.LowPart;
-  MsqPostMessage(Window->MessageQueue, &Mesg);
+  MsqPostMessage(Window->MessageQueue, &Mesg, FALSE);
   ObmDereferenceObject(Window);
   ObDereferenceObject (Thread);
 
@@ -678,7 +679,7 @@
 }
 
 PUSER_MESSAGE FASTCALL
-MsqCreateMessage(LPMSG Msg)
+MsqCreateMessage(LPMSG Msg, BOOLEAN FreeLParam)
 {
   PUSER_MESSAGE Message;
 
@@ -688,6 +689,7 @@
       return NULL;
     }
 
+  Message->FreeLParam = FreeLParam;
   RtlMoveMemory(&Message->Msg, Msg, sizeof(MSG));
 
   return Message;
@@ -875,11 +877,11 @@
 }
 
 VOID FASTCALL
-MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, MSG* Msg)
+MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, MSG* Msg, BOOLEAN FreeLParam)
 {
   PUSER_MESSAGE Message;
   
-  if(!(Message = MsqCreateMessage(Msg)))
+  if(!(Message = MsqCreateMessage(Msg, FreeLParam)))
   {
     return;
   }

reactos/subsys/win32k/ntuser
painting.c 1.80 -> 1.81
diff -u -r1.80 -r1.81
--- painting.c	9 Apr 2004 20:03:19 -0000	1.80
+++ painting.c	29 Apr 2004 21:13:16 -0000	1.81
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- *  $Id: painting.c,v 1.80 2004/04/09 20:03:19 navaraf Exp $
+ *  $Id: painting.c,v 1.81 2004/04/29 21:13:16 gvg Exp $
  *
  *  COPYRIGHT:        See COPYING in the top level directory
  *  PROJECT:          ReactOS kernel
@@ -609,8 +609,8 @@
 }
 
 BOOL FASTCALL
-IntGetPaintMessage(HWND hWnd, PW32THREAD Thread, MSG *Message,
-   BOOL Remove)
+IntGetPaintMessage(HWND hWnd, UINT MsgFilterMin, UINT MsgFilterMax,
+                   PW32THREAD Thread, MSG *Message, BOOL Remove)
 {
    PWINDOW_OBJECT Window;
    PUSER_MESSAGE_QUEUE MessageQueue = (PUSER_MESSAGE_QUEUE)Thread->MessageQueue;
@@ -625,13 +625,14 @@
 
    if (Message->hwnd == NULL)
    {
-#if 0
-      DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n");
-#endif
-      IntLockMessageQueue(MessageQueue);
-      MessageQueue->PaintPosted = 0;
-      MessageQueue->PaintCount = 0;
-      IntUnLockMessageQueue(MessageQueue);
+      if (NULL == hWnd)
+      {
+         DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n");
+         IntLockMessageQueue(MessageQueue);
+         MessageQueue->PaintPosted = 0;
+         MessageQueue->PaintCount = 0;
+         IntUnLockMessageQueue(MessageQueue);
+      }
       return FALSE;
    }
 
@@ -639,7 +640,10 @@
    if (Window != NULL)
    {
       IntLockWindowUpdate(Window);
-      if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
+      if (0 != (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
+          && ((0 == MsgFilterMin && 0 == MsgFilterMax) ||
+              (MsgFilterMin <= WM_NCPAINT &&
+               WM_NCPAINT <= MsgFilterMax)))
       {
          Message->message = WM_NCPAINT;
          Message->wParam = (WPARAM)Window->NCUpdateRegion;
@@ -651,7 +655,9 @@
             Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
             MsqDecPaintCountQueue(Window->MessageQueue);
          }
-      } else
+      } else if ((0 == MsgFilterMin && 0 == MsgFilterMax) ||
+                 (MsgFilterMin <= WM_PAINT &&
+                  WM_PAINT <= MsgFilterMax))
       {
          Message->message = WM_PAINT;
          Message->wParam = Message->lParam = 0;

reactos/subsys/win32k/ntuser
timer.c 1.30 -> 1.31
diff -u -r1.30 -r1.31
--- timer.c	9 Apr 2004 20:03:19 -0000	1.30
+++ timer.c	29 Apr 2004 21:13:16 -0000	1.31
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: timer.c,v 1.30 2004/04/09 20:03:19 navaraf Exp $
+/* $Id: timer.c,v 1.31 2004/04/29 21:13:16 gvg Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -418,7 +418,7 @@
           continue;
         }
         
-        MsqPostMessage(((PW32THREAD)Thread->Win32Thread)->MessageQueue, &MsgTimer->Msg);
+        MsqPostMessage(((PW32THREAD)Thread->Win32Thread)->MessageQueue, &MsgTimer->Msg, FALSE);
         
         ThreadsToDereference[ThreadsToDereferencePos] = Thread;
         ++ThreadsToDereferencePos;
CVSspam 0.2.8