[User32|Win32k]
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / message.c
index 5d1cf8e..030b1c9 100644 (file)
@@ -1,12 +1,12 @@
 /*
- * COPYRIGHT:        See COPYING in the top level directory
- * PROJECT:          ReactOS kernel
- * PURPOSE:          Messages
- * FILE:             subsys/win32k/ntuser/message.c
- * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
- * REVISION HISTORY:
- *       06-06-2001  CSH  Created
- */
+* COPYRIGHT:        See COPYING in the top level directory
+* PROJECT:          ReactOS kernel
+* PURPOSE:          Messages
+* FILE:             subsystems/win32/win32k/ntuser/message.c
+* PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
+* REVISION HISTORY:
+*       06-06-2001  CSH  Created
+*/
 
 /* INCLUDES ******************************************************************/
 
 #define NDEBUG
 #include <debug.h>
 
-#define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
+BOOLEAN NTAPI PsGetProcessExitProcessCalled(PEPROCESS Process);
 
-typedef struct
-{
-   UINT uFlags;
-   UINT uTimeout;
-   ULONG_PTR Result;
-}
-DOSENDMESSAGE, *PDOSENDMESSAGE;
+#define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
 
 /* FUNCTIONS *****************************************************************/
 
 NTSTATUS FASTCALL
 IntInitMessageImpl(VOID)
 {
-   return STATUS_SUCCESS;
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS FASTCALL
 IntCleanupMessageImpl(VOID)
 {
-   return STATUS_SUCCESS;
+    return STATUS_SUCCESS;
+}
+
+/* From wine: */
+/* flag for messages that contain pointers */
+/* 32 messages per entry, messages 0..31 map to bits 0..31 */
+
+#define SET(msg) (1 << ((msg) & 31))
+
+static const unsigned int message_pointer_flags[] =
+{
+    /* 0x00 - 0x1f */
+    SET(WM_CREATE) | SET(WM_SETTEXT) | SET(WM_GETTEXT) |
+    SET(WM_WININICHANGE) | SET(WM_DEVMODECHANGE),
+    /* 0x20 - 0x3f */
+    SET(WM_GETMINMAXINFO) | SET(WM_DRAWITEM) | SET(WM_MEASUREITEM) | SET(WM_DELETEITEM) |
+    SET(WM_COMPAREITEM),
+    /* 0x40 - 0x5f */
+    SET(WM_WINDOWPOSCHANGING) | SET(WM_WINDOWPOSCHANGED) | SET(WM_COPYDATA) |
+    SET(WM_COPYGLOBALDATA) | SET(WM_NOTIFY) | SET(WM_HELP),
+    /* 0x60 - 0x7f */
+    SET(WM_STYLECHANGING) | SET(WM_STYLECHANGED),
+    /* 0x80 - 0x9f */
+    SET(WM_NCCREATE) | SET(WM_NCCALCSIZE) | SET(WM_GETDLGCODE),
+    /* 0xa0 - 0xbf */
+    SET(EM_GETSEL) | SET(EM_GETRECT) | SET(EM_SETRECT) | SET(EM_SETRECTNP),
+    /* 0xc0 - 0xdf */
+    SET(EM_REPLACESEL) | SET(EM_GETLINE) | SET(EM_SETTABSTOPS),
+    /* 0xe0 - 0xff */
+    SET(SBM_GETRANGE) | SET(SBM_SETSCROLLINFO) | SET(SBM_GETSCROLLINFO) | SET(SBM_GETSCROLLBARINFO),
+    /* 0x100 - 0x11f */
+    0,
+    /* 0x120 - 0x13f */
+    0,
+    /* 0x140 - 0x15f */
+    SET(CB_GETEDITSEL) | SET(CB_ADDSTRING) | SET(CB_DIR) | SET(CB_GETLBTEXT) |
+    SET(CB_INSERTSTRING) | SET(CB_FINDSTRING) | SET(CB_SELECTSTRING) |
+    SET(CB_GETDROPPEDCONTROLRECT) | SET(CB_FINDSTRINGEXACT),
+    /* 0x160 - 0x17f */
+    0,
+    /* 0x180 - 0x19f */
+    SET(LB_ADDSTRING) | SET(LB_INSERTSTRING) | SET(LB_GETTEXT) | SET(LB_SELECTSTRING) |
+    SET(LB_DIR) | SET(LB_FINDSTRING) |
+    SET(LB_GETSELITEMS) | SET(LB_SETTABSTOPS) | SET(LB_ADDFILE) | SET(LB_GETITEMRECT),
+    /* 0x1a0 - 0x1bf */
+    SET(LB_FINDSTRINGEXACT),
+    /* 0x1c0 - 0x1df */
+    0,
+    /* 0x1e0 - 0x1ff */
+    0,
+    /* 0x200 - 0x21f */
+    SET(WM_NEXTMENU) | SET(WM_SIZING) | SET(WM_MOVING) | SET(WM_DEVICECHANGE),
+    /* 0x220 - 0x23f */
+    SET(WM_MDICREATE) | SET(WM_MDIGETACTIVE) | SET(WM_DROPOBJECT) |
+    SET(WM_QUERYDROPOBJECT) | SET(WM_DRAGLOOP) | SET(WM_DRAGSELECT) | SET(WM_DRAGMOVE),
+    /* 0x240 - 0x25f */
+    0,
+    /* 0x260 - 0x27f */
+    0,
+    /* 0x280 - 0x29f */
+    0,
+    /* 0x2a0 - 0x2bf */
+    0,
+    /* 0x2c0 - 0x2df */
+    0,
+    /* 0x2e0 - 0x2ff */
+    0,
+    /* 0x300 - 0x31f */
+    SET(WM_ASKCBFORMATNAME)
+};
+
+/* check whether a given message type includes pointers */
+static inline int is_pointer_message( UINT message )
+{
+    if (message >= 8*sizeof(message_pointer_flags)) return FALSE;
+        return (message_pointer_flags[message / 32] & SET(message)) != 0;
 }
 
 #define MMS_SIZE_WPARAM      -1
@@ -48,1078 +117,760 @@ IntCleanupMessageImpl(VOID)
 #define MMS_FLAG_READWRITE   (MMS_FLAG_READ | MMS_FLAG_WRITE)
 typedef struct tagMSGMEMORY
 {
-   UINT Message;
-   UINT Size;
-   INT Flags;
+    UINT Message;
+    UINT Size;
+    INT Flags;
 }
 MSGMEMORY, *PMSGMEMORY;
 
 static MSGMEMORY MsgMemory[] =
-   {
-      { WM_CREATE, MMS_SIZE_SPECIAL, 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, MMS_SIZE_SPECIAL, 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_COPYDATA, MMS_SIZE_SPECIAL, MMS_FLAG_READ },
-      { WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READ },
-      { WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE },
-   };
+{
+    { WM_CREATE, MMS_SIZE_SPECIAL, 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, MMS_SIZE_SPECIAL, 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_COPYDATA, MMS_SIZE_SPECIAL, MMS_FLAG_READ },
+    { WM_COPYGLOBALDATA, MMS_SIZE_WPARAM, MMS_FLAG_READ },
+    { WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READ },
+    { WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE },
+};
 
 static PMSGMEMORY FASTCALL
 FindMsgMemory(UINT Msg)
 {
-   PMSGMEMORY MsgMemoryEntry;
+    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;
-      }
-   }
+    /* 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;
+    return NULL;
 }
 
 static UINT FASTCALL
 MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam)
 {
-   CREATESTRUCTW *Cs;
-   PUNICODE_STRING WindowName;
-   PUNICODE_STRING ClassName;
-   UINT Size = 0;
+    CREATESTRUCTW *Cs;
+    PUNICODE_STRING WindowName;
+    PUNICODE_STRING ClassName;
+    UINT Size = 0;
 
-   _SEH2_TRY
-   {
-      if (MMS_SIZE_WPARAM == MsgMemoryEntry->Size)
-      {
-         Size = (UINT)wParam;
-      }
-      else if (MMS_SIZE_WPARAMWCHAR == MsgMemoryEntry->Size)
-      {
-         Size = (UINT) (wParam * sizeof(WCHAR));
-      }
-      else if (MMS_SIZE_LPARAMSZ == MsgMemoryEntry->Size)
-      {
-         Size = (UINT) ((wcslen((PWSTR) lParam) + 1) * sizeof(WCHAR));
-      }
-      else if (MMS_SIZE_SPECIAL == MsgMemoryEntry->Size)
-      {
-         switch(MsgMemoryEntry->Message)
-         {
+    _SEH2_TRY
+    {
+        if (MMS_SIZE_WPARAM == MsgMemoryEntry->Size)
+        {
+            Size = (UINT)wParam;
+        }
+        else if (MMS_SIZE_WPARAMWCHAR == MsgMemoryEntry->Size)
+        {
+            Size = (UINT) (wParam * sizeof(WCHAR));
+        }
+        else if (MMS_SIZE_LPARAMSZ == MsgMemoryEntry->Size)
+        {
+            Size = (UINT) ((wcslen((PWSTR) lParam) + 1) * sizeof(WCHAR));
+        }
+        else if (MMS_SIZE_SPECIAL == MsgMemoryEntry->Size)
+        {
+            switch(MsgMemoryEntry->Message)
+            {
             case WM_CREATE:
             case WM_NCCREATE:
-               Cs = (CREATESTRUCTW *) lParam;
-               WindowName = (PUNICODE_STRING) Cs->lpszName;
-               ClassName = (PUNICODE_STRING) Cs->lpszClass;
-               Size = sizeof(CREATESTRUCTW) + WindowName->Length + sizeof(WCHAR);
-               if (IS_ATOM(ClassName->Buffer))
-               {
-                  Size += sizeof(WCHAR) + sizeof(ATOM);
-               }
-               else
-               {
-                  Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR);
-               }
-               break;
+                Cs = (CREATESTRUCTW *) lParam;
+                WindowName = (PUNICODE_STRING) Cs->lpszName;
+                ClassName = (PUNICODE_STRING) Cs->lpszClass;
+                Size = sizeof(CREATESTRUCTW) + WindowName->Length + sizeof(WCHAR);
+                if (IS_ATOM(ClassName->Buffer))
+                {
+                    Size += sizeof(WCHAR) + sizeof(ATOM);
+                }
+                else
+                {
+                    Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR);
+                }
+                break;
 
             case WM_NCCALCSIZE:
-               Size = wParam ? sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS) : sizeof(RECT);
-               break;
+                Size = wParam ? sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS) : sizeof(RECT);
+                break;
 
             case WM_COPYDATA:
-               Size = sizeof(COPYDATASTRUCT) + ((PCOPYDATASTRUCT)lParam)->cbData;
-               break;
-
-            case WM_COPYGLOBALDATA:
-               Size = wParam;
-               break;
+                Size = sizeof(COPYDATASTRUCT) + ((PCOPYDATASTRUCT)lParam)->cbData;
+                break;
 
             default:
-               ASSERT(FALSE);
-               Size = 0;
-               break;
-         }
-      }
-      else
-      {
-         Size = MsgMemoryEntry->Size;
-      }
-   }
-   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-   {
-      DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
-      Size = 0;
-   }
-   _SEH2_END;
-   return Size;
+                ASSERT(FALSE);
+                Size = 0;
+                break;
+            }
+        }
+        else
+        {
+            Size = MsgMemoryEntry->Size;
+        }
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
+        Size = 0;
+    }
+    _SEH2_END;
+    return Size;
 }
 
 static NTSTATUS
 PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolNeeded)
 {
-   NCCALCSIZE_PARAMS *UnpackedNcCalcsize;
-   NCCALCSIZE_PARAMS *PackedNcCalcsize;
-   CREATESTRUCTW *UnpackedCs;
-   CREATESTRUCTW *PackedCs;
-   PLARGE_STRING WindowName;
-   PUNICODE_STRING ClassName;
-   POOL_TYPE PoolType;
-   UINT Size;
-   PCHAR CsData;
-
-   *lParamPacked = lParam;
+    NCCALCSIZE_PARAMS *UnpackedNcCalcsize;
+    NCCALCSIZE_PARAMS *PackedNcCalcsize;
+    CREATESTRUCTW *UnpackedCs;
+    CREATESTRUCTW *PackedCs;
+    PLARGE_STRING WindowName;
+    PUNICODE_STRING ClassName;
+    POOL_TYPE PoolType;
+    UINT Size;
+    PCHAR CsData;
+
+    *lParamPacked = lParam;
 
     if (NonPagedPoolNeeded)
-       PoolType = NonPagedPool;
+        PoolType = NonPagedPool;
     else
-       PoolType = PagedPool;
-
-   if (WM_NCCALCSIZE == Msg && wParam)
-   {
+        PoolType = PagedPool;
 
-      UnpackedNcCalcsize = (NCCALCSIZE_PARAMS *) lParam;
-      PackedNcCalcsize = ExAllocatePoolWithTag(PoolType,
-                         sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS),
-                         TAG_MSG);
+    if (WM_NCCALCSIZE == Msg && wParam)
+    {
 
-      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;
-   }
-   else if (WM_CREATE == Msg || WM_NCCREATE == Msg)
-   {
-      UnpackedCs = (CREATESTRUCTW *) lParam;
-      WindowName = (PLARGE_STRING) UnpackedCs->lpszName;
-      ClassName = (PUNICODE_STRING) UnpackedCs->lpszClass;
-      Size = sizeof(CREATESTRUCTW) + WindowName->Length + sizeof(WCHAR);
-      if (IS_ATOM(ClassName->Buffer))
-      {
-         Size += sizeof(WCHAR) + sizeof(ATOM);
-      }
-      else
-      {
-         Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR);
-      }
-      PackedCs = ExAllocatePoolWithTag(PoolType, Size, TAG_MSG);
-      if (NULL == PackedCs)
-      {
-         DPRINT1("Not enough memory to pack lParam\n");
-         return STATUS_NO_MEMORY;
-      }
-      RtlCopyMemory(PackedCs, UnpackedCs, sizeof(CREATESTRUCTW));
-      CsData = (PCHAR) (PackedCs + 1);
-      PackedCs->lpszName = (LPCWSTR) (CsData - (PCHAR) PackedCs);
-      RtlCopyMemory(CsData, WindowName->Buffer, WindowName->Length);
-      CsData += WindowName->Length;
-      *((WCHAR *) CsData) = L'\0';
-      CsData += sizeof(WCHAR);
-      PackedCs->lpszClass = (LPCWSTR) (CsData - (PCHAR) PackedCs);
-      if (IS_ATOM(ClassName->Buffer))
-      {
-         *((WCHAR *) CsData) = L'A';
-         CsData += sizeof(WCHAR);
-         *((ATOM *) CsData) = (ATOM)(DWORD_PTR) ClassName->Buffer;
-         CsData += sizeof(ATOM);
-      }
-      else
-      {
-         *((WCHAR *) CsData) = L'S';
-         CsData += sizeof(WCHAR);
-         RtlCopyMemory(CsData, ClassName->Buffer, ClassName->Length);
-         CsData += ClassName->Length;
-         *((WCHAR *) CsData) = L'\0';
-         CsData += sizeof(WCHAR);
-      }
-      ASSERT(CsData == (PCHAR) PackedCs + Size);
-      *lParamPacked = (LPARAM) PackedCs;
-   }
+        UnpackedNcCalcsize = (NCCALCSIZE_PARAMS *) lParam;
+        PackedNcCalcsize = ExAllocatePoolWithTag(PoolType,
+        sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS),
+        TAG_MSG);
 
-   else if (PoolType == NonPagedPool)
-   {
-      PMSGMEMORY MsgMemoryEntry;
-      PVOID PackedData;
+        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;
+    }
+    else if (WM_CREATE == Msg || WM_NCCREATE == Msg)
+    {
+        UnpackedCs = (CREATESTRUCTW *) lParam;
+        WindowName = (PLARGE_STRING) UnpackedCs->lpszName;
+        ClassName = (PUNICODE_STRING) UnpackedCs->lpszClass;
+        Size = sizeof(CREATESTRUCTW) + WindowName->Length + sizeof(WCHAR);
+        if (IS_ATOM(ClassName->Buffer))
+        {
+            Size += sizeof(WCHAR) + sizeof(ATOM);
+        }
+        else
+        {
+            Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR);
+        }
+        PackedCs = ExAllocatePoolWithTag(PoolType, Size, TAG_MSG);
+        if (NULL == PackedCs)
+        {
+            DPRINT1("Not enough memory to pack lParam\n");
+            return STATUS_NO_MEMORY;
+        }
+        RtlCopyMemory(PackedCs, UnpackedCs, sizeof(CREATESTRUCTW));
+        CsData = (PCHAR) (PackedCs + 1);
+        PackedCs->lpszName = (LPCWSTR) (CsData - (PCHAR) PackedCs);
+        RtlCopyMemory(CsData, WindowName->Buffer, WindowName->Length);
+        CsData += WindowName->Length;
+        *((WCHAR *) CsData) = L'\0';
+        CsData += sizeof(WCHAR);
+        PackedCs->lpszClass = (LPCWSTR) (CsData - (PCHAR) PackedCs);
+        if (IS_ATOM(ClassName->Buffer))
+        {
+            *((WCHAR *) CsData) = L'A';
+            CsData += sizeof(WCHAR);
+            *((ATOM *) CsData) = (ATOM)(DWORD_PTR) ClassName->Buffer;
+            CsData += sizeof(ATOM);
+        }
+        else
+        {
+            *((WCHAR *) CsData) = L'S';
+            CsData += sizeof(WCHAR);
+            RtlCopyMemory(CsData, ClassName->Buffer, ClassName->Length);
+            CsData += ClassName->Length;
+            *((WCHAR *) CsData) = L'\0';
+            CsData += sizeof(WCHAR);
+        }
+        ASSERT(CsData == (PCHAR) PackedCs + Size);
+        *lParamPacked = (LPARAM) PackedCs;
+    }
+    else if (PoolType == NonPagedPool)
+    {
+        PMSGMEMORY MsgMemoryEntry;
+        PVOID PackedData;
+        SIZE_T size;
 
-      MsgMemoryEntry = FindMsgMemory(Msg);
+        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;
-   }
+        if ((!MsgMemoryEntry) || (MsgMemoryEntry->Size < 0))
+        {
+            /* Keep previous behavior */
+            return STATUS_SUCCESS;
+        }
+        size = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
+        if (!size)
+        {
+           DPRINT1("No size for lParamPacked\n");
+           return STATUS_SUCCESS;
+        }
+        PackedData = ExAllocatePoolWithTag(NonPagedPool, size, TAG_MSG);
+        RtlCopyMemory(PackedData, (PVOID)lParam, MsgMemorySize(MsgMemoryEntry, wParam, lParam));
+        *lParamPacked = (LPARAM)PackedData;
+    }
 
-   return STATUS_SUCCESS;
+    return STATUS_SUCCESS;
 }
 
 static NTSTATUS
 UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolUsed)
 {
-   NCCALCSIZE_PARAMS *UnpackedParams;
-   NCCALCSIZE_PARAMS *PackedParams;
-   PWINDOWPOS UnpackedWindowPos;
+    NCCALCSIZE_PARAMS *UnpackedParams;
+    NCCALCSIZE_PARAMS *PackedParams;
+    PWINDOWPOS UnpackedWindowPos;
 
-   if (lParamPacked == lParam)
-   {
-      return STATUS_SUCCESS;
-   }
+    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;
-   }
-   else if (WM_CREATE == Msg || WM_NCCREATE == Msg)
-   {
-      ExFreePool((PVOID) lParamPacked);
+    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;
+    }
+    else if (WM_CREATE == Msg || WM_NCCREATE == Msg)
+    {
+        ExFreePool((PVOID) lParamPacked);
 
-      return STATUS_SUCCESS;
-   }
-   else if (NonPagedPoolUsed)
-   {
-      PMSGMEMORY MsgMemoryEntry;
-      MsgMemoryEntry = FindMsgMemory(Msg);
-      if (MsgMemoryEntry->Size < 0)
-      {
-         /* Keep previous behavior */
-         return STATUS_INVALID_PARAMETER;
-      }
+        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;
-   }
+        if (MsgMemory->Flags == MMS_FLAG_READWRITE)
+        {
+            //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemory->Size);
+        }
+        ExFreePool((PVOID) lParamPacked);
+        return STATUS_SUCCESS;
+    }
 
-   ASSERT(FALSE);
+    ASSERT(FALSE);
 
-   return STATUS_INVALID_PARAMETER;
+    return STATUS_INVALID_PARAMETER;
 }
 
-static
-VOID
-FASTCALL
-IntCallWndProc
-( PWINDOW_OBJECT Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+static NTSTATUS FASTCALL
+CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEntry)
 {
-   BOOL SameThread = FALSE;
+    NTSTATUS Status;
 
-   if (Window->pti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread()))
-      SameThread = TRUE;
+    PVOID KernelMem;
+    UINT Size;
 
-   if ((!SameThread && (Window->pti->fsHooks & HOOKID_TO_FLAG(WH_CALLWNDPROC))) ||
-        (SameThread && ISITHOOKED(WH_CALLWNDPROC)) )
-   {
-      CWPSTRUCT CWP;
-      CWP.hwnd    = hWnd;
-      CWP.message = Msg;
-      CWP.wParam  = wParam;
-      CWP.lParam  = lParam;
-      co_HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, SameThread, (LPARAM)&CWP );
-   }
-}
-
-static
-VOID
-FASTCALL
-IntCallWndProcRet
-( PWINDOW_OBJECT Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *uResult)
-{
-   BOOL SameThread = FALSE;
+    *KernelModeMsg = *UserModeMsg;
 
-   if (Window->pti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread()))
-      SameThread = TRUE;
+    /* See if this message type is present in the table */
+    if (NULL == MsgMemoryEntry)
+    {
+        /* Not present, no copying needed */
+        return STATUS_SUCCESS;
+    }
 
-   if ((!SameThread && (Window->pti->fsHooks & HOOKID_TO_FLAG(WH_CALLWNDPROCRET))) ||
-        (SameThread && ISITHOOKED(WH_CALLWNDPROCRET)) )
-   {
-      CWPRETSTRUCT CWPR;
-      CWPR.hwnd    = hWnd;
-      CWPR.message = Msg;
-      CWPR.wParam  = wParam;
-      CWPR.lParam  = lParam;
-      CWPR.lResult = *uResult;
-      co_HOOK_CallHooks( WH_CALLWNDPROCRET, HC_ACTION, SameThread, (LPARAM)&CWPR );
-   }
-}
+    /* Determine required size */
+    Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
 
-LRESULT
-FASTCALL
-IntDispatchMessage(PMSG pMsg)
-{
-  LARGE_INTEGER TickCount;
-  LONG Time;
-  LRESULT retval;
-  PMSGMEMORY MsgMemoryEntry;
-  INT lParamBufferSize;
-  LPARAM lParamPacked;
-  PWINDOW_OBJECT Window = NULL;
-
-  if (pMsg->hwnd)
-  {
-     Window = UserGetWindowObject(pMsg->hwnd);
-     if (!Window || !Window->Wnd) return 0;
-  }
-
-  if (((pMsg->message == WM_SYSTIMER) ||
-       (pMsg->message == WM_TIMER)) &&
-      (pMsg->lParam) )
-  {
-     if (pMsg->message == WM_TIMER)
-     {
-        if (ValidateTimerCallback(PsGetCurrentThreadWin32Thread(),Window,pMsg->wParam,pMsg->lParam))
-        {
-           KeQueryTickCount(&TickCount);
-           Time = MsqCalculateMessageTime(&TickCount);
-           return co_IntCallWindowProc((WNDPROC)pMsg->lParam,
-                                        TRUE,
-                                        pMsg->hwnd,
-                                        WM_TIMER,
-                                        pMsg->wParam,
-                                        (LPARAM)Time,
-                                        sizeof(LPARAM));
-        }
-        return 0;        
-     }
-     else
-     {
-        PTIMER pTimer = FindSystemTimer(pMsg);
-        if (pTimer && pTimer->pfn)
-        {
-           KeQueryTickCount(&TickCount);
-           Time = MsqCalculateMessageTime(&TickCount);
-           pTimer->pfn(pMsg->hwnd, WM_SYSTIMER, (UINT)pMsg->wParam, Time);
+    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;
         }
-        return 0;
-     }
-  }
-  // Need a window!
-  if ( !Window || !Window->Wnd ) return 0;
-
-  /* See if this message type is present in the table */
-  MsgMemoryEntry = FindMsgMemory(pMsg->message);
-  if ( !MsgMemoryEntry )
-  {
-     lParamBufferSize = -1;
-  }
-  else
-  {
-     lParamBufferSize = MsgMemorySize(MsgMemoryEntry, 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;
-  }
-
-  retval = co_IntCallWindowProc( Window->Wnd->lpfnWndProc,
-                                !Window->Wnd->Unicode,
-                                 pMsg->hwnd,
-                                 pMsg->message,
-                                 pMsg->wParam,
-                                 lParamPacked,
-                                 lParamBufferSize);
-
-  if (! NT_SUCCESS(UnpackParam(lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam, FALSE)))
-  {
-     DPRINT1("Failed to unpack message parameters\n");
-  }
-
-  if (pMsg->message == WM_PAINT)
-  {
-  /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
-     HRGN hrgn = IntSysCreateRectRgn( 0, 0, 0, 0 );
-     co_UserGetUpdateRgn( Window, hrgn, TRUE );
-     REGION_FreeRgnByHandle( hrgn );
-  }
-  return retval;
-}
+        KernelModeMsg->lParam = (LPARAM) KernelMem;
 
-VOID FASTCALL
-co_IntSendHitTestMessages(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg)
-{
-   if(!Msg->hwnd || ThreadQueue->CaptureWindow)
-   {
-      return;
-   }
-
-   switch(Msg->message)
-   {
-      case WM_MOUSEMOVE:
-         {
-            co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(HTCLIENT, Msg->message));
-            break;
-         }
-      case WM_NCMOUSEMOVE:
-         {
-            co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(Msg->wParam, Msg->message));
-            break;
-         }
-      case WM_LBUTTONDOWN:
-      case WM_MBUTTONDOWN:
-      case WM_RBUTTONDOWN:
-      case WM_XBUTTONDOWN:
-      case WM_LBUTTONDBLCLK:
-      case WM_MBUTTONDBLCLK:
-      case WM_RBUTTONDBLCLK:
-      case WM_XBUTTONDBLCLK:
-         {
-            WPARAM wParam;
-            PSYSTEM_CURSORINFO CurInfo;
-                       CurInfo = IntGetSysCursorInfo();
-
-            wParam = (WPARAM)(CurInfo->ButtonsDown);
+        /* 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");
+                ExFreePoolWithTag(KernelMem, TAG_MSG);
+                return Status;
+            }
+        }
+        else
+        {
+            /* Make sure we don't pass any secrets to usermode */
+            RtlZeroMemory(KernelMem, Size);
+        }
+    }
+    else
+    {
+        KernelModeMsg->lParam = 0;
+    }
 
-            co_IntSendMessage(Msg->hwnd, WM_MOUSEMOVE, wParam, Msg->lParam);
-            co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(HTCLIENT, Msg->message));
-            break;
-         }
-      case WM_NCLBUTTONDOWN:
-      case WM_NCMBUTTONDOWN:
-      case WM_NCRBUTTONDOWN:
-      case WM_NCXBUTTONDOWN:
-      case WM_NCLBUTTONDBLCLK:
-      case WM_NCMBUTTONDBLCLK:
-      case WM_NCRBUTTONDBLCLK:
-      case WM_NCXBUTTONDBLCLK:
-         {
-            co_IntSendMessage(Msg->hwnd, WM_NCMOUSEMOVE, (WPARAM)Msg->wParam, Msg->lParam);
-            co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(Msg->wParam, Msg->message));
-            break;
-         }
-   }
+    return STATUS_SUCCESS;
 }
 
-BOOL FASTCALL
-co_IntActivateWindowMouse(
-   PUSER_MESSAGE_QUEUE ThreadQueue,
-   LPMSG Msg,
-   PWINDOW_OBJECT MsgWindow,
-   USHORT *HitTest)
+static NTSTATUS FASTCALL
+CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
 {
-   ULONG Result;
-   PWINDOW_OBJECT Parent;
+    NTSTATUS Status;
+    PMSGMEMORY MsgMemoryEntry;
+    UINT Size;
 
-   ASSERT_REFS_CO(MsgWindow);
-
-   if(*HitTest == (USHORT)HTTRANSPARENT)
-   {
-      /* eat the message, search again! */
-      return TRUE;
-   }
+    /* 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;
+    }
 
-   Parent = IntGetParent(MsgWindow);//fixme: deref retval?
+    /* Determine required size */
+    Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
 
-   /* If no parent window, pass MsgWindows HWND as wParam. Fixes bug #3111 */
-   Result = co_IntSendMessage(MsgWindow->hSelf,
-                              WM_MOUSEACTIVATE,
-                              (WPARAM) (Parent ? Parent->hSelf : MsgWindow->hSelf),
-                              (LPARAM)MAKELONG(*HitTest, Msg->message)
-                             );
+    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;
+            }
+        }
 
-   switch (Result)
-   {
-      case MA_NOACTIVATEANDEAT:
-         return TRUE;
-      case MA_NOACTIVATE:
-         break;
-      case MA_ACTIVATEANDEAT:
-         co_IntMouseActivateWindow(MsgWindow);
-         return TRUE;
-      default:
-         /* MA_ACTIVATE */
-         co_IntMouseActivateWindow(MsgWindow);
-         break;
-   }
+        ExFreePool((PVOID) KernelModeMsg->lParam);
+    }
 
-   return FALSE;
+    return STATUS_SUCCESS;
 }
 
-BOOL FASTCALL
-co_IntTranslateMouseMessage(
-   PUSER_MESSAGE_QUEUE ThreadQueue,
-   LPMSG Msg,
-   USHORT *HitTest,
-   BOOL Remove)
+//
+// Wakeup any thread/process waiting on idle input.
+//
+VOID FASTCALL
+IdlePing(VOID)
 {
-   PWINDOW_OBJECT Window;
-   USER_REFERENCE_ENTRY Ref, DesktopRef;
+   PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
+   PUSER_MESSAGE_QUEUE ForegroundQueue;
+   PTHREADINFO pti, ptiForeground = NULL;
 
-   if(!(Window = UserGetWindowObject(Msg->hwnd)))
-   {
-      /* let's just eat the message?! */
-      return TRUE;
-   }
+   ForegroundQueue = IntGetFocusMessageQueue();
 
-   UserRefObjectCo(Window, &Ref);
+   if (ForegroundQueue)
+      ptiForeground = ForegroundQueue->Thread->Tcb.Win32Thread;
 
-   if ( ThreadQueue == Window->pti->MessageQueue &&
-        ThreadQueue->CaptureWindow != Window->hSelf)
+   pti = PsGetCurrentThreadWin32Thread();
+
+   if ( pti )
    {
-      /* only send WM_NCHITTEST messages if we're not capturing the window! */
-      *HitTest = co_IntSendMessage(Window->hSelf, WM_NCHITTEST, 0,
-                                   MAKELONG(Msg->pt.x, Msg->pt.y));
+      pti->pClientInfo->cSpins = 0; // Reset spins.
 
-      if (*HitTest == (USHORT)HTTRANSPARENT)
+      if ( pti->pDeskInfo && pti == ptiForeground )
       {
-         PWINDOW_OBJECT DesktopWindow;
-         HWND hDesktop = IntGetDesktopWindow();
-
-         if ((DesktopWindow = UserGetWindowObject(hDesktop)))
+         if ( pti->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) ||
+              pti->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) )
          {
-            PWINDOW_OBJECT Wnd;
-
-            UserRefObjectCo(DesktopWindow, &DesktopRef);
-
-            co_WinPosWindowFromPoint(DesktopWindow, Window->pti->MessageQueue, &Msg->pt, &Wnd);
-            if (Wnd)
-            {
-               if (Wnd != Window)
-               {
-                  /* post the message to the other window */
-                  Msg->hwnd = Wnd->hSelf;
-                  if(!(Wnd->state & WINDOWSTATUS_DESTROYING))
-                  {
-                     MsqPostMessage(Wnd->pti->MessageQueue, Msg, FALSE,
-                                    Msg->message == WM_MOUSEMOVE ? QS_MOUSEMOVE :
-                                    QS_MOUSEBUTTON);
-                  }
-
-                  /* eat the message */
-                  UserDereferenceObject(Wnd);
-                  UserDerefObjectCo(DesktopWindow);
-                  UserDerefObjectCo(Window);
-                  return TRUE;
-               }
-               UserDereferenceObject(Wnd);
-            }
-
-            UserDerefObjectCo(DesktopWindow);
+            co_HOOK_CallHooks(WH_FOREGROUNDIDLE,HC_ACTION,0,0);
          }
       }
    }
-   else
-   {
-      *HitTest = HTCLIENT;
-   }
 
-   if ( gspv.bMouseClickLock && 
-        ( (Msg->message == WM_LBUTTONUP) ||
-          (Msg->message == WM_LBUTTONDOWN) ) )
+   DPRINT("IdlePing ppi 0x%x\n",ppi);
+   if ( ppi && ppi->InputIdleEvent )
    {
-      if (MsqIsClkLck(Msg, Remove))
-      {
-        // FIXME: drop the message, hack: use WM_NULL
-        Msg->message = WM_NULL;
-      }
+      DPRINT("InputIdleEvent\n");
+      KeSetEvent( ppi->InputIdleEvent, IO_NO_INCREMENT, FALSE);
    }
+}
+
+VOID FASTCALL
+IdlePong(VOID)
+{
+   PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
 
-   if (IS_BTN_MESSAGE(Msg->message, DOWN))
+   DPRINT("IdlePong ppi 0x%x\n",ppi);
+   if ( ppi && ppi->InputIdleEvent )
    {
-      /* generate double click messages, if necessary */
-      if ((((*HitTest) != HTCLIENT) ||
-            (Window->Wnd->pcls->style & CS_DBLCLKS)) &&
-            MsqIsDblClk(Msg, Remove))
-      {
-         Msg->message += WM_LBUTTONDBLCLK - WM_LBUTTONDOWN;
-      }
+      KeClearEvent(ppi->InputIdleEvent);
    }
+}
 
-   if(Msg->message != WM_MOUSEWHEEL)
-   {
+UINT FASTCALL
+GetWakeMask(UINT first, UINT last )
+{
+    UINT mask = QS_POSTMESSAGE | QS_SENDMESSAGE;  /* Always selected */
 
-      if ((*HitTest) != HTCLIENT)
-      {
-         Msg->message += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
-         if ( (Msg->message == WM_NCRBUTTONUP) &&
-              (((*HitTest) == HTCAPTION) || ((*HitTest) == HTSYSMENU)) )
-         {
-            Msg->message = WM_CONTEXTMENU;
-            Msg->wParam = (WPARAM)Window->hSelf;
-         }
-         else
-         {
-            Msg->wParam = *HitTest;
-         }
-         Msg->lParam = MAKELONG(Msg->pt.x, Msg->pt.y);
-      }
-      else if ( ThreadQueue->MoveSize == NULL &&
-                ThreadQueue->MenuOwner == NULL )
-      {
-         /* NOTE: Msg->pt should remain in screen coordinates. -- FiN */
-         Msg->lParam = MAKELONG(
-                          Msg->pt.x - (WORD)Window->Wnd->rcClient.left,
-                          Msg->pt.y - (WORD)Window->Wnd->rcClient.top);
-      }
-   }
+    if (first || last)
+    {
+        if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
+        if ( ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) ||
+             ((first <= WM_NCMOUSELAST) && (last >= WM_NCMOUSEFIRST)) ) mask |= QS_MOUSE;
+        if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= QS_TIMER;
+        if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= QS_TIMER;
+        if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= QS_PAINT;
+    }
+    else mask = QS_ALLINPUT;
 
-   UserDerefObjectCo(Window);
-   return FALSE;
+    return mask;
 }
 
-BOOL ProcessMouseMessage(MSG* Msg, USHORT HitTest, UINT RemoveMsg)
+static VOID FASTCALL
+IntCallWndProc( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
 {
-    MOUSEHOOKSTRUCT MHook;
-    EVENTMSG Event;
-
-    Event.message = Msg->message;
-    Event.time    = Msg->time;
-    Event.hwnd    = Msg->hwnd;
-    Event.paramL  = Msg->pt.x;
-    Event.paramH  = Msg->pt.y;
-    co_HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&Event);
-
-
-    MHook.pt           = Msg->pt;
-    MHook.hwnd         = Msg->hwnd;
-    MHook.wHitTestCode = HitTest;
-    MHook.dwExtraInfo  = 0;
-    if (co_HOOK_CallHooks( WH_MOUSE,
-                           RemoveMsg ? HC_ACTION : HC_NOREMOVE,
-                           Msg->message,
-                           (LPARAM)&MHook ))
-    {
-        if (ISITHOOKED(WH_CBT))
-        {
-            MHook.pt           = Msg->pt;
-            MHook.hwnd         = Msg->hwnd;
-            MHook.wHitTestCode = HitTest;
-            MHook.dwExtraInfo  = 0;
-            co_HOOK_CallHooks( WH_CBT,
-                               HCBT_CLICKSKIPPED,
-                               Msg->message,
-                               (LPARAM)&MHook);
-        }
-        return FALSE;
-    }
+    BOOL SameThread = FALSE;
+    CWPSTRUCT CWP;
+
+    if (Window->head.pti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread()))
+        SameThread = TRUE;
 
-       return TRUE;
+    CWP.hwnd    = hWnd;
+    CWP.message = Msg;
+    CWP.wParam  = wParam;
+    CWP.lParam  = lParam;
+    co_HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, SameThread, (LPARAM)&CWP );
 }
 
-BOOL ProcessKeyboardMessage(MSG* Msg, UINT RemoveMsg)
+static VOID FASTCALL
+IntCallWndProcRet ( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *uResult)
 {
-   EVENTMSG Event;
+    BOOL SameThread = FALSE;
+    CWPRETSTRUCT CWPR;
+
+    if (Window->head.pti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread()))
+        SameThread = TRUE;
+
+    CWPR.hwnd    = hWnd;
+    CWPR.message = Msg;
+    CWPR.wParam  = wParam;
+    CWPR.lParam  = lParam;
+    CWPR.lResult = *uResult;
+    co_HOOK_CallHooks( WH_CALLWNDPROCRET, HC_ACTION, SameThread, (LPARAM)&CWPR );
+}
+
+LRESULT FASTCALL
+IntDispatchMessage(PMSG pMsg)
+{
+    LARGE_INTEGER TickCount;
+    LONG Time;
+    LRESULT retval = 0;
+    PTHREADINFO pti;
+    PWND Window = NULL;
+
+    if (pMsg->hwnd)
+    {
+        Window = UserGetWindowObject(pMsg->hwnd);
+        if (!Window) return 0;
+    }
 
-   Event.message = Msg->message;
-   Event.hwnd    = Msg->hwnd;
-   Event.time    = Msg->time;
-   Event.paramL  = (Msg->wParam & 0xFF) | (HIWORD(Msg->lParam) << 8);
-   Event.paramH  = Msg->lParam & 0x7FFF;
-   if (HIWORD(Msg->lParam) & 0x0100) Event.paramH |= 0x8000;
-   co_HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&Event);
+    pti = PsGetCurrentThreadWin32Thread();
 
-    if (co_HOOK_CallHooks( WH_KEYBOARD,
-                           RemoveMsg ? HC_ACTION : HC_NOREMOVE,
-                           LOWORD(Msg->wParam),
-                           Msg->lParam))
+    if ( Window->head.pti != pti)
     {
-        if (ISITHOOKED(WH_CBT))
+       EngSetLastError( ERROR_MESSAGE_SYNC_ONLY );
+       return 0;
+    }
+
+    if (((pMsg->message == WM_SYSTIMER) ||
+         (pMsg->message == WM_TIMER)) &&
+         (pMsg->lParam) )
+    {
+        if (pMsg->message == WM_TIMER)
         {
-            /* skip this message */
-            co_HOOK_CallHooks( WH_CBT,
-                               HCBT_KEYSKIPPED,
-                               LOWORD(Msg->wParam),
-                               Msg->lParam );
+            if (ValidateTimerCallback(pti,pMsg->lParam))
+            {
+                KeQueryTickCount(&TickCount);
+                Time = MsqCalculateMessageTime(&TickCount);
+                retval = co_IntCallWindowProc((WNDPROC)pMsg->lParam,
+                                              TRUE,
+                                              pMsg->hwnd,
+                                              WM_TIMER,
+                                              pMsg->wParam,
+                                              (LPARAM)Time,
+                                              0);
+            }
+            return retval;
         }
-        return FALSE;
+        else
+        {
+            PTIMER pTimer = FindSystemTimer(pMsg);
+            if (pTimer && pTimer->pfn)
+            {
+                KeQueryTickCount(&TickCount);
+                Time = MsqCalculateMessageTime(&TickCount);
+                pTimer->pfn(pMsg->hwnd, WM_SYSTIMER, (UINT)pMsg->wParam, Time);
+            }
+            return 0;
+        }
+    }
+    // Need a window!
+    if ( !Window ) return 0;
+
+    /* Since we are doing a callback on the same thread right away, there is
+       no need to copy the lparam to kernel mode and then back to usermode.
+       We just pretend it isn't a pointer */
+
+    retval = co_IntCallWindowProc( Window->lpfnWndProc,
+                                   !Window->Unicode,
+                                   pMsg->hwnd,
+                                   pMsg->message,
+                                   pMsg->wParam,
+                                   pMsg->lParam,
+                                   0);
+
+    if (pMsg->message == WM_PAINT)
+    {
+        /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
+        HRGN hrgn = IntSysCreateRectRgn( 0, 0, 0, 0 );
+        co_UserGetUpdateRgn( Window, hrgn, TRUE );
+        REGION_FreeRgnByHandle( hrgn );
     }
-       return TRUE;
+
+    return retval;
 }
+
 /*
  * Internal version of PeekMessage() doing all the work
  */
 BOOL FASTCALL
-co_IntPeekMessage( PUSER_MESSAGE Msg,
-                   PWINDOW_OBJECT Window,
+co_IntPeekMessage( PMSG Msg,
+                   PWND Window,
                    UINT MsgFilterMin,
                    UINT MsgFilterMax,
-                   UINT RemoveMsg )
+                   UINT RemoveMsg,
+                   BOOL bGMSG )
 {
-   PTHREADINFO pti;
-   LARGE_INTEGER LargeTickCount;
-   PUSER_MESSAGE_QUEUE ThreadQueue;
-   PUSER_MESSAGE Message;
-   BOOL Present, RemoveMessages;
-   USER_REFERENCE_ENTRY Ref;
-   USHORT HitTest;
+    PTHREADINFO pti;
+    PCLIENTINFO pci;
+    LARGE_INTEGER LargeTickCount;
+    PUSER_MESSAGE_QUEUE ThreadQueue;
+    BOOL RemoveMessages;
+    UINT ProcessMask;
+    BOOL Hit = FALSE;
 
-   /* The queues and order in which they are checked are documented in the MSDN
-      article on GetMessage() */
+    pti = PsGetCurrentThreadWin32Thread();
+    ThreadQueue = pti->MessageQueue;
+    pci = pti->pClientInfo;
 
-   pti = PsGetCurrentThreadWin32Thread();
-   ThreadQueue = pti->MessageQueue;
-
-   /* Inspect RemoveMsg flags */
-   /* Note:
-       The only flag we process is PM_REMOVE.
-       Processing (High word) PM_QS_Xx Is needed. This and MsgFilterXxx can result
-       with QS_Xx flags to be used to isolate which message check to test for.
-       ATM, we look at all messages and the filters are sent to co_MsqFindMessage
-       and there, it is cross checked.
-       Example: Wine server/queue.c is_keyboard_msg, check_msg_filter and
-                filter_contains_hw_range.
-    */
-   RemoveMessages = RemoveMsg & PM_REMOVE;
+    RemoveMessages = RemoveMsg & PM_REMOVE;
+    ProcessMask = HIWORD(RemoveMsg);
 
-/*
-   If no filter is specified, messages are processed in the following order:
-
-    * Sent messages
-    * Posted messages
-    * Input (hardware) messages and system internal events
-    * Sent messages (again)
-    * WM_PAINT messages
-    * WM_TIMER messages
- */
-CheckMessages:
-
-   Present = FALSE;
-
-   KeQueryTickCount(&LargeTickCount);
-   ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
+ /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
+    all available messages (that is, no range filtering is performed)".        */
+    if (!ProcessMask) ProcessMask = (QS_ALLPOSTMESSAGE|QS_ALLINPUT);
 
-   /* Dispatch sent messages here. */
-   while (co_MsqDispatchOneSentMessage(ThreadQueue))
-      ;
+    IdlePong();
 
-   /* Now look for a quit message. */
-
-   if (ThreadQueue->QuitPosted)
-   {
-      /* According to the PSDK, WM_QUIT messages are always returned, regardless
-         of the filter specified */
-      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;
-      }
-      goto MsgExit;
-   }
+    do
+    {
+        KeQueryTickCount(&LargeTickCount);
+        ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
+        pti->pcti->tickLastMsgChecked = LargeTickCount.u.LowPart;
 
-   /* Now check for normal messages. */
-   Present = co_MsqFindMessage( ThreadQueue,
-                                FALSE,
-                                RemoveMessages,
-                                Window,
-                                MsgFilterMin,
-                                MsgFilterMax,
-                               &Message );
-   if (Present)
-   {
-      RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
-      if (RemoveMessages)
-      {
-         MsqDestroyMessage(Message);
-      }
-      goto MessageFound;
-   }
+        /* Dispatch sent messages here. */
+        while ( co_MsqDispatchOneSentMessage(ThreadQueue) )
+        {
+           /* if some PM_QS* flags were specified, only handle sent messages from now on */
+           if (HIWORD(RemoveMsg) && !bGMSG) Hit = TRUE; // wine does this; ProcessMask = QS_SENDMESSAGE;
+        }
+        if (Hit) return FALSE;
 
-   /* Check for hardware events. */
-   Present = co_MsqFindMessage( ThreadQueue,
-                                TRUE,
-                                RemoveMessages,
-                                Window,
-                                MsgFilterMin,
-                                MsgFilterMax,
-                               &Message );
-   if (Present)
-   {
-      RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
-      if (RemoveMessages)
-      {
-         MsqDestroyMessage(Message);
-      }
-      goto MessageFound;
-   }
+        /* Clear changed bits so we can wait on them if we don't find a message */
+        if (ProcessMask & QS_POSTMESSAGE)
+        {
+           pti->pcti->fsChangeBits &= ~(QS_POSTMESSAGE | QS_HOTKEY | QS_TIMER);
+           if (MsgFilterMin == 0 && MsgFilterMax == 0) // wine hack does this; ~0U)
+           {
+              pti->pcti->fsChangeBits &= ~QS_ALLPOSTMESSAGE;
+           }
+        }
 
-   /* Check for sent messages again. */
-   while (co_MsqDispatchOneSentMessage(ThreadQueue))
-      ;
+        if (ProcessMask & QS_INPUT)
+        {
+           pti->pcti->fsChangeBits &= ~QS_INPUT;
+        }
 
-   /* Check for paint messages. */
-   if ( IntGetPaintMessage( Window,
+        /* Now check for normal messages. */
+        if (( (ProcessMask & QS_POSTMESSAGE) ||
+              (ProcessMask & QS_HOTKEY) ) &&
+            MsqPeekMessage( ThreadQueue,
+                            RemoveMessages,
+                            Window,
                             MsgFilterMin,
                             MsgFilterMax,
-                            pti,
-                            &Msg->Msg,
-                            RemoveMessages))
-   {
-      Msg->FreeLParam = FALSE;
-      goto MsgExit;
-   }
-
-   if (PostTimerMessages(Window))
-      goto CheckMessages;
-
-   if(Present)
-   {
-MessageFound:
-
-      if(RemoveMessages)
-      {
-         PWINDOW_OBJECT MsgWindow = NULL;
-
-         /* Mouse message process */
-
-         if( Msg->Msg.hwnd &&
-            ( MsgWindow = UserGetWindowObject(Msg->Msg.hwnd) ) &&
-             Msg->Msg.message >= WM_MOUSEFIRST &&
-             Msg->Msg.message <= WM_MOUSELAST )
-         {
-            USHORT HitTest;
-
-            UserRefObjectCo(MsgWindow, &Ref);
-
-            if ( co_IntTranslateMouseMessage( ThreadQueue,
-                                              &Msg->Msg,
-                                              &HitTest,
-                                              TRUE))
-         /* FIXME - check message filter again, if the message doesn't match anymore,
-                    search again */
-            {
-               UserDerefObjectCo(MsgWindow);
-               /* eat the message, search again */
-               goto CheckMessages;
-            }
+                            ProcessMask,
+                            Msg ))
+        {
+               return TRUE;
+        }
 
-            if(ThreadQueue->CaptureWindow == NULL)
+        /* Now look for a quit message. */
+        if (ThreadQueue->QuitPosted)
+        {
+            /* 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;
+            if (RemoveMessages)
             {
-               co_IntSendHitTestMessages(ThreadQueue, &Msg->Msg);
-
-               if ( ( Msg->Msg.message != WM_MOUSEMOVE &&
-                      Msg->Msg.message != WM_NCMOUSEMOVE ) &&
-                     IS_BTN_MESSAGE(Msg->Msg.message, DOWN) &&
-                     co_IntActivateWindowMouse(ThreadQueue, &Msg->Msg, MsgWindow, &HitTest) )
-               {
-                  UserDerefObjectCo(MsgWindow);
-                  /* eat the message, search again */
-                  goto CheckMessages;
-               }
+                ThreadQueue->QuitPosted = FALSE;
+                ClearMsgBitsMask(ThreadQueue, QS_POSTMESSAGE);
+                pti->pcti->fsWakeBits &= ~QS_ALLPOSTMESSAGE;
+                pti->pcti->fsChangeBits &= ~QS_ALLPOSTMESSAGE;
             }
+            return TRUE;
+        }
 
-            UserDerefObjectCo(MsgWindow);
-         }
-         else
-         {
-            co_IntSendHitTestMessages(ThreadQueue, &Msg->Msg);
-         }
-
-//         if(MsgWindow)
-//         {
-//            UserDereferenceObject(MsgWindow);
-//         }
-
-         goto MsgExit;
-      }
-
-      if ( ( Msg->Msg.hwnd &&
-             Msg->Msg.message >= WM_MOUSEFIRST &&
-             Msg->Msg.message <= WM_MOUSELAST ) &&
-           co_IntTranslateMouseMessage( ThreadQueue,
-                                       &Msg->Msg,
-                                       &HitTest,
-                                        FALSE) )
-    /* FIXME - check message filter again, if the message doesn't match anymore,
-               search again */
-      {
-         /* eat the message, search again */
-         goto CheckMessages;
-      }
-
-MsgExit:
-      if ( ISITHOOKED(WH_MOUSE) && IS_MOUSE_MESSAGE(Msg->Msg.message))
-      {
-          if(!ProcessMouseMessage(&Msg->Msg, HitTest, RemoveMsg))
-                 {
-                         return FALSE;
-                 }
-         }
-
-      if ( ISITHOOKED(WH_KEYBOARD) && IS_KBD_MESSAGE(Msg->Msg.message))
-      {
-          if(!ProcessKeyboardMessage(&Msg->Msg, RemoveMsg))
-          {
-              return FALSE;
-          }
-      }
-      // The WH_GETMESSAGE hook enables an application to monitor messages about to
-      // be returned by the GetMessage or PeekMessage function.
-      if (ISITHOOKED(WH_GETMESSAGE))
-      {
-         //DPRINT1("Peek WH_GETMESSAGE -> %x\n",&Msg);
-         co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)&Msg->Msg);
-      }
-      return TRUE;
-   }
-
-   return Present;
-}
-
-static NTSTATUS FASTCALL
-CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEntry)
-{
-   NTSTATUS Status;
-
-   PVOID KernelMem;
-   UINT Size;
-
-   *KernelModeMsg = *UserModeMsg;
-
-   /* See if this message type is present in the table */
-   if (NULL == MsgMemoryEntry)
-   {
-      /* Not present, no copying needed */
-      return STATUS_SUCCESS;
-   }
-
-   /* 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");
-            ExFreePoolWithTag(KernelMem, TAG_MSG);
-            return Status;
-         }
-      }
-      else
-      {
-         /* Make sure we don't pass any secrets to usermode */
-         RtlZeroMemory(KernelMem, Size);
-      }
-   }
-   else
-   {
-      KernelModeMsg->lParam = 0;
-   }
-
-   return STATUS_SUCCESS;
-}
+        /* Check for hardware events. */
+        if ((ProcessMask & QS_MOUSE) &&
+            co_MsqPeekMouseMove( ThreadQueue,
+                                 RemoveMessages,
+                                 Window,
+                                 MsgFilterMin,
+                                 MsgFilterMax,
+                                 Msg ))
+        {
+            return TRUE;
+        }
 
-static NTSTATUS FASTCALL
-CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
-{
-   NTSTATUS Status;
-   PMSGMEMORY MsgMemoryEntry;
-   UINT Size;
+        if ((ProcessMask & QS_INPUT) &&
+            co_MsqPeekHardwareMessage( ThreadQueue,
+                                       RemoveMessages,
+                                       Window,
+                                       MsgFilterMin,
+                                       MsgFilterMax,
+                                       ProcessMask,
+                                       Msg))
+        {
+            return TRUE;
+        }
 
-   /* 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;
-   }
+        /* Check for sent messages again. */
+        while ( co_MsqDispatchOneSentMessage(ThreadQueue) )
+        {
+           if (HIWORD(RemoveMsg) && !bGMSG) Hit = TRUE;
+        }
+        if (Hit) return FALSE;
 
-   /* Determine required size */
-   Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
+        /* Check for paint messages. */
+        if ((ProcessMask & QS_PAINT) &&
+            pti->cPaintsReady &&
+            IntGetPaintMessage( Window,
+                                MsgFilterMin,
+                                MsgFilterMax,
+                                pti,
+                                Msg,
+                                RemoveMessages))
+        {
+            return TRUE;
+        }
 
-   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;
-         }
-      }
+       /* This is correct, check for the current threads timers waiting to be
+          posted to this threads message queue. If any we loop again.
+        */
+        if ((ProcessMask & QS_TIMER) &&
+            PostTimerMessages(Window))
+        {
+            continue;
+        }
 
-      ExFreePool((PVOID) KernelModeMsg->lParam);
-   }
+        return FALSE;
+    }
+    while (TRUE);
 
-   return STATUS_SUCCESS;
+    return TRUE;
 }
 
 static BOOL FASTCALL
-co_IntWaitMessage( PWINDOW_OBJECT Window,
+co_IntWaitMessage( PWND Window,
                    UINT MsgFilterMin,
                    UINT MsgFilterMax )
 {
-   PTHREADINFO pti;
-   PUSER_MESSAGE_QUEUE ThreadQueue;
-   NTSTATUS Status = STATUS_SUCCESS;
-   USER_MESSAGE Msg;
+    PTHREADINFO pti;
+    PUSER_MESSAGE_QUEUE ThreadQueue;
+    NTSTATUS Status = STATUS_SUCCESS;
+    MSG Msg;
 
-   pti = PsGetCurrentThreadWin32Thread();
-   ThreadQueue = pti->MessageQueue;
+    pti = PsGetCurrentThreadWin32Thread();
+    ThreadQueue = pti->MessageQueue;
 
-   do
-   {
-      if ( co_IntPeekMessage( &Msg,
-                               Window,
-                               MsgFilterMin,
-                               MsgFilterMax,
-                               PM_NOREMOVE))
-      {
-         return TRUE;
-      }
-      /* Nothing found. Wait for new messages. */
-      Status = co_MsqWaitForNewMessages( ThreadQueue,
-                                         Window,
-                                         MsgFilterMin,
-                                         MsgFilterMax);
-   }
-   while ( (STATUS_WAIT_0 <= Status && Status <= STATUS_WAIT_63) ||
-           STATUS_TIMEOUT == Status );
+    do
+    {
+        if ( co_IntPeekMessage( &Msg,       // Dont reenter!
+                                 Window,
+                                 MsgFilterMin,
+                                 MsgFilterMax,
+                                 MAKELONG( PM_NOREMOVE, GetWakeMask( MsgFilterMin, MsgFilterMax)),
+                                 TRUE ) )   // act like GetMessage.
+        {
+            return TRUE;
+        }
 
-   if (!NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      DPRINT1("Exit co_IntWaitMessage on error!\n");
-   }
+        /* Nothing found. Wait for new messages. */
+        Status = co_MsqWaitForNewMessages( ThreadQueue,
+                                           Window,
+                                           MsgFilterMin,
+                                           MsgFilterMax);
+        if (!NT_SUCCESS(Status))
+        {
+            SetLastNtError(Status);
+            DPRINT1("Exit co_IntWaitMessage on error!\n");
+            return FALSE;
+        }
+        if (Status == STATUS_USER_APC || Status == STATUS_TIMEOUT)
+        {
+           return FALSE;
+        }
+    }
+    while ( TRUE );
 
-   return FALSE;
+    return FALSE;
 }
 
 BOOL FASTCALL
@@ -1130,72 +881,110 @@ co_IntGetPeekMessage( PMSG pMsg,
                       UINT RemoveMsg,
                       BOOL bGMSG )
 {
-   BOOL Present;
-   PWINDOW_OBJECT Window;
-   USER_MESSAGE Msg;
+    PWND Window;
+    PTHREADINFO pti;
+    BOOL Present = FALSE;
+    NTSTATUS Status;
 
-   if ( hWnd == HWND_TOPMOST ||
-        hWnd == HWND_BROADCAST )
-      hWnd = HWND_BOTTOM;
+    if ( hWnd == HWND_TOPMOST || hWnd == HWND_BROADCAST )
+        hWnd = HWND_BOTTOM;
 
-   /* Validate input */
-   if (hWnd && hWnd != HWND_BOTTOM)
-   {
-      if (!(Window = UserGetWindowObject(hWnd)))
-      {
-         if (bGMSG)
-            return -1;
-         else
-            return FALSE;
-      }
-   }
-   else
-   {
-      Window = (PWINDOW_OBJECT)hWnd;
-   }
+    /* Validate input */
+    if (hWnd && hWnd != HWND_BOTTOM)
+    {
+        if (!(Window = UserGetWindowObject(hWnd)))
+        {
+            if (bGMSG)
+                return -1;
+            else
+                return FALSE;
+        }
+    }
+    else
+    {
+        Window = (PWND)hWnd;
+    }
 
-   if (MsgFilterMax < MsgFilterMin)
-   {
-      MsgFilterMin = 0;
-      MsgFilterMax = 0;
-   }
+    if (MsgFilterMax < MsgFilterMin)
+    {
+        MsgFilterMin = 0;
+        MsgFilterMax = 0;
+    }
 
-   do
-   {
-      Present = co_IntPeekMessage( &Msg,
-                                    Window,
-                                    MsgFilterMin,
-                                    MsgFilterMax,
-                                    RemoveMsg );
-      if (Present)
-      {
-         RtlCopyMemory( pMsg, &Msg.Msg, sizeof(MSG));
+    if (bGMSG)
+    {
+       RemoveMsg |= ((GetWakeMask( MsgFilterMin, MsgFilterMax ))<< 16);
+    }
 
-         if (bGMSG)
-            return (WM_QUIT != pMsg->message);
-         else
-            return TRUE;
-      }
+    pti = PsGetCurrentThreadWin32Thread();
+    pti->pClientInfo->cSpins++; // Bump up the spin count.
 
-      if ( bGMSG && !co_IntWaitMessage(Window, MsgFilterMin, MsgFilterMax) )
-      {
-         return -1;
-      }
-      else
-      {
-         if (!(RemoveMsg & PM_NOYIELD))
-         {
-         // Yield this thread!
-            UserLeave();
-            ZwYieldExecution();
-            UserEnterExclusive();
-         // Fall through to fail.
-         }
-      }
-   }
-   while( bGMSG && !Present );
+    do
+    {
+        Present = co_IntPeekMessage( pMsg,
+                                     Window,
+                                     MsgFilterMin,
+                                     MsgFilterMax,
+                                     RemoveMsg,
+                                     bGMSG );
+        if (Present)
+        {
+           /* GetMessage or PostMessage must never get messages that contain pointers */
+           ASSERT(FindMsgMemory(pMsg->message) == NULL);
+
+           if (pMsg->message != WM_PAINT && pMsg->message != WM_QUIT)
+           {
+              pti->timeLast = pMsg->time;
+              pti->ptLast   = pMsg->pt;
+           }
+
+           // The WH_GETMESSAGE hook enables an application to monitor messages about to
+           // be returned by the GetMessage or PeekMessage function.
+
+           co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)pMsg);
+
+           if ( bGMSG ) break;
+        }
 
-   return FALSE;
+        if ( bGMSG )
+        {
+            Status = co_MsqWaitForNewMessages( pti->MessageQueue,
+                                               Window,
+                                               MsgFilterMin,
+                                               MsgFilterMax);
+           if ( !NT_SUCCESS(Status) ||
+                Status == STATUS_USER_APC ||
+                Status == STATUS_TIMEOUT )
+           {
+              Present = -1;
+              break;
+           }
+        }
+        else
+        {
+           if (!(RemoveMsg & PM_NOYIELD))
+           {
+              IdlePing();
+              // Yield this thread!
+              UserLeave();
+              ZwYieldExecution();
+              UserEnterExclusive();
+              // Fall through to exit.
+              IdlePong();
+           }
+           break;
+        }
+    }
+    while( bGMSG && !Present );
+
+    // Been spinning, time to swap vinyl...
+    if (pti->pClientInfo->cSpins >= 100)
+    {
+       // Clear the spin cycle to fix the mix.
+       pti->pClientInfo->cSpins = 0;
+       //if (!(pti->TIF_flags & TIF_SPINNING)) FIXME need to swap vinyl..
+    }
+    return Present;
 }
 
 BOOL FASTCALL
@@ -1204,50 +993,48 @@ UserPostThreadMessage( DWORD idThread,
                        WPARAM wParam,
                        LPARAM lParam )
 {
-   MSG Message;
-   PETHREAD peThread;
-   PTHREADINFO pThread;
-   LARGE_INTEGER LargeTickCount;
-   NTSTATUS Status;
-
-   DPRINT1("UserPostThreadMessage wParam 0x%x  lParam 0x%x\n", wParam,lParam);
+    MSG Message;
+    PETHREAD peThread;
+    PTHREADINFO pThread;
+    LARGE_INTEGER LargeTickCount;
+    NTSTATUS Status;
 
-   if (FindMsgMemory(Msg) != 0)
-   {
-      SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
-      return FALSE;
-   }
+    if (is_pointer_message(Msg))
+    {
+        EngSetLastError(ERROR_MESSAGE_SYNC_ONLY );
+        return FALSE;
+    }
 
-   Status = PsLookupThreadByThreadId((HANDLE)idThread,&peThread);
+    Status = PsLookupThreadByThreadId((HANDLE)idThread,&peThread);
 
-   if( Status == STATUS_SUCCESS )
-   {
-      pThread = (PTHREADINFO)peThread->Tcb.Win32Thread;
-      if( !pThread ||
-          !pThread->MessageQueue ||
-         (pThread->TIF_flags & TIF_INCLEANUP))
-      {
-         ObDereferenceObject( peThread );
-         return FALSE;
-      }
+    if( Status == STATUS_SUCCESS )
+    {
+        pThread = (PTHREADINFO)peThread->Tcb.Win32Thread;
+        if( !pThread ||
+            !pThread->MessageQueue ||
+            (pThread->TIF_flags & TIF_INCLEANUP))
+        {
+            ObDereferenceObject( peThread );
+            return FALSE;
+        }
 
-      Message.hwnd = NULL;
-      Message.message = Msg;
-      Message.wParam = wParam;
-      Message.lParam = lParam;
-      Message.pt = gpsi->ptCursor;
-
-      KeQueryTickCount(&LargeTickCount);
-      pThread->timeLast = Message.time = MsqCalculateMessageTime(&LargeTickCount);
-      MsqPostMessage(pThread->MessageQueue, &Message, FALSE, QS_POSTMESSAGE);
-      ObDereferenceObject( peThread );
-      return TRUE;
-   }
-   else
-   {
-      SetLastNtError( Status );
-   }
-   return FALSE;
+        Message.hwnd = NULL;
+        Message.message = Msg;
+        Message.wParam = wParam;
+        Message.lParam = lParam;
+        Message.pt = gpsi->ptCursor;
+
+        KeQueryTickCount(&LargeTickCount);
+        Message.time = MsqCalculateMessageTime(&LargeTickCount);
+        MsqPostMessage(pThread->MessageQueue, &Message, FALSE, QS_POSTMESSAGE);
+        ObDereferenceObject( peThread );
+        return TRUE;
+    }
+    else
+    {
+        SetLastNtError( Status );
+    }
+    return FALSE;
 }
 
 BOOL FASTCALL
@@ -1256,79 +1043,108 @@ UserPostMessage( HWND Wnd,
                  WPARAM wParam,
                  LPARAM lParam )
 {
-   PTHREADINFO pti;
-   MSG Message;
-   LARGE_INTEGER LargeTickCount;
+    PTHREADINFO pti;
+    MSG Message, KernelModeMsg;
+    LARGE_INTEGER LargeTickCount;
+
+    Message.hwnd = Wnd;
+    Message.message = Msg;
+    Message.wParam = wParam;
+    Message.lParam = lParam;
+    Message.pt = gpsi->ptCursor;
+    KeQueryTickCount(&LargeTickCount);
+    Message.time = MsqCalculateMessageTime(&LargeTickCount);
+
+    if (is_pointer_message(Message.message))
+    {
+        EngSetLastError(ERROR_MESSAGE_SYNC_ONLY );
+        return FALSE;
+    }
 
-   if (FindMsgMemory(Msg) != 0)
-   {
-      SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
-      return FALSE;
-   }
+    if( Msg >= WM_DDE_FIRST && Msg <= WM_DDE_LAST )
+    {
+        NTSTATUS Status;
+        PMSGMEMORY MsgMemoryEntry;
 
-   if (!Wnd) 
-      return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
-                                    Msg,
-                                    wParam,
-                                    lParam);
+        MsgMemoryEntry = FindMsgMemory(Message.message);
 
-   if (Wnd == HWND_BROADCAST)
-   {
-      HWND *List;
-      PWINDOW_OBJECT DesktopWindow;
-      ULONG i;
+        Status = CopyMsgToKernelMem(&KernelModeMsg, &Message, MsgMemoryEntry);
+        if (! NT_SUCCESS(Status))
+        {
+            EngSetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+        }
+        co_IntSendMessageNoWait(KernelModeMsg.hwnd,
+                                KernelModeMsg.message,
+                                KernelModeMsg.wParam,
+                                KernelModeMsg.lParam);
 
-      DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
-      List = IntWinListChildren(DesktopWindow);
+        if (MsgMemoryEntry && KernelModeMsg.lParam)
+            ExFreePool((PVOID) KernelModeMsg.lParam);
 
-      if (List != NULL)
-      {
-         for (i = 0; List[i]; i++)
-            UserPostMessage(List[i], Msg, wParam, lParam);
-         ExFreePool(List);
-      }
-   }
-   else
-   {
-      PWINDOW_OBJECT Window;
+        return TRUE;
+    }
 
-      Window = UserGetWindowObject(Wnd);
-      if ( !Window || !Window->Wnd )
-      {
-         return FALSE;
-      }
+    if (!Wnd)
+    {
+        return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
+                                      Msg,
+                                      wParam,
+                                      lParam);
+    }
+    if (Wnd == HWND_BROADCAST)
+    {
+        HWND *List;
+        PWND DesktopWindow;
+        ULONG i;
 
-      pti = Window->Wnd->head.pti;
-      if ( pti->TIF_flags & TIF_INCLEANUP )
-      {
-         DPRINT1("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd);
-         return FALSE;
-      }
+        DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+        List = IntWinListChildren(DesktopWindow);
 
-      if ( Window->state & WINDOWSTATUS_DESTROYING )
-      {
-         DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd);
-         /* FIXME - last error code? */
-         return FALSE;
-      }
+        if (List != NULL)
+        {
+            UserPostMessage(DesktopWindow->head.h, Msg, wParam, lParam);
+            for (i = 0; List[i]; i++)
+            {
+                UserPostMessage(List[i], Msg, wParam, lParam);
+            }
+            ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
+        }
+    }
+    else
+    {
+        PWND Window;
 
-      if (WM_QUIT == Msg)
-      {
-          MsqPostQuitMessage(Window->pti->MessageQueue, wParam);
-      }
-      else
-      {
-         Message.hwnd = Wnd;
-         Message.message = Msg;
-         Message.wParam = wParam;
-         Message.lParam = lParam;
-         Message.pt = gpsi->ptCursor;
-         KeQueryTickCount(&LargeTickCount);
-         pti->timeLast = Message.time = MsqCalculateMessageTime(&LargeTickCount);
-         MsqPostMessage(Window->pti->MessageQueue, &Message, FALSE, QS_POSTMESSAGE);
-      }
-   }
-   return TRUE;
+        Window = UserGetWindowObject(Wnd);
+        if ( !Window )
+        {
+            return FALSE;
+        }
+
+        pti = Window->head.pti;
+        if ( pti->TIF_flags & TIF_INCLEANUP )
+        {
+            DPRINT1("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd);
+            return FALSE;
+        }
+
+        if ( Window->state & WNDS_DESTROYED )
+        {
+            DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd);
+            /* FIXME - last error code? */
+            return FALSE;
+        }
+
+        if (WM_QUIT == Msg)
+        {
+            MsqPostQuitMessage(Window->head.pti->MessageQueue, wParam);
+        }
+        else
+        {
+            MsqPostMessage(Window->head.pti->MessageQueue, &Message, FALSE, QS_POSTMESSAGE);
+        }
+    }
+    return TRUE;
 }
 
 
@@ -1338,16 +1154,15 @@ co_IntSendMessage( HWND hWnd,
                    WPARAM wParam,
                    LPARAM lParam )
 {
-   ULONG_PTR Result = 0;
-   if(co_IntSendMessageTimeout(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
-   {
-      return (LRESULT)Result;
-   }
-   return 0;
+    ULONG_PTR Result = 0;
+    if(co_IntSendMessageTimeout(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
+    {
+        return (LRESULT)Result;
+    }
+    return 0;
 }
 
-static
-LRESULT FASTCALL
+static LRESULT FASTCALL
 co_IntSendMessageTimeoutSingle( HWND hWnd,
                                 UINT Msg,
                                 WPARAM wParam,
@@ -1356,131 +1171,135 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
                                 UINT uTimeout,
                                 ULONG_PTR *uResult )
 {
-   ULONG_PTR Result;
-   NTSTATUS Status;
-   PWINDOW_OBJECT Window = NULL;
-   PMSGMEMORY MsgMemoryEntry;
-   INT lParamBufferSize;
-   LPARAM lParamPacked;
-   PTHREADINFO Win32Thread;
-   DECLARE_RETURN(LRESULT);
-   USER_REFERENCE_ENTRY Ref;
-
-   if (!(Window = UserGetWindowObject(hWnd)))
-   {
-       RETURN( FALSE);
-   }
+    NTSTATUS Status;
+    PWND Window = NULL;
+    PMSGMEMORY MsgMemoryEntry;
+    INT lParamBufferSize;
+    LPARAM lParamPacked;
+    PTHREADINFO Win32Thread;
+    ULONG_PTR Result = 0;
+    DECLARE_RETURN(LRESULT);
+    USER_REFERENCE_ENTRY Ref;
+
+    if (!(Window = UserGetWindowObject(hWnd)))
+    {
+        RETURN( FALSE);
+    }
 
-   UserRefObjectCo(Window, &Ref);
+    UserRefObjectCo(Window, &Ref);
 
-   Win32Thread = PsGetCurrentThreadWin32Thread();
+    Win32Thread = PsGetCurrentThreadWin32Thread();
 
-   IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
+    IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
 
-   if ( NULL != Win32Thread &&
-        Window->pti->MessageQueue == Win32Thread->MessageQueue)
-   {
-      if (Win32Thread->TIF_flags & TIF_INCLEANUP)
-      {
-         /* Never send messages to exiting threads */
-          RETURN( FALSE);
-      }
+    if ( NULL != Win32Thread &&
+         Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
+    {
+        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);
-      }
+        /* 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, FALSE)))
-      {
-          DPRINT1("Failed to pack message parameters\n");
-          RETURN( FALSE);
-      }
+        if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, FALSE)))
+        {
+            DPRINT1("Failed to pack message parameters\n");
+            RETURN( FALSE);
+        }
 
-      Result = (ULONG_PTR)co_IntCallWindowProc( Window->Wnd->lpfnWndProc,
-                                               !Window->Wnd->Unicode,
-                                                hWnd,
-                                                Msg,
-                                                wParam,
-                                                lParamPacked,
-                                                lParamBufferSize );
-      if(uResult)
-      {
-         *uResult = Result;
-      }
+        ObReferenceObject(Win32Thread->pEThread);
+        Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc,
+                                                  !Window->Unicode,
+                                                  hWnd,
+                                                  Msg,
+                                                  wParam,
+                                                  lParamPacked,
+                                                  lParamBufferSize );
+        if(uResult)
+        {
+            *uResult = Result;
+        }
 
-      IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
+        ObDereferenceObject(Win32Thread->pEThread);
 
-      if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
-      {
-         DPRINT1("Failed to unpack message parameters\n");
-         RETURN( TRUE);
-      }
+        IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
 
-      RETURN( TRUE);
-   }
+        if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
+        {
+            DPRINT1("Failed to unpack message parameters\n");
+            RETURN( TRUE);
+        }
 
-   if (uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->pti->MessageQueue))
-   {
-      /* FIXME - Set a LastError? */
-      RETURN( FALSE);
-   }
+        RETURN( TRUE);
+    }
 
-   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);
-   }
+    if (uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->head.pti->MessageQueue))
+    {
+        // FIXME - Set window hung and add to a list.
+        /* FIXME - Set a LastError? */
+        RETURN( FALSE);
+    }
 
-   do
-   {
-      Status = co_MsqSendMessage( Window->pti->MessageQueue,
-                                                       hWnd,
-                                                        Msg,
-                                                     wParam,
-                                                     lParam,
-                                                   uTimeout,
-                                      (uFlags & SMTO_BLOCK),
-                                                 MSQ_NORMAL,
-                                                    uResult );
-   }
-   while ((STATUS_TIMEOUT == Status) &&
-          (uFlags & SMTO_NOTIMEOUTIFNOTHUNG) &&
-          !MsqIsHung(Window->pti->MessageQueue));
+    if (Window->state & WNDS_DESTROYED)
+    {
+        /* FIXME - last error? */
+        DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd);
+        RETURN( FALSE);
+    }
+
+    do
+    {
+        Status = co_MsqSendMessage( Window->head.pti->MessageQueue,
+                                    hWnd,
+                                    Msg,
+                                    wParam,
+                                    lParam,
+                                    uTimeout,
+                                    (uFlags & SMTO_BLOCK),
+                                    MSQ_NORMAL,
+                                    uResult );
+    }
+    while ((STATUS_TIMEOUT == Status) &&
+           (uFlags & SMTO_NOTIMEOUTIFNOTHUNG) &&
+           !MsqIsHung(Window->head.pti->MessageQueue)); // FIXME - Set window hung and add to a list.
 
-   IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
+    IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
 
-   if (STATUS_TIMEOUT == Status)
-   {
+    if (STATUS_TIMEOUT == Status)
+    {
 /*
-   MSDN says:
-      Microsoft Windows 2000: If GetLastError returns zero, then the function
-      timed out.
-      XP+ : If the function fails or times out, the return value is zero.
-      To get extended error information, call GetLastError. If GetLastError
-      returns ERROR_TIMEOUT, then the function timed out.
- */
-      SetLastWin32Error(ERROR_TIMEOUT);
-      RETURN( FALSE);
-   }
-   else if (! NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      RETURN( FALSE);
-   }
+    MSDN says:
+    Microsoft Windows 2000: If GetLastError returns zero, then the function
+    timed out.
+    XP+ : If the function fails or times out, the return value is zero.
+    To get extended error information, call GetLastError. If GetLastError
+    returns ERROR_TIMEOUT, then the function timed out.
+*/
+        EngSetLastError(ERROR_TIMEOUT);
+        RETURN( FALSE);
+    }
+    else if (! NT_SUCCESS(Status))
+    {
+        SetLastNtError(Status);
+        RETURN( FALSE);
+    }
 
-   RETURN( TRUE);
+    RETURN( TRUE);
 
 CLEANUP:
-   if (Window) UserDerefObjectCo(Window);
-   END_CLEANUP;
+    if (Window) UserDerefObjectCo(Window);
+    END_CLEANUP;
 }
 
 LRESULT FASTCALL
@@ -1492,217 +1311,249 @@ co_IntSendMessageTimeout( HWND hWnd,
                           UINT uTimeout,
                           ULONG_PTR *uResult )
 {
-   PWINDOW_OBJECT DesktopWindow;
-   HWND *Children;
-   HWND *Child;
+    PWND DesktopWindow;
+    HWND *Children;
+    HWND *Child;
 
-   if (HWND_BROADCAST != hWnd)
-   {
-      return co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, uFlags, uTimeout, uResult);
-   }
+    if (HWND_BROADCAST != hWnd)
+    {
+        return co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, uFlags, uTimeout, uResult);
+    }
 
-   DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
-   if (NULL == DesktopWindow)
-   {
-      SetLastWin32Error(ERROR_INTERNAL_ERROR);
-      return 0;
-   }
+    DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+    if (NULL == DesktopWindow)
+    {
+        EngSetLastError(ERROR_INTERNAL_ERROR);
+        return 0;
+    }
 
-   Children = IntWinListChildren(DesktopWindow);
-   if (NULL == Children)
-   {
-      return 0;
-   }
+    /* Send message to the desktop window too! */
+    co_IntSendMessageTimeoutSingle(DesktopWindow->head.h, Msg, wParam, lParam, uFlags, uTimeout, uResult);
 
-   for (Child = Children; NULL != *Child; Child++)
-   {
-      co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout, uResult);
-   }
+    Children = IntWinListChildren(DesktopWindow);
+    if (NULL == Children)
+    {
+        return 0;
+    }
 
-   ExFreePool(Children);
+    for (Child = Children; NULL != *Child; Child++)
+    {
+        co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout, uResult);
+    }
+
+    ExFreePool(Children);
 
-   return (LRESULT) TRUE;
+    return (LRESULT) TRUE;
 }
 
-LRESULT FASTCALL co_IntSendMessageNoWait(HWND hWnd,
-                                         UINT Msg,
-                                         WPARAM wParam,
-                                         LPARAM lParam)
+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;
+    ULONG_PTR Result = 0;
+    co_IntSendMessageWithCallBack(hWnd,
+                                  Msg,
+                                  wParam,
+                                  lParam,
+                                  NULL,
+                                  0,
+                                  &Result);
+    return Result;
 }
-
+/* MSDN:
+   If you send a message in the range below WM_USER to the asynchronous message
+   functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
+   message parameters cannot include pointers. Otherwise, the operation will fail.
+   The functions will return before the receiving thread has had a chance to
+   process the message and the sender will free the memory before it is used.
+*/
 LRESULT FASTCALL
 co_IntSendMessageWithCallBack( HWND hWnd,
-                               UINT Msg,
-                               WPARAM wParam,
-                               LPARAM lParam,
-                               SENDASYNCPROC CompletionCallback,
-                               ULONG_PTR CompletionCallbackContext,
-                               ULONG_PTR *uResult)
+                              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);
+    ULONG_PTR Result;
+    PWND 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);
+    }
 
-   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);
-   }
+    UserRefObjectCo(Window, &Ref);
 
-   Win32Thread = PsGetCurrentThreadWin32Thread();
+    if (Window->state & WNDS_DESTROYED)
+    {
+        /* FIXME - last error? */
+        DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd);
+        RETURN(FALSE);
+    }
 
-   IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
+    Win32Thread = PsGetCurrentThreadWin32Thread();
 
-   if (Win32Thread == NULL)
-   {
-     ASSERT(FALSE);
-     RETURN(FALSE);
-   }
+    if (Win32Thread == NULL)
+    {
+        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);
+    }
 
-   /* 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->head.pti->MessageQueue != Win32Thread->MessageQueue)))
+    {
+        DPRINT1("Failed to pack message parameters\n");
+        RETURN( FALSE);
+    }
 
-   if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, Window->pti->MessageQueue != Win32Thread->MessageQueue)))
-   {
-       DPRINT1("Failed to pack message parameters\n");
-       RETURN( FALSE);
-   }
+    /* If it can be sent now, then send it. */
+    if (Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
+    {
+        if (Win32Thread->TIF_flags & TIF_INCLEANUP)
+        {
+            UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE);
+            /* Never send messages to exiting threads */
+            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))
-   {
+        IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
 
-      Result = (ULONG_PTR)co_IntCallWindowProc( Window->Wnd->lpfnWndProc,
-                                               !Window->Wnd->Unicode,
-                                                hWnd,
-                                                Msg,
-                                                wParam,
-                                                lParamPacked,
-                                                lParamBufferSize );
-      if(uResult)
-      {
-         *uResult = Result;
-      }
-   }
+        ObReferenceObject(Win32Thread->pEThread);
+        Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc,
+                                                  !Window->Unicode,
+                                                  hWnd,
+                                                  Msg,
+                                                  wParam,
+                                                  lParamPacked,
+                                                  lParamBufferSize );
+        if(uResult)
+        {
+            *uResult = Result;
+        }
+        ObDereferenceObject(Win32Thread->pEThread);
 
-   IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
+        IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
 
-   if ((Window->pti->MessageQueue == Win32Thread->MessageQueue) && (CompletionCallback == NULL))
-   {
-      if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
-      {
-         DPRINT1("Failed to unpack message parameters\n");
-      }
-      RETURN(TRUE);
-   }
+        if (CompletionCallback)
+        {
+            co_IntCallSentMessageCallback(CompletionCallback,
+                                          hWnd,
+                                          Msg,
+                                          CompletionCallbackContext,
+                                          Result);
+        }
+    }
 
-   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 = NULL; //Win32Thread->MessageQueue;
 
-   IntReferenceMessageQueue(Window->pti->MessageQueue);
-   Message->CompletionCallback = CompletionCallback;
-   Message->CompletionCallbackContext = CompletionCallbackContext;
-   Message->HookMessage = MSQ_NORMAL | MSQ_SENTNOWAIT;
-   Message->HasPackedLParam = (lParamBufferSize > 0);
+    if (Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
+    {
+        if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
+        {
+            DPRINT1("Failed to unpack message parameters\n");
+        }
+        RETURN(TRUE);
+    }
 
-   InsertTailList(&Window->pti->MessageQueue->SentMessagesListHead, &Message->ListEntry);
-   IntDereferenceMessageQueue(Window->pti->MessageQueue);
+    if(!(Message = ExAllocatePoolWithTag(NonPagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG)))
+    {
+        DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
+        RETURN( FALSE);
+    }
 
-   RETURN(TRUE);
+    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;
+    Message->Msg.wParam = wParam;
+    Message->Msg.lParam = lParamPacked;
+    Message->CompletionEvent = NULL;
+    Message->Result = 0;
+    Message->lResult = 0;
+    Message->QS_Flags = 0;
+    Message->SenderQueue = NULL; // mjmartin, you are right! This is null.
+    Message->CallBackSenderQueue = Win32Thread->MessageQueue;
+    Message->DispatchingListEntry.Flink = NULL;
+    Message->CompletionCallback = CompletionCallback;
+    Message->CompletionCallbackContext = CompletionCallbackContext;
+    Message->HookMessage = MSQ_NORMAL;
+    Message->HasPackedLParam = (lParamBufferSize > 0);
+    Message->QS_Flags = QS_SENDMESSAGE;
+
+    InsertTailList(&Window->head.pti->MessageQueue->SentMessagesListHead, &Message->ListEntry);
+    MsqWakeQueue(Window->head.pti->MessageQueue, QS_SENDMESSAGE, TRUE);
+    IntDereferenceMessageQueue(Window->head.pti->MessageQueue);
+
+    RETURN(TRUE);
 
 CLEANUP:
-   if (Window) UserDerefObjectCo(Window);
-   END_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
-   messages! */
+another thread, otherwise it sends the message. It does not support broadcast
+messages! */
 LRESULT FASTCALL
 co_IntPostOrSendMessage( HWND hWnd,
                          UINT Msg,
                          WPARAM wParam,
                          LPARAM lParam )
 {
-   ULONG_PTR Result;
-   PTHREADINFO pti;
-   PWINDOW_OBJECT Window;
+    ULONG_PTR Result;
+    PTHREADINFO pti;
+    PWND Window;
 
-   if ( hWnd == HWND_BROADCAST )
-   {
-      return 0;
-   }
+    if ( hWnd == HWND_BROADCAST )
+    {
+        return 0;
+    }
 
-   if(!(Window = UserGetWindowObject(hWnd)))
-   {
-      return 0;
-   }
+    if(!(Window = UserGetWindowObject(hWnd)))
+    {
+        return 0;
+    }
 
-   pti = PsGetCurrentThreadWin32Thread();
+    pti = PsGetCurrentThreadWin32Thread();
 
-   if ( Window->pti->MessageQueue != pti->MessageQueue &&
-        FindMsgMemory(Msg) == 0 )
-   {
-      Result = UserPostMessage(hWnd, Msg, wParam, lParam);
-   }
-   else
-   {
-      if ( !co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result) )
-      {
-         Result = 0;
-      }
-   }
+    if ( Window->head.pti->MessageQueue != pti->MessageQueue &&
+         FindMsgMemory(Msg) == 0 )
+    {
+        Result = UserPostMessage(hWnd, Msg, wParam, lParam);
+    }
+    else
+    {
+        if ( !co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result) )
+        {
+            Result = 0;
+        }
+    }
 
-   return (LRESULT)Result;
+    return (LRESULT)Result;
 }
 
 LRESULT FASTCALL
@@ -1710,994 +1561,749 @@ co_IntDoSendMessage( HWND hWnd,
                      UINT Msg,
                      WPARAM wParam,
                      LPARAM lParam,
-                     PDOSENDMESSAGE dsm,
-                     PNTUSERSENDMESSAGEINFO UnsafeInfo )
+                     PDOSENDMESSAGE dsm)
 {
-   PTHREADINFO pti;
-   LRESULT Result = TRUE;
-   NTSTATUS Status;
-   PWINDOW_OBJECT Window = NULL;
-   NTUSERSENDMESSAGEINFO Info;
-   MSG UserModeMsg;
-   MSG KernelModeMsg;
-   PMSGMEMORY MsgMemoryEntry;
-
-   RtlZeroMemory(&Info, sizeof(NTUSERSENDMESSAGEINFO));
-
-   /* FIXME: Call hooks. */
-   if (HWND_BROADCAST != hWnd)
-   {
-      Window = UserGetWindowObject(hWnd);
-      if ( !Window || !Window->Wnd )
-      {
-         /* Tell usermode to not touch this one */
-         Info.HandledByKernel = TRUE;
-         MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
-         return 0;
-      }
-   }
-
-   /* Check for an exiting window. */
-   if (Window && Window->state & WINDOWSTATUS_DESTROYING)
-   {
-      DPRINT1("co_IntDoSendMessage Window Exiting!\n");
-   }
-
-   /* See if the current thread can handle the message */
-   pti = PsGetCurrentThreadWin32Thread();
+    PTHREADINFO pti;
+    LRESULT Result = TRUE;
+    NTSTATUS Status;
+    PWND Window = NULL;
+    MSG UserModeMsg;
+    MSG KernelModeMsg;
+    PMSGMEMORY MsgMemoryEntry;
+
+    if (HWND_BROADCAST != hWnd)
+    {
+        Window = UserGetWindowObject(hWnd);
+        if ( !Window )
+        {
+            return 0;
+        }
+    }
 
-   // This is checked in user mode!!!!!!!
-   if ( HWND_BROADCAST != hWnd &&
-        NULL != pti &&
-        Window->pti->MessageQueue == pti->MessageQueue &&
-       !ISITHOOKED(WH_CALLWNDPROC) &&
-       !ISITHOOKED(WH_CALLWNDPROCRET) &&
-        ( Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST ) )
-   {
-      /* Gather the information usermode needs to call the window proc directly */
-      Info.HandledByKernel = FALSE;
+    /* Check for an exiting window. */
+    if (Window && Window->state & WNDS_DESTROYED)
+    {
+        DPRINT1("co_IntDoSendMessage Window Exiting!\n");
+    }
 
-      Status = MmCopyFromCaller(&(Info.Ansi), &(UnsafeInfo->Ansi),
-                                sizeof(BOOL));
-      if (! NT_SUCCESS(Status))
-      {
-         Info.Ansi = ! Window->Wnd->Unicode;
-      }
+    /* See if the current thread can handle the message */
+    pti = PsGetCurrentThreadWin32Thread();
 
-      Info.Ansi = !Window->Wnd->Unicode;
-      Info.Proc = Window->Wnd->lpfnWndProc;
-   }
-   else
-   {
-      /* Must be handled by other thread */
-//      if (HWND_BROADCAST != hWnd)
-//      {
-//         UserDereferenceObject(Window);
-//      }
-      Info.HandledByKernel = TRUE;
-      UserModeMsg.hwnd = hWnd;
-      UserModeMsg.message = Msg;
-      UserModeMsg.wParam = wParam;
-      UserModeMsg.lParam = lParam;
-      MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
-
-      Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
-      if (! NT_SUCCESS(Status))
-      {
-         MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         return (dsm ? 0 : -1);
-      }
+    UserModeMsg.hwnd = hWnd;
+    UserModeMsg.message = Msg;
+    UserModeMsg.wParam = wParam;
+    UserModeMsg.lParam = lParam;
+    MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
 
-      if(!dsm)
-      {
-         Result = co_IntSendMessage( KernelModeMsg.hwnd,
-                                     KernelModeMsg.message,
-                                     KernelModeMsg.wParam,
-                                     KernelModeMsg.lParam );
-      }
-      else
-      {
-         Result = co_IntSendMessageTimeout( KernelModeMsg.hwnd,
-                                            KernelModeMsg.message,
-                                            KernelModeMsg.wParam,
-                                            KernelModeMsg.lParam,
-                                            dsm->uFlags,
-                                            dsm->uTimeout,
-                                           &dsm->Result );
-      }
+    Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
+    if (! NT_SUCCESS(Status))
+    {
+       EngSetLastError(ERROR_INVALID_PARAMETER);
+       return (dsm ? 0 : -1);
+    }
 
-      Status = CopyMsgToUserMem(&UserModeMsg, &KernelModeMsg);
-      if (! NT_SUCCESS(Status))
-      {
-         MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         return(dsm ? 0 : -1);
-      }
-   }
+    if (!dsm)
+    {
+       Result = co_IntSendMessage( KernelModeMsg.hwnd,
+                                   KernelModeMsg.message,
+                                   KernelModeMsg.wParam,
+                                   KernelModeMsg.lParam );
+    }
+    else
+    {
+       Result = co_IntSendMessageTimeout( KernelModeMsg.hwnd,
+                                          KernelModeMsg.message,
+                                          KernelModeMsg.wParam,
+                                          KernelModeMsg.lParam,
+                                          dsm->uFlags,
+                                          dsm->uTimeout,
+                                         &dsm->Result );
+    }
 
-   Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
-   if (! NT_SUCCESS(Status))
-   {
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-   }
+    Status = CopyMsgToUserMem(&UserModeMsg, &KernelModeMsg);
+    if (! NT_SUCCESS(Status))
+    {
+       EngSetLastError(ERROR_INVALID_PARAMETER);
+       return(dsm ? 0 : -1);
+    }
 
-   return (LRESULT)Result;
+    return (LRESULT)Result;
 }
 
-
 BOOL FASTCALL
 UserSendNotifyMessage( HWND hWnd,
                        UINT Msg,
                        WPARAM wParam,
                        LPARAM lParam )
 {
-   BOOL Result = TRUE;
-
-   if (FindMsgMemory(Msg) != 0)
-   {
-      SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
-      return FALSE;
-   }
+    BOOL Ret = TRUE;
 
-   // Basicly the same as IntPostOrSendMessage
-   if (hWnd == HWND_BROADCAST) //Handle Broadcast
-   {
-      HWND *List;
-      PWINDOW_OBJECT DesktopWindow;
-      ULONG i;
-
-      DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
-      List = IntWinListChildren(DesktopWindow);
-
-      if (List != NULL)
-      {
-         for (i = 0; List[i]; i++)
-         {
-            UserSendNotifyMessage(List[i], Msg, wParam, lParam);
-         }
-         ExFreePool(List);
-      }
-   }
-   else
-   {
-     ULONG_PTR PResult;
-     PTHREADINFO pti;
-     PWINDOW_OBJECT Window;
-     MSG Message;
+    if (is_pointer_message(Msg))
+    {
+        EngSetLastError(ERROR_MESSAGE_SYNC_ONLY );
+        return FALSE;
+    }
 
-      if ( !(Window = UserGetWindowObject(hWnd)) ) return FALSE;
+    // Basicly the same as IntPostOrSendMessage
+    if (hWnd == HWND_BROADCAST) //Handle Broadcast
+    {
+        HWND *List;
+        PWND DesktopWindow;
+        ULONG i;
 
-      pti = PsGetCurrentThreadWin32Thread();
+        DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+        List = IntWinListChildren(DesktopWindow);
 
-      if (Window->pti->MessageQueue != pti->MessageQueue)
-      { // Send message w/o waiting for it.
-         Result = UserPostMessage(hWnd, Msg, wParam, lParam);
-      }
-      else
-      { // Handle message and callback.
-         Message.hwnd = hWnd;
-         Message.message = Msg;
-         Message.wParam = wParam;
-         Message.lParam = lParam;
-
-         Result = co_IntSendMessageTimeoutSingle( hWnd,
-                                                  Msg,
-                                                  wParam,
-                                                  lParam,
-                                                  SMTO_NORMAL,
-                                                  0,
-                                                 &PResult );
-      }
-   }
-   return Result;
+        if (List != NULL)
+        {
+            UserSendNotifyMessage(DesktopWindow->head.h, Msg, wParam, lParam);
+            for (i = 0; List[i]; i++)
+            {
+                Ret = UserSendNotifyMessage(List[i], Msg, wParam, lParam);
+            }
+            ExFreePool(List);
+        }
+    }
+    else
+    {
+        ULONG_PTR lResult = 0;
+        Ret = co_IntSendMessageWithCallBack( hWnd,
+                                             Msg,
+                                             wParam,
+                                             lParam,
+                                             NULL,
+                                             0,
+                                            &lResult);
+    }
+    return Ret;
 }
 
 
 DWORD APIENTRY
-IntGetQueueStatus(BOOL ClearChanges)
+IntGetQueueStatus(DWORD Changes)
 {
-   PTHREADINFO pti;
-   PUSER_MESSAGE_QUEUE Queue;
-   DWORD Result;
-   DECLARE_RETURN(DWORD);
+    PTHREADINFO pti;
+    PUSER_MESSAGE_QUEUE Queue;
+    DWORD Result;
 
-   DPRINT("Enter IntGetQueueStatus\n");
+    pti = PsGetCurrentThreadWin32Thread();
+    Queue = pti->MessageQueue;
+// wine:
+    Changes &= (QS_ALLINPUT|QS_ALLPOSTMESSAGE|QS_SMRESULT);
 
-   pti = PsGetCurrentThreadWin32Thread();
-   Queue = pti->MessageQueue;
-
-   Result = MAKELONG(Queue->QueueBits, Queue->ChangedBits);
-   if (ClearChanges)
-   {
-      Queue->ChangedBits = 0;
-   }
+    /* High word, types of messages currently in the queue.
+       Low  word, types of messages that have been added to the queue and that
+                  are still in the queue
+     */
+    Result = MAKELONG(pti->pcti->fsChangeBits & Changes, pti->pcti->fsWakeBits & Changes);
 
-   RETURN(Result);
+    pti->pcti->fsChangeBits &= ~Changes;
 
-CLEANUP:
-   DPRINT("Leave IntGetQueueStatus, ret=%i\n",_ret_);
-   END_CLEANUP;
+    return Result;
 }
 
 BOOL APIENTRY
 IntInitMessagePumpHook()
 {
-   if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti)
-   {
-     ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook++;
-     return TRUE;
-   }
-   return FALSE;
+    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+
+    if (pti->pcti)
+    {
+        pti->pcti->dwcPumpHook++;
+        return TRUE;
+    }
+    return FALSE;
 }
 
 BOOL APIENTRY
 IntUninitMessagePumpHook()
 {
-   if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti)
-   {
-      if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook <= 0)
-      {
-         return FALSE;
-      }
-      ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook--;
-      return TRUE;
-   }
-   return FALSE;
+    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+
+    if (pti->pcti)
+    {
+        if (pti->pcti->dwcPumpHook <= 0)
+        {
+            return FALSE;
+        }
+        pti->pcti->dwcPumpHook--;
+        return TRUE;
+    }
+    return FALSE;
 }
 
 /** Functions ******************************************************************/
 
-BOOL APIENTRY
-NtUserPostMessage(HWND hWnd,
-                  UINT Msg,
-                  WPARAM wParam,
-                  LPARAM lParam)
+BOOL
+APIENTRY
+NtUserDragDetect(
+   HWND hWnd,
+   POINT pt) // Just like the User call.
 {
-   DECLARE_RETURN(BOOL);
+    MSG msg;
+    RECT rect;
+    WORD wDragWidth, wDragHeight;
+    DECLARE_RETURN(BOOL);
 
-   DPRINT("Enter NtUserPostMessage\n");
-   UserEnterExclusive();
+    DPRINT("Enter NtUserDragDetect(%x)\n", hWnd);
+    UserEnterExclusive();
 
-   RETURN( UserPostMessage(hWnd, Msg, wParam, lParam));
+    wDragWidth = UserGetSystemMetrics(SM_CXDRAG);
+    wDragHeight= UserGetSystemMetrics(SM_CYDRAG);
 
-CLEANUP:
-   DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
-}
+    rect.left = pt.x - wDragWidth;
+    rect.right = pt.x + wDragWidth;
 
-BOOL APIENTRY
-NtUserPostThreadMessage(DWORD idThread,
-                        UINT Msg,
-                        WPARAM wParam,
-                        LPARAM lParam)
-{
-   DECLARE_RETURN(BOOL);
+    rect.top = pt.y - wDragHeight;
+    rect.bottom = pt.y + wDragHeight;
 
-   DPRINT("Enter NtUserPostThreadMessage\n");
-   UserEnterExclusive();
+    co_UserSetCapture(hWnd);
 
-   RETURN( UserPostThreadMessage( idThread,
-                                  Msg,
-                                  wParam,
-                                  lParam));
+    for (;;)
+    {
+        while (co_IntGetPeekMessage( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE, FALSE ) ||
+               co_IntGetPeekMessage( &msg, 0, WM_QUEUESYNC,  WM_QUEUESYNC, PM_REMOVE, FALSE ) ||
+               co_IntGetPeekMessage( &msg, 0, WM_KEYFIRST,   WM_KEYLAST,   PM_REMOVE, FALSE ) )
+        {
+            if ( msg.message == WM_LBUTTONUP )
+            {
+                co_UserSetCapture(NULL);
+                RETURN( FALSE);
+            }
+            if ( msg.message == WM_MOUSEMOVE )
+            {
+                POINT tmp;
+                tmp.x = (short)LOWORD(msg.lParam);
+                tmp.y = (short)HIWORD(msg.lParam);
+                if( !IntPtInRect( &rect, tmp ) )
+                {
+                    co_UserSetCapture(NULL);
+                    RETURN( TRUE);
+                }
+            }
+            if ( msg.message == WM_KEYDOWN )
+            {
+                if ( msg.wParam == VK_ESCAPE )
+                {
+                   co_UserSetCapture(NULL);
+                   RETURN( TRUE);
+                }
+            }
+            if ( msg.message == WM_QUEUESYNC )
+            {
+                co_HOOK_CallHooks( WH_CBT, HCBT_QS, 0, 0 );
+            }
+        }
+        co_IntWaitMessage(NULL, 0, 0);
+    }
+    RETURN( FALSE);
 
 CLEANUP:
-   DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_);
+   DPRINT("Leave NtUserDragDetect, ret=%i\n",_ret_);
    UserLeave();
    END_CLEANUP;
 }
 
-DWORD APIENTRY
-NtUserQuerySendMessage(DWORD Unknown0)
-{
-   UNIMPLEMENTED;
-
-   return 0;
-}
-
-
-////////// API on the way out!
-LRESULT APIENTRY
-NtUserSendMessageTimeout( HWND hWnd,
-                          UINT Msg,
-                          WPARAM wParam,
-                          LPARAM lParam,
-                          UINT uFlags,
-                          UINT uTimeout,
-                          ULONG_PTR *uResult,
-                          PNTUSERSENDMESSAGEINFO UnsafeInfo )
+BOOL APIENTRY
+NtUserPostMessage(HWND hWnd,
+                  UINT Msg,
+                  WPARAM wParam,
+                  LPARAM lParam)
 {
-   DOSENDMESSAGE dsm;
-   LRESULT Result;
-   DECLARE_RETURN(BOOL);
+    BOOL ret;
 
-   DPRINT("Enter NtUserSendMessageTimeout\n");
-   UserEnterExclusive();
+    UserEnterExclusive();
 
-   dsm.uFlags = uFlags;
-   dsm.uTimeout = uTimeout;
-   Result = co_IntDoSendMessage(hWnd, Msg, wParam, lParam, &dsm, UnsafeInfo);
-   if(uResult != NULL && Result != 0)
-   {
-      NTSTATUS Status;
+    ret = UserPostMessage(hWnd, Msg, wParam, lParam);
 
-      Status = MmCopyToCaller(uResult, &dsm.Result, sizeof(ULONG_PTR));
-      if(!NT_SUCCESS(Status))
-      {
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         RETURN( FALSE);
-      }
-   }
-   RETURN( Result);
+    UserLeave();
 
-CLEANUP:
-   DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
+    return ret;
 }
 
-LRESULT APIENTRY
-NtUserSendMessage( HWND Wnd,
-                   UINT Msg,
-                   WPARAM wParam,
-                   LPARAM lParam,
-                   PNTUSERSENDMESSAGEINFO UnsafeInfo )
+BOOL APIENTRY
+NtUserPostThreadMessage(DWORD idThread,
+                        UINT Msg,
+                        WPARAM wParam,
+                        LPARAM lParam)
 {
-   DECLARE_RETURN(BOOL);
+    BOOL ret;
 
-   DPRINT("Enter NtUserSendMessage\n");
-   UserEnterExclusive();
+    UserEnterExclusive();
 
-   RETURN(co_IntDoSendMessage(Wnd, Msg, wParam, lParam, NULL, UnsafeInfo));
+    ret = UserPostThreadMessage( idThread, Msg, wParam, lParam);
 
-CLEANUP:
-   DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
+    UserLeave();
+
+    return ret;
 }
-//////////
 
 BOOL APIENTRY
 NtUserWaitMessage(VOID)
 {
-   DECLARE_RETURN(BOOL);
+    BOOL ret;
 
-   DPRINT("EnterNtUserWaitMessage\n");
-   UserEnterExclusive();
+    UserEnterExclusive();
+    DPRINT("NtUserWaitMessage Enter\n");
+    ret = co_IntWaitMessage(NULL, 0, 0);
+    DPRINT("NtUserWaitMessage Leave\n");
+    UserLeave();
 
-   RETURN(co_IntWaitMessage(NULL, 0, 0));
-
-CLEANUP:
-   DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
+    return ret;
 }
 
-
 BOOL APIENTRY
-NtUserGetMessage( PNTUSERGETMESSAGEINFO UnsafeInfo,
+NtUserGetMessage(PMSG pMsg,
                   HWND hWnd,
                   UINT MsgFilterMin,
                   UINT MsgFilterMax )
-/*
- * FUNCTION: Get a message from the calling thread's message queue.
- * ARGUMENTS:
- *      UnsafeMsg - Pointer to the structure which receives the returned message.
- *      Wnd - Window whose messages are to be retrieved.
- *      MsgFilterMin - Integer value of the lowest message value to be
- *                     retrieved.
- *      MsgFilterMax - Integer value of the highest message value to be
- *                     retrieved.
- */
 {
-   BOOL GotMessage;
-   NTUSERGETMESSAGEINFO Info;
-   NTSTATUS Status;
-   /* FIXME: if initialization is removed, gcc complains that this may be used before initialization. Please review */
-   PWINDOW_OBJECT Window = NULL;
-   PMSGMEMORY MsgMemoryEntry;
-   PVOID UserMem;
-   UINT Size;
-   USER_MESSAGE Msg;
-   DECLARE_RETURN(BOOL);
-//   USER_REFERENCE_ENTRY Ref;
-
-   DPRINT("Enter NtUserGetMessage\n");
-   UserEnterExclusive();
-
-   /* Validate input */
-   if (hWnd && !(Window = UserGetWindowObject(hWnd)))
-   {
-      RETURN(-1);
-   }
-
-//   if (Window) UserRefObjectCo(Window, &Ref);
-
-   if (MsgFilterMax < MsgFilterMin)
-   {
-      MsgFilterMin = 0;
-      MsgFilterMax = 0;
-   }
-
-   do
-   {
-      GotMessage = co_IntPeekMessage(&Msg, Window, MsgFilterMin, MsgFilterMax, PM_REMOVE);
-      if (GotMessage)
-      {
-         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);
-            RETURN( (BOOL) -1);
-         }
-      }
-      else if (! co_IntWaitMessage(Window, MsgFilterMin, MsgFilterMax))
-      {
-         RETURN( (BOOL) -1);
-      }
-   }
-   while (! GotMessage);
-
-   RETURN( WM_QUIT != Info.Msg.message);
-
-CLEANUP:
-//   if (Window) UserDerefObjectCo(Window);
-
-   DPRINT("Leave NtUserGetMessage\n");
-   UserLeave();
-   END_CLEANUP;
-}
+    MSG Msg;
+    BOOL Ret;
 
+    if ( (MsgFilterMin|MsgFilterMax) & ~WM_MAXIMUM )
+    {
+        EngSetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
 
-BOOL
-APIENTRY
-NtUserGetMessageX(
-   PMSG pMsg,
-   HWND hWnd,
-   UINT MsgFilterMin,
-   UINT MsgFilterMax)
-{
-   MSG Msg;
-   BOOL Ret = FALSE;
-   DECLARE_RETURN(BOOL);
+    UserEnterExclusive();
 
-   DPRINT("Enter NtUserGetMessage\n");
-   UserEnterExclusive();
+    RtlZeroMemory(&Msg, sizeof(MSG));
 
-   if ( (MsgFilterMin|MsgFilterMax) & ~WM_MAXIMUM )
-   {
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      RETURN( Ret);
-   }
+    Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE, TRUE);
 
-   RtlZeroMemory(&Msg, sizeof(MSG));
+    UserLeave();
 
-   Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE, TRUE);
+    if (Ret == TRUE)
+    {
+        _SEH2_TRY
+        {
+            ProbeForWrite(pMsg, sizeof(MSG), 1);
+            RtlCopyMemory(pMsg, &Msg, sizeof(MSG));
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            SetLastNtError(_SEH2_GetExceptionCode());
+            Ret = FALSE;
+        }
+        _SEH2_END;
+    }
 
-   if (Ret)
-   {
-      _SEH2_TRY
-      {
-         ProbeForWrite(pMsg, sizeof(MSG), 1);
-         RtlCopyMemory(pMsg, &Msg, sizeof(MSG));
-      }
-      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-      {
-         SetLastNtError(_SEH2_GetExceptionCode());
-         Ret = FALSE;
-      }
-      _SEH2_END;
-   }
-   RETURN( Ret);
+    if ((INT)Ret != -1)
+       Ret = Ret ? (WM_QUIT != pMsg->message) : FALSE;
 
-CLEANUP:
-   DPRINT("Leave NtUserGetMessage\n");
-   UserLeave();
-   END_CLEANUP;
+    return Ret;
 }
 
 BOOL APIENTRY
-NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
+NtUserPeekMessage( PMSG pMsg,
                   HWND hWnd,
                   UINT MsgFilterMin,
                   UINT MsgFilterMax,
                   UINT RemoveMsg)
 {
-   NTSTATUS Status;
-   BOOL Present;
-   NTUSERGETMESSAGEINFO Info;
-   PWINDOW_OBJECT Window;
-   PMSGMEMORY MsgMemoryEntry;
-   PVOID UserMem;
-   UINT Size;
-   USER_MESSAGE Msg;
-   DECLARE_RETURN(BOOL);
-
-   DPRINT("Enter NtUserPeekMessage\n");
-   UserEnterExclusive();
-
-   if (hWnd == (HWND)-1 || hWnd == (HWND)0x0000FFFF || hWnd == (HWND)0xFFFFFFFF)
-      hWnd = (HWND)1;
-
-   /* Validate input */
-   if (hWnd && hWnd != (HWND)1)
-   {
-      if (!(Window = UserGetWindowObject(hWnd)))
-      {
-         RETURN(-1);
-      }
-   }
-   else
-   {
-      Window = (PWINDOW_OBJECT)hWnd;
-   }
+    MSG Msg;
+    BOOL Ret;
 
-   if (MsgFilterMax < MsgFilterMin)
-   {
-      MsgFilterMin = 0;
-      MsgFilterMax = 0;
-   }
+    if ( RemoveMsg & PM_BADMSGFLAGS )
+    {
+        EngSetLastError(ERROR_INVALID_FLAGS);
+        return FALSE;
+    }
 
-   Present = co_IntPeekMessage(&Msg, Window, MsgFilterMin, MsgFilterMax, RemoveMsg);
-   if (Present)
-   {
+    UserEnterExclusive();
 
-      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_RELEASE);
-            SetLastNtError(Status);
-            RETURN( (BOOL) -1);
-         }
-         Info.Msg.lParam = (LPARAM) UserMem;
-      }
-      if (RemoveMsg && Msg.FreeLParam && 0 != Msg.Msg.lParam)
-      {
-         ExFreePool((void *) Msg.Msg.lParam);
-      }
-      Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO));
-      if (! NT_SUCCESS(Status))
-      {
-         SetLastNtError(Status);
-         RETURN( (BOOL) -1);
-      }
-   }
+    RtlZeroMemory(&Msg, sizeof(MSG));
 
-   RETURN( Present);
+    Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg, FALSE);
 
-CLEANUP:
-   DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
+    UserLeave();
+
+    if (Ret)
+    {
+        _SEH2_TRY
+        {
+            ProbeForWrite(pMsg, sizeof(MSG), 1);
+            RtlCopyMemory(pMsg, &Msg, sizeof(MSG));
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            SetLastNtError(_SEH2_GetExceptionCode());
+            Ret = FALSE;
+        }
+        _SEH2_END;
+    }
+
+    return Ret;
 }
 
-BOOL
-APIENTRY
-NtUserPeekMessageX(
-   PMSG pMsg,
-   HWND hWnd,
-   UINT MsgFilterMin,
-   UINT MsgFilterMax,
-   UINT RemoveMsg)
+BOOL APIENTRY
+NtUserCallMsgFilter( LPMSG lpmsg, INT code)
 {
-   MSG Msg;
-   BOOL Ret = FALSE;
-   DECLARE_RETURN(BOOL);
+    BOOL Ret = FALSE;
+    MSG Msg;
 
-   DPRINT("Enter NtUserPeekMessage\n");
-   UserEnterExclusive();
+    _SEH2_TRY
+    {
+        ProbeForRead(lpmsg, sizeof(MSG), 1);
+        RtlCopyMemory( &Msg, lpmsg, sizeof(MSG));
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        _SEH2_YIELD(return FALSE);
+    }
+    _SEH2_END;
 
-   if ( RemoveMsg & PM_BADMSGFLAGS )
-   {
-      SetLastWin32Error(ERROR_INVALID_FLAGS);
-      RETURN( Ret);
-   }
+    UserEnterExclusive();
 
-   RtlZeroMemory(&Msg, sizeof(MSG));
+    if ( co_HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)&Msg))
+    {
+        Ret = TRUE;
+    }
+    else
+    {
+        Ret = co_HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)&Msg);
+    }
 
-   Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg, FALSE);
+    UserLeave();
 
-   if (Ret)
-   {
-      _SEH2_TRY
-      {
-         ProbeForWrite(pMsg, sizeof(MSG), 1);
-         RtlCopyMemory(pMsg, &Msg, sizeof(MSG));
-      }
-      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-      {
-         SetLastNtError(_SEH2_GetExceptionCode());
-         Ret = FALSE;
-      }
-      _SEH2_END;
-   }
-   RETURN( Ret);
+    _SEH2_TRY
+    {
+        ProbeForWrite(lpmsg, sizeof(MSG), 1);
+        RtlCopyMemory(lpmsg, &Msg, sizeof(MSG));
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Ret = FALSE;
+    }
+    _SEH2_END;
 
-CLEANUP:
-   DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
+    return Ret;
 }
 
-BOOL
-APIENTRY
-NtUserCallMsgFilter(
-   LPMSG lpmsg,
-   INT code)
+LRESULT APIENTRY
+NtUserDispatchMessage(PMSG UnsafeMsgInfo)
 {
-   BOOL BadChk = FALSE, Ret = FALSE;
-   MSG Msg;
-   DECLARE_RETURN(BOOL);
-
-   DPRINT("Enter NtUserCallMsgFilter\n");
-   UserEnterExclusive();
-   if (lpmsg)
-   {
-      _SEH2_TRY
-      {
-         ProbeForRead((PVOID)lpmsg,
-                       sizeof(MSG),
-                                1);
-         RtlCopyMemory( &Msg,
-                (PVOID)lpmsg,
-                 sizeof(MSG));
-      }
-      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-      {
-         BadChk = TRUE;
-      }
-      _SEH2_END;
-   }
-   else
-     RETURN( FALSE);
+    LRESULT Res = 0;
+    MSG SafeMsg;
 
-   if (BadChk) RETURN( FALSE);
-
-   if ( ISITHOOKED(WH_SYSMSGFILTER) &&
-        co_HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)&Msg))
-   {
-      Ret = TRUE;
-   }
-   else
-   {
-      if ( ISITHOOKED(WH_MSGFILTER) )
-      {
-         Ret = co_HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)&Msg);
-      }
-   }
+    _SEH2_TRY
+    {
+        ProbeForRead(UnsafeMsgInfo, sizeof(MSG), 1);
+        RtlCopyMemory(&SafeMsg, UnsafeMsgInfo, sizeof(MSG));
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        SetLastNtError(_SEH2_GetExceptionCode());
+        _SEH2_YIELD(return FALSE);
+    }
+    _SEH2_END;
 
-   _SEH2_TRY
-   {
-      ProbeForWrite((PVOID)lpmsg,
-                     sizeof(MSG),
-                               1);
-      RtlCopyMemory((PVOID)lpmsg,
-                            &Msg,
-                     sizeof(MSG));
-   }
-   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-   {
-      BadChk = TRUE;
-   }
-   _SEH2_END;
-   if (BadChk) RETURN( FALSE);
-   RETURN( Ret)
+    UserEnterExclusive();
 
-CLEANUP:
-   DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_);
-   UserLeave();
-   END_CLEANUP;
-}
+    Res = IntDispatchMessage(&SafeMsg);
 
-LRESULT APIENTRY
-NtUserDispatchMessage(PMSG UnsafeMsgInfo)
-{
-  LRESULT Res = 0;
-  BOOL Hit = FALSE;
-  MSG SafeMsg;
-
-  UserEnterExclusive();  
-  _SEH2_TRY
-  {
-    ProbeForRead(UnsafeMsgInfo, sizeof(MSG), 1);
-    RtlCopyMemory(&SafeMsg, UnsafeMsgInfo, sizeof(MSG));
-  }
-  _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-  {
-    SetLastNtError(_SEH2_GetExceptionCode());
-    Hit = TRUE;
-  }
-  _SEH2_END;
-  
-  if (!Hit) Res = IntDispatchMessage(&SafeMsg);
-
-  UserLeave();
-  return Res;
+    UserLeave();
+    return Res;
 }
 
 
 BOOL APIENTRY
-NtUserTranslateMessage(LPMSG lpMsg,
-                       UINT flags)
+NtUserTranslateMessage(LPMSG lpMsg, UINT flags)
 {
-   NTSTATUS Status;
-   MSG SafeMsg;
-   DECLARE_RETURN(BOOL);
+    MSG SafeMsg;
+    BOOL Ret;
 
-   DPRINT("Enter NtUserTranslateMessage\n");
-   UserEnterExclusive();
+    _SEH2_TRY
+    {
+        ProbeForRead(lpMsg, sizeof(MSG), 1);
+        RtlCopyMemory(&SafeMsg, lpMsg, sizeof(MSG));
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        SetLastNtError(_SEH2_GetExceptionCode());
+        _SEH2_YIELD(return FALSE);
+    }
+    _SEH2_END;
 
-   Status = MmCopyFromCaller(&SafeMsg, lpMsg, sizeof(MSG));
-   if(!NT_SUCCESS(Status))
-   {
-      SetLastNtError(Status);
-      RETURN( FALSE);
-   }
+    UserEnterExclusive();
 
-   RETURN( IntTranslateKbdMessage(&SafeMsg, flags));
+    Ret = IntTranslateKbdMessage(&SafeMsg, flags);
 
-CLEANUP:
-   DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
+    UserLeave();
+
+    return Ret;
 }
 
 BOOL APIENTRY
-NtUserMessageCall(
-   HWND hWnd,
-   UINT Msg,
-   WPARAM wParam,
-   LPARAM lParam,
-   ULONG_PTR ResultInfo,
-   DWORD dwType, // fnID?
-   BOOL Ansi)
+NtUserMessageCall( HWND hWnd,
+                   UINT Msg,
+                   WPARAM wParam,
+                   LPARAM lParam,
+                   ULONG_PTR ResultInfo,
+                   DWORD dwType, // fnID?
+                   BOOL Ansi)
 {
-   LRESULT lResult = 0;
-   BOOL Ret = FALSE;
-   BOOL BadChk = FALSE;
-   PWINDOW_OBJECT Window = NULL;
-   USER_REFERENCE_ENTRY Ref;
+    LRESULT lResult = 0;
+    BOOL Ret = FALSE;
+    PWND Window = NULL;
+    USER_REFERENCE_ENTRY Ref;
 
-   UserEnterExclusive();
+    UserEnterExclusive();
 
-   /* Validate input */
-   if (hWnd && (hWnd != INVALID_HANDLE_VALUE) && !(Window = UserGetWindowObject(hWnd)))
-   {
-      UserLeave();
-      return FALSE;
-   }
-   switch(dwType)
-   {
-      case FNID_DEFWINDOWPROC:
-         UserRefObjectCo(Window, &Ref);
-         lResult = IntDefWindowProc(Window, Msg, wParam, lParam, Ansi);
-         Ret = TRUE;
-         UserDerefObjectCo(Window);
-      break;
-      case FNID_SENDNOTIFYMESSAGE:
-         Ret = UserSendNotifyMessage(hWnd, Msg, wParam, lParam);
-      break;
-      case FNID_BROADCASTSYSTEMMESSAGE:
-      {
-         BROADCASTPARM parm;
-         DWORD_PTR RetVal = 0;
+    switch(dwType)
+    {
+    case FNID_DEFWINDOWPROC:
+        /* Validate input */
+        if (hWnd && (hWnd != INVALID_HANDLE_VALUE))
+        {
+           Window = UserGetWindowObject(hWnd);
+           if (!Window)
+           {
+               UserLeave();
+               return FALSE;
+           }
+        }
+        UserRefObjectCo(Window, &Ref);
+        lResult = IntDefWindowProc(Window, Msg, wParam, lParam, Ansi);
+        Ret = TRUE;
+        UserDerefObjectCo(Window);
+        break;
+    case FNID_SENDNOTIFYMESSAGE:
+        Ret = UserSendNotifyMessage(hWnd, Msg, wParam, lParam);
+        break;
+    case FNID_BROADCASTSYSTEMMESSAGE:
+        {
+            BROADCASTPARM parm;
+            DWORD_PTR RetVal = 0;
+
+            if (ResultInfo)
+            {
+                _SEH2_TRY
+                {
+                    ProbeForWrite((PVOID)ResultInfo, sizeof(BROADCASTPARM), 1);
+                    RtlCopyMemory(&parm, (PVOID)ResultInfo, sizeof(BROADCASTPARM));
+                }
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                {
+                    _SEH2_YIELD(break);
+                }
+                _SEH2_END;
+            }
+            else
+                break;
+
+            if ( parm.recipients & BSM_ALLDESKTOPS ||
+                    parm.recipients == BSM_ALLCOMPONENTS )
+            {
+            }
+            else if (parm.recipients & BSM_APPLICATIONS)
+            {
+                if (parm.flags & BSF_QUERY)
+                {
+                    if (parm.flags & BSF_FORCEIFHUNG || parm.flags & BSF_NOHANG)
+                    {
+                        co_IntSendMessageTimeout( HWND_BROADCAST,
+                                                  Msg,
+                                                  wParam,
+                                                  lParam,
+                                                  SMTO_ABORTIFHUNG,
+                                                  2000,
+                                                 &RetVal);
+                    }
+                    else if (parm.flags & BSF_NOTIMEOUTIFNOTHUNG)
+                    {
+                        co_IntSendMessageTimeout( HWND_BROADCAST,
+                                                  Msg,
+                                                  wParam,
+                                                  lParam,
+                                                  SMTO_NOTIMEOUTIFNOTHUNG,
+                                                  2000,
+                                                 &RetVal);
+                    }
+                    else
+                    {
+                        co_IntSendMessageTimeout( HWND_BROADCAST,
+                                                  Msg,
+                                                 wParam,
+                                                  lParam,
+                                                  SMTO_NORMAL,
+                                                  2000,
+                                                 &RetVal);
+                    }
+                    Ret = RetVal;
+                }
+                else if (parm.flags & BSF_POSTMESSAGE)
+                {
+                    Ret = UserPostMessage(HWND_BROADCAST, Msg, wParam, lParam);
+                }
+                else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
+                {
+                    Ret = UserSendNotifyMessage(HWND_BROADCAST, Msg, wParam, lParam);
+                }
+            }
+        }
+        break;
+    case FNID_SENDMESSAGECALLBACK:
+        {
+            CALL_BACK_INFO CallBackInfo;
+            ULONG_PTR uResult;
 
-         if (ResultInfo)
-         {
             _SEH2_TRY
             {
-               ProbeForWrite((PVOID)ResultInfo,
-                         sizeof(BROADCASTPARM),
-                                             1);
-               RtlCopyMemory(&parm, (PVOID)ResultInfo, sizeof(BROADCASTPARM));
+                ProbeForRead((PVOID)ResultInfo, sizeof(CALL_BACK_INFO), 1);
+                RtlCopyMemory(&CallBackInfo, (PVOID)ResultInfo, sizeof(CALL_BACK_INFO));
             }
             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
-               BadChk = TRUE;
+                _SEH2_YIELD(break);
             }
             _SEH2_END;
-            if (BadChk) break;
-         }
-         else
-           break;
 
-         if ( parm.recipients & BSM_ALLDESKTOPS ||
-              parm.recipients == BSM_ALLCOMPONENTS )
-         {
-         }
-         else if (parm.recipients & BSM_APPLICATIONS)
-         {
-            if (parm.flags & BSF_QUERY)
+            if (is_pointer_message(Msg))
             {
-               if (parm.flags & BSF_FORCEIFHUNG || parm.flags & BSF_NOHANG)
-               {
-                  co_IntSendMessageTimeout( HWND_BROADCAST,
-                                            Msg,
-                                            wParam,
-                                            lParam,
-                                            SMTO_ABORTIFHUNG,
-                                            2000,
-                                            &RetVal);
-               }
-               else if (parm.flags & BSF_NOTIMEOUTIFNOTHUNG)
-               {
-                  co_IntSendMessageTimeout( HWND_BROADCAST,
-                                            Msg,
-                                            wParam,
-                                            lParam,
-                                            SMTO_NOTIMEOUTIFNOTHUNG,
-                                            2000,
-                                            &RetVal);
-               }
-               else
-               {
-                  co_IntSendMessageTimeout( HWND_BROADCAST,
-                                            Msg,
-                                            wParam,
-                                            lParam,
-                                            SMTO_NORMAL,
-                                            2000,
-                                            &RetVal);
-               }
+               EngSetLastError(ERROR_MESSAGE_SYNC_ONLY );
+               break;
             }
-            else if (parm.flags & BSF_POSTMESSAGE)
+
+            if (!(Ret = co_IntSendMessageWithCallBack(hWnd, Msg, wParam, lParam,
+                        CallBackInfo.CallBack, CallBackInfo.Context, &uResult)))
             {
-               Ret = UserPostMessage(HWND_BROADCAST, Msg, wParam, lParam);
+                DPRINT1("Callback failure!\n");
             }
-            else if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
+        }
+        break;
+    case FNID_SENDMESSAGE:
+        {
+            Ret = co_IntDoSendMessage(hWnd, Msg, wParam, lParam, 0);
+
+            if (ResultInfo)
             {
-               Ret = UserSendNotifyMessage(HWND_BROADCAST, Msg, wParam, lParam);
+                _SEH2_TRY
+                {
+                    ProbeForWrite((PVOID)ResultInfo, sizeof(ULONG_PTR), 1);
+                    RtlCopyMemory((PVOID)ResultInfo, &Ret, sizeof(ULONG_PTR));
+                }
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                {
+                    Ret = FALSE;
+                    _SEH2_YIELD(break);
+                }
+                _SEH2_END;
+            }
+            break;
+        }
+    case FNID_SENDMESSAGETIMEOUT:
+        {
+            DOSENDMESSAGE dsm, *pdsm = (PDOSENDMESSAGE)ResultInfo;
+            if (ResultInfo)
+            {
+                _SEH2_TRY
+                {
+                    ProbeForRead(pdsm, sizeof(DOSENDMESSAGE), 1);
+                    RtlCopyMemory(&dsm, pdsm, sizeof(DOSENDMESSAGE));
+                }
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                {
+                    _SEH2_YIELD(break);
+                }
+                _SEH2_END;
             }
-         }
-      }
-      break;
-      case FNID_SENDMESSAGECALLBACK:
-      {
-         PCALL_BACK_INFO CallBackInfo = (PCALL_BACK_INFO)ResultInfo;
 
-         if (!CallBackInfo)
+            Ret = co_IntDoSendMessage( hWnd, Msg, wParam, lParam, &dsm );
+
+            if (pdsm)
+            {
+                _SEH2_TRY
+                {
+                    ProbeForWrite(pdsm, sizeof(DOSENDMESSAGE), 1);
+                    RtlCopyMemory(pdsm, &dsm, sizeof(DOSENDMESSAGE));
+                }
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                {
+                    Ret = FALSE;
+                    _SEH2_YIELD(break);
+                }
+                _SEH2_END;
+            }
             break;
+        }
+        // CallNextHook bypass.
+    case FNID_CALLWNDPROC:
+    case FNID_CALLWNDPROCRET:
+        {
+            PTHREADINFO pti;
+            PCLIENTINFO ClientInfo;
+            PHOOK NextObj, Hook;
 
-         if (!co_IntSendMessageWithCallBack(hWnd, Msg, wParam, lParam,
-             CallBackInfo->CallBack, CallBackInfo->Context, NULL))
-         {
-            DPRINT1("Callback failure!\n");
-         }
-      }
-      break;
-      // CallNextHook bypass.
-      case FNID_CALLWNDPROC:
-      case FNID_CALLWNDPROCRET:
-      {
-         PCLIENTINFO ClientInfo = GetWin32ClientInfo();
-         PHOOK NextObj, Hook = ClientInfo->phkCurrent;
+            pti = GetW32ThreadInfo();
 
-         if (!ClientInfo || !Hook) break;
+            Hook = pti->sphkCurrent;
 
-         UserReferenceObject(Hook);
+            if (!Hook) break;
 
-         if (Hook->Thread && (Hook->Thread != PsGetCurrentThread()))
-         {
-            UserDereferenceObject(Hook);
-            break;
-         }
+            NextObj = Hook->phkNext;
+            ClientInfo = pti->pClientInfo;
+            _SEH2_TRY
+            {
+                ClientInfo->phkCurrent = NextObj;
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                ClientInfo = NULL;
+            }
+            _SEH2_END;
 
-         NextObj = IntGetNextHook(Hook);
-         ClientInfo->phkCurrent = NextObj;
+            if (!ClientInfo || !NextObj) break;
 
-         if ( Hook->HookId == WH_CALLWNDPROC)
-         {
-            CWPSTRUCT CWP;
-            CWP.hwnd    = hWnd;
-            CWP.message = Msg;
-            CWP.wParam  = wParam;
-            CWP.lParam  = lParam;
-            DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook, NextObj );
-
-            lResult = co_IntCallHookProc( Hook->HookId,
-                                          HC_ACTION,
-                                        ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
-                                         (LPARAM)&CWP,
-                                          Hook->Proc,
-                                          Hook->Ansi,
-                                          &Hook->ModuleName);
-         }
-         else
-         {
-            CWPRETSTRUCT CWPR;
-            CWPR.hwnd    = hWnd;
-            CWPR.message = Msg;
-            CWPR.wParam  = wParam;
-            CWPR.lParam  = lParam;
-            CWPR.lResult = ClientInfo->dwHookData;
-
-            lResult = co_IntCallHookProc( Hook->HookId,
-                                          HC_ACTION,
-                                        ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
-                                         (LPARAM)&CWPR,
-                                          Hook->Proc,
-                                          Hook->Ansi,
-                                          &Hook->ModuleName);
-         }
-         UserDereferenceObject(Hook);
-         lResult = (LRESULT) NextObj;
-      }
-      break;
-   }
+            NextObj->phkNext = IntGetNextHook(NextObj);
 
-   switch(dwType)
-   {
-      case FNID_DEFWINDOWPROC:
-      case FNID_CALLWNDPROC:
-      case FNID_CALLWNDPROCRET:
-         if (ResultInfo)
-         {
+            if ( Hook->HookId == WH_CALLWNDPROC)
+            {
+                CWPSTRUCT CWP;
+                CWP.hwnd    = hWnd;
+                CWP.message = Msg;
+                CWP.wParam  = wParam;
+                CWP.lParam  = lParam;
+                DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook, NextObj );
+
+                lResult = co_IntCallHookProc( Hook->HookId,
+                                              HC_ACTION,
+                                              ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
+                                              (LPARAM)&CWP,
+                                              Hook->Proc,
+                                              Hook->Ansi,
+                                              &Hook->ModuleName);
+            }
+            else
+            {
+                CWPRETSTRUCT CWPR;
+                CWPR.hwnd    = hWnd;
+                CWPR.message = Msg;
+                CWPR.wParam  = wParam;
+                CWPR.lParam  = lParam;
+                CWPR.lResult = ClientInfo->dwHookData;
+
+                lResult = co_IntCallHookProc( Hook->HookId,
+                                              HC_ACTION,
+                                              ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
+                                              (LPARAM)&CWPR,
+                                              Hook->Proc,
+                                              Hook->Ansi,
+                                              &Hook->ModuleName);
+            }
+        }
+        break;
+    }
+
+    switch(dwType)
+    {
+    case FNID_DEFWINDOWPROC:
+    case FNID_CALLWNDPROC:
+    case FNID_CALLWNDPROCRET:
+        if (ResultInfo)
+        {
             _SEH2_TRY
             {
                 ProbeForWrite((PVOID)ResultInfo, sizeof(LRESULT), 1);
@@ -2705,18 +2311,18 @@ NtUserMessageCall(
             }
             _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
             {
-                BadChk = TRUE;
+                Ret = FALSE;
             }
-            _SEH2_END;      
-         }
-         break;
-      default:
-         break;   
-   }
+            _SEH2_END;
+        }
+        break;
+    default:
+        break;
+    }
 
-   UserLeave();
+    UserLeave();
 
-   return BadChk ? FALSE : Ret;
+    return Ret;
 }
 
 #define INFINITE 0xFFFFFFFF
@@ -2724,127 +2330,126 @@ NtUserMessageCall(
 
 DWORD
 APIENTRY
-NtUserWaitForInputIdle(
-   IN HANDLE hProcess,
-   IN DWORD dwMilliseconds,
-   IN BOOL Unknown2)
+NtUserWaitForInputIdle( IN HANDLE hProcess,
+                        IN DWORD dwMilliseconds,
+                        IN BOOL Unknown2)
 {
-  PEPROCESS Process;
-  PPROCESSINFO W32Process;
-  NTSTATUS Status;
-  HANDLE Handles[2];
-  LARGE_INTEGER Timeout;
-  ULONGLONG StartTime, Run, Elapsed = 0;
-
-  UserEnterExclusive();
-
-  Status = ObReferenceObjectByHandle(hProcess,
-                                     PROCESS_QUERY_INFORMATION,
-                                     PsProcessType,
-                                     UserMode,
-                                     (PVOID*)&Process,
-                                     NULL);
-
-  if (!NT_SUCCESS(Status))
-  {
-     UserLeave();
-     SetLastNtError(Status);
-     return WAIT_FAILED;
-  }
-
-  W32Process = (PPROCESSINFO)Process->Win32Process;
-  if (!W32Process)
-  {
-      ObDereferenceObject(Process);
-      UserLeave();
-      SetLastWin32Error(ERROR_INVALID_PARAMETER);
-      return WAIT_FAILED;
-  }
-
-  EngCreateEvent((PEVENT *)&W32Process->InputIdleEvent);
-
-  Handles[0] = Process;
-  Handles[1] = W32Process->InputIdleEvent;
-
-  if (!Handles[1])
-  {
-      ObDereferenceObject(Process);
-      UserLeave();
-      return STATUS_SUCCESS;  /* no event to wait on */
-  }
-
-  StartTime = EngGetTickCount();
-
-  Run = dwMilliseconds;
-
-  DPRINT("WFII: waiting for %p\n", Handles[1] );
-  do
-  {
-     Timeout.QuadPart = Run - Elapsed;
-     UserLeave();
-     Status = KeWaitForMultipleObjects( 2,
-                                        Handles,
-                                        WaitAny,
-                                        UserRequest,
-                                        UserMode,
-                                        FALSE,
-                             dwMilliseconds == INFINITE ? NULL : &Timeout,
-                                        NULL);
-     UserEnterExclusive();
-
-     if (!NT_SUCCESS(Status))
-     {
+    PEPROCESS Process;
+    PPROCESSINFO W32Process;
+    PTHREADINFO pti;
+    NTSTATUS Status;
+    HANDLE Handles[3];
+    LARGE_INTEGER Timeout;
+
+    UserEnterExclusive();
+
+    Status = ObReferenceObjectByHandle(hProcess,
+                                       PROCESS_QUERY_INFORMATION,
+                                       PsProcessType,
+                                       UserMode,
+                                       (PVOID*)&Process,
+                                       NULL);
+
+    if (!NT_SUCCESS(Status))
+    {
+        UserLeave();
         SetLastNtError(Status);
-        Status = WAIT_FAILED;
-        goto WaitExit;
-     }
+        return WAIT_FAILED;
+    }
 
-     switch (Status)
-     {
-        case STATUS_WAIT_0:
-           Status = WAIT_FAILED;
-           goto WaitExit;
+    pti = PsGetCurrentThreadWin32Thread();
 
-        case STATUS_WAIT_2:
+    W32Process = (PPROCESSINFO)Process->Win32Process;
+
+    if ( PsGetProcessExitProcessCalled(Process) ||
+         !W32Process ||
+         pti->ppi == W32Process)
+    {
+        ObDereferenceObject(Process);
+        UserLeave();
+        EngSetLastError(ERROR_INVALID_PARAMETER);
+        return WAIT_FAILED;
+    }
+
+    Handles[0] = Process;
+    Handles[1] = W32Process->InputIdleEvent;
+    Handles[2] = pti->MessageQueue->NewMessages; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
+
+    if (!Handles[1])
+    {
+        ObDereferenceObject(Process);
+        UserLeave();
+        return STATUS_SUCCESS;  /* no event to wait on */
+    }
+
+    if (dwMilliseconds != INFINITE)
+       Timeout.QuadPart = (LONGLONG) dwMilliseconds * (LONGLONG) -10000;
+
+    W32Process->W32PF_flags |= W32PF_WAITFORINPUTIDLE;
+    for (pti = W32Process->ptiList; pti; pti = pti->ptiSibling)
+    {
+       pti->TIF_flags |= TIF_WAITFORINPUTIDLE;
+       pti->pClientInfo->dwTIFlags = pti->TIF_flags;
+    }
+
+    DPRINT("WFII: ppi 0x%x\n",W32Process);
+    DPRINT("WFII: waiting for %p\n", Handles[1] );
+    do
+    {
+        UserLeave();
+        Status = KeWaitForMultipleObjects( 3,
+                                           Handles,
+                                           WaitAny,
+                                           UserRequest,
+                                           UserMode,
+                                           FALSE,
+                                           dwMilliseconds == INFINITE ? NULL : &Timeout,
+                                           NULL);
+        UserEnterExclusive();
+
+        if (!NT_SUCCESS(Status))
         {
-           USER_MESSAGE Msg;
-           co_IntPeekMessage( &Msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE );
-           break;
+            SetLastNtError(Status);
+            Status = WAIT_FAILED;
+            goto WaitExit;
         }
 
-        case STATUS_USER_APC:
-        case STATUS_ALERTED:
-        case STATUS_TIMEOUT:
-           DPRINT1("WFII: timeout\n");
-           Status = STATUS_TIMEOUT;
-           goto WaitExit;
+        switch (Status)
+        {
+        case STATUS_WAIT_0:
+            goto WaitExit;
 
-        default:
-           DPRINT1("WFII: finished\n");
-           Status = STATUS_SUCCESS;
-           goto WaitExit;
-     }
+        case STATUS_WAIT_2:
+            {
+               MSG Msg;
+               co_IntGetPeekMessage( &Msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE, FALSE);
+               DPRINT1("WFII: WAIT 2\n");
+            }
+            break;
 
-     if (dwMilliseconds != INFINITE)
-     {
-        Elapsed = EngGetTickCount() - StartTime;
+        case STATUS_TIMEOUT:
+            DPRINT1("WFII: timeout\n");
+        case WAIT_FAILED:
+            goto WaitExit;
 
-        if (Elapsed > Run)
-           Status = STATUS_TIMEOUT;
-           break;
-     }
-  }
-  while (1);
+        default:
+            DPRINT1("WFII: finished\n");
+            Status = STATUS_SUCCESS;
+            goto WaitExit;
+        }
+    }
+    while (TRUE);
 
 WaitExit:
-  if (W32Process->InputIdleEvent)
-  {
-     EngFreeMem((PVOID)W32Process->InputIdleEvent);
-     W32Process->InputIdleEvent = NULL;
-  }
-  ObDereferenceObject(Process);
-  UserLeave();
-  return Status;
+    for (pti = W32Process->ptiList; pti; pti = pti->ptiSibling)
+    {
+       pti->TIF_flags &= ~TIF_WAITFORINPUTIDLE;
+       pti->pClientInfo->dwTIFlags = pti->TIF_flags;
+    }
+    W32Process->W32PF_flags &= ~W32PF_WAITFORINPUTIDLE;
+    ObDereferenceObject(Process);
+    UserLeave();
+    return Status;
 }
 
 /* EOF */