[Win32k]
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / message.c
index fb798ed..9d5b72b 100644 (file)
@@ -16,6 +16,7 @@
 #include <debug.h>
 
 BOOLEAN NTAPI PsGetProcessExitProcessCalled(PEPROCESS Process);
+HWND FASTCALL co_UserSetCapture(HWND hWnd);
 
 #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
 
@@ -33,6 +34,81 @@ IntCleanupMessageImpl(VOID)
     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
 #define MMS_SIZE_WPARAMWCHAR -2
 #define MMS_SIZE_LPARAMSZ    -3
@@ -61,6 +137,7 @@ static MSGMEMORY MsgMemory[] =
     { 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 },
 };
@@ -134,10 +211,6 @@ MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam)
                 Size = sizeof(COPYDATASTRUCT) + ((PCOPYDATASTRUCT)lParam)->cbData;
                 break;
 
-            case WM_COPYGLOBALDATA:
-                Size = wParam;
-                break;
-
             default:
                 ASSERT(FALSE);
                 Size = 0;
@@ -243,7 +316,6 @@ PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Non
         ASSERT(CsData == (PCHAR) PackedCs + Size);
         *lParamPacked = (LPARAM) PackedCs;
     }
-
     else if (PoolType == NonPagedPool)
     {
         PMSGMEMORY MsgMemoryEntry;
@@ -317,6 +389,100 @@ UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL No
     return STATUS_INVALID_PARAMETER;
 }
 
+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;
+}
+
+static NTSTATUS FASTCALL
+CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
+{
+    NTSTATUS Status;
+    PMSGMEMORY MsgMemoryEntry;
+    UINT Size;
+
+    /* See if this message type is present in the table */
+    MsgMemoryEntry = FindMsgMemory(UserModeMsg->message);
+    if (NULL == MsgMemoryEntry)
+    {
+        /* Not present, no copying needed */
+        return STATUS_SUCCESS;
+    }
+
+    /* Determine required size */
+    Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
+
+    if (0 != Size)
+    {
+        /* Copy data if required */
+        if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_WRITE))
+        {
+            Status = MmCopyToCaller((PVOID) UserModeMsg->lParam, (PVOID) KernelModeMsg->lParam, Size);
+            if (! NT_SUCCESS(Status))
+            {
+                DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
+                ExFreePool((PVOID) KernelModeMsg->lParam);
+                return Status;
+            }
+        }
+
+        ExFreePool((PVOID) KernelModeMsg->lParam);
+    }
+
+    return STATUS_SUCCESS;
+}
+
 //
 // Wakeup any thread/process waiting on idle input.
 //
@@ -331,10 +497,10 @@ IdlePing(VOID)
 
    if (ForegroundQueue)
       ptiForeground = ForegroundQueue->Thread->Tcb.Win32Thread;
-     
+
    pti = PsGetCurrentThreadWin32Thread();
 
-   if ( pti ) 
+   if ( pti )
    {
       pti->pClientInfo->cSpins = 0; // Reset spins.
 
@@ -426,10 +592,7 @@ IntDispatchMessage(PMSG pMsg)
     LARGE_INTEGER TickCount;
     LONG Time;
     LRESULT retval = 0;
-    PMSGMEMORY MsgMemoryEntry;
-    INT lParamBufferSize;
     PTHREADINFO pti;
-    LPARAM lParamPacked;
     PWND Window = NULL;
 
     if (pMsg->hwnd)
@@ -442,7 +605,7 @@ IntDispatchMessage(PMSG pMsg)
 
     if ( Window->head.pti != pti)
     {
-       SetLastWin32Error( ERROR_MESSAGE_SYNC_ONLY );
+       EngSetLastError( ERROR_MESSAGE_SYNC_ONLY );
        return 0;
     }
 
@@ -452,7 +615,6 @@ IntDispatchMessage(PMSG pMsg)
     {
         if (pMsg->message == WM_TIMER)
         {
-            ObReferenceObject(pti->pEThread);
             if (ValidateTimerCallback(pti,pMsg->lParam))
             {
                 KeQueryTickCount(&TickCount);
@@ -463,10 +625,9 @@ IntDispatchMessage(PMSG pMsg)
                                               WM_TIMER,
                                               pMsg->wParam,
                                               (LPARAM)Time,
-                                              sizeof(LPARAM));
+                                              0);
             }
-            ObDereferenceObject(pti->pEThread);
-            return retval;        
+            return retval;
         }
         else
         {
@@ -483,35 +644,17 @@ IntDispatchMessage(PMSG pMsg)
     // Need a window!
     if ( !Window ) 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);
-    }
+    /* 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 */
 
-    if (! NT_SUCCESS(PackParam(&lParamPacked, pMsg->message, pMsg->wParam, pMsg->lParam, FALSE)))
-    {
-        DPRINT1("Failed to pack message parameters\n");
-        return 0;
-    }
-    ObReferenceObject(pti->pEThread);
     retval = co_IntCallWindowProc( Window->lpfnWndProc,
                                    !Window->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");
-    }
+                                   pMsg->lParam,
+                                   0);
 
     if (pMsg->message == WM_PAINT)
     {
@@ -520,7 +663,7 @@ IntDispatchMessage(PMSG pMsg)
         co_UserGetUpdateRgn( Window, hrgn, TRUE );
         REGION_FreeRgnByHandle( hrgn );
     }
-    ObDereferenceObject(pti->pEThread);
+
     return retval;
 }
 
@@ -630,12 +773,12 @@ co_IntPeekMessage( PMSG Msg,
         }
 
         if ((ProcessMask & QS_INPUT) &&
-            co_MsqPeekHardwareMessage( ThreadQueue, 
-                                       RemoveMessages, 
-                                       Window, 
-                                       MsgFilterMin, 
+            co_MsqPeekHardwareMessage( ThreadQueue,
+                                       RemoveMessages,
+                                       Window,
+                                       MsgFilterMin,
                                        MsgFilterMax,
-                                       ProcessMask, 
+                                       ProcessMask,
                                        Msg))
         {
             return TRUE;
@@ -677,100 +820,6 @@ co_IntPeekMessage( PMSG Msg,
     return TRUE;
 }
 
-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;
-}
-
-static NTSTATUS FASTCALL
-CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
-{
-    NTSTATUS Status;
-    PMSGMEMORY MsgMemoryEntry;
-    UINT Size;
-
-    /* See if this message type is present in the table */
-    MsgMemoryEntry = FindMsgMemory(UserModeMsg->message);
-    if (NULL == MsgMemoryEntry)
-    {
-        /* Not present, no copying needed */
-        return STATUS_SUCCESS;
-    }
-
-    /* Determine required size */
-    Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
-
-    if (0 != Size)
-    {
-        /* Copy data if required */
-        if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_WRITE))
-        {
-            Status = MmCopyToCaller((PVOID) UserModeMsg->lParam, (PVOID) KernelModeMsg->lParam, Size);
-            if (! NT_SUCCESS(Status))
-            {
-                DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
-                ExFreePool((PVOID) KernelModeMsg->lParam);
-                return Status;
-            }
-        }
-
-        ExFreePool((PVOID) KernelModeMsg->lParam);
-    }
-
-    return STATUS_SUCCESS;
-}
-
 static BOOL FASTCALL
 co_IntWaitMessage( PWND Window,
                    UINT MsgFilterMin,
@@ -798,9 +847,9 @@ co_IntWaitMessage( PWND Window,
 
         /* Nothing found. Wait for new messages. */
         Status = co_MsqWaitForNewMessages( ThreadQueue,
-                                            Window,
-                                            MsgFilterMin,
-                                            MsgFilterMax);
+                                           Window,
+                                           MsgFilterMin,
+                                           MsgFilterMax);
     }
     while ( (STATUS_WAIT_0 <= Status && Status <= STATUS_WAIT_63) ||
             STATUS_TIMEOUT == Status );
@@ -857,6 +906,7 @@ co_IntGetPeekMessage( PMSG pMsg,
     }
 
     pti = PsGetCurrentThreadWin32Thread();
+    pti->pClientInfo->cSpins++; // Bump up the spin count.
 
     do
     {
@@ -868,8 +918,14 @@ co_IntGetPeekMessage( PMSG pMsg,
                                      bGMSG );
         if (Present)
         {
-           pti->timeLast = pMsg->time;
-           pti->ptLast   = pMsg->pt;
+           /* 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.
@@ -930,11 +986,9 @@ UserPostThreadMessage( DWORD idThread,
     LARGE_INTEGER LargeTickCount;
     NTSTATUS Status;
 
-    DPRINT1("UserPostThreadMessage wParam 0x%x  lParam 0x%x\n", wParam,lParam);
-
-    if (FindMsgMemory(Msg) != 0)
+    if (is_pointer_message(Msg))
     {
-        SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
+        EngSetLastError(ERROR_MESSAGE_SYNC_ONLY );
         return FALSE;
     }
 
@@ -998,23 +1052,23 @@ UserPostMessage( HWND Wnd,
         Status = CopyMsgToKernelMem(&KernelModeMsg, &Message, MsgMemoryEntry);
         if (! NT_SUCCESS(Status))
         {
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
+            EngSetLastError(ERROR_INVALID_PARAMETER);
             return FALSE;
         }
-        co_IntSendMessageNoWait(KernelModeMsg.hwnd, 
-                                KernelModeMsg.message, 
-                                KernelModeMsg.wParam, 
+        co_IntSendMessageNoWait(KernelModeMsg.hwnd,
+                                KernelModeMsg.message,
+                                KernelModeMsg.wParam,
                                 KernelModeMsg.lParam);
 
-        if(MsgMemoryEntry)
+        if (MsgMemoryEntry && KernelModeMsg.lParam)
             ExFreePool((PVOID) KernelModeMsg.lParam);
 
         return TRUE;
     }
 
-    if (MsgMemoryEntry)
+    if (is_pointer_message(Message.message))
     {
-        SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
+        EngSetLastError(ERROR_MESSAGE_SYNC_ONLY );
         return FALSE;
     }
 
@@ -1041,7 +1095,7 @@ UserPostMessage( HWND Wnd,
             {
                 UserPostMessage(List[i], Msg, wParam, lParam);
             }
-            ExFreePool(List);
+            ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
         }
     }
     else
@@ -1067,13 +1121,13 @@ UserPostMessage( HWND 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);
         }
     }
@@ -1218,7 +1272,7 @@ MSDN says:
     To get extended error information, call GetLastError. If GetLastError
     returns ERROR_TIMEOUT, then the function timed out.
 */
-        SetLastWin32Error(ERROR_TIMEOUT);
+        EngSetLastError(ERROR_TIMEOUT);
         RETURN( FALSE);
     }
     else if (! NT_SUCCESS(Status))
@@ -1255,7 +1309,7 @@ co_IntSendMessageTimeout( HWND hWnd,
     DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
     if (NULL == DesktopWindow)
     {
-        SetLastWin32Error(ERROR_INTERNAL_ERROR);
+        EngSetLastError(ERROR_INTERNAL_ERROR);
         return 0;
     }
 
@@ -1278,7 +1332,7 @@ co_IntSendMessageTimeout( HWND hWnd,
     return (LRESULT) TRUE;
 }
 
-LRESULT FASTCALL 
+LRESULT FASTCALL
 co_IntSendMessageNoWait(HWND hWnd,
                         UINT Msg,
                         WPARAM wParam,
@@ -1415,7 +1469,7 @@ co_IntSendMessageWithCallBack( HWND hWnd,
 
     Message->QS_Flags = QS_SENDMESSAGE;
     MsqWakeQueue(Window->head.pti->MessageQueue, QS_SENDMESSAGE, FALSE);
-    
+
     InsertTailList(&Window->head.pti->MessageQueue->SentMessagesListHead, &Message->ListEntry);
     IntDereferenceMessageQueue(Window->head.pti->MessageQueue);
 
@@ -1509,7 +1563,7 @@ co_IntDoSendMessage( HWND hWnd,
     Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
     if (! NT_SUCCESS(Status))
     {
-       SetLastWin32Error(ERROR_INVALID_PARAMETER);
+       EngSetLastError(ERROR_INVALID_PARAMETER);
        return (dsm ? 0 : -1);
     }
 
@@ -1534,7 +1588,7 @@ co_IntDoSendMessage( HWND hWnd,
     Status = CopyMsgToUserMem(&UserModeMsg, &KernelModeMsg);
     if (! NT_SUCCESS(Status))
     {
-       SetLastWin32Error(ERROR_INVALID_PARAMETER);
+       EngSetLastError(ERROR_INVALID_PARAMETER);
        return(dsm ? 0 : -1);
     }
 
@@ -1549,9 +1603,9 @@ UserSendNotifyMessage( HWND hWnd,
 {
     BOOL Ret = TRUE;
 
-    if (FindMsgMemory(Msg) != 0)
+    if (is_pointer_message(Msg))
     {
-        SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
+        EngSetLastError(ERROR_MESSAGE_SYNC_ONLY );
         return FALSE;
     }
 
@@ -1571,11 +1625,6 @@ UserSendNotifyMessage( HWND hWnd,
             for (i = 0; List[i]; i++)
             {
                 Ret = UserSendNotifyMessage(List[i], Msg, wParam, lParam);
-                if (!Ret)
-                {
-                   DPRINT1("SendNotifyMessage: Failed in Broadcast!\n");
-                   break;
-                }
             }
             ExFreePool(List);
         }
@@ -1607,9 +1656,9 @@ IntGetQueueStatus(DWORD Changes)
 // wine:
     Changes &= (QS_ALLINPUT|QS_ALLPOSTMESSAGE|QS_SMRESULT);
 
-    /* High word, types of messages currently in the queue. 
+    /* 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 
+                  are still in the queue
      */
     Result = MAKELONG(pti->pcti->fsChangeBits & Changes, pti->pcti->fsWakeBits & Changes);
 
@@ -1650,6 +1699,76 @@ IntUninitMessagePumpHook()
 
 /** Functions ******************************************************************/
 
+BOOL
+APIENTRY
+NtUserDragDetect(
+   HWND hWnd,
+   POINT pt) // Just like the User call.
+{
+    MSG msg;
+    RECT rect;
+    WORD wDragWidth, wDragHeight;
+    DECLARE_RETURN(BOOL);
+
+    DPRINT("Enter NtUserDragDetect(%x)\n", hWnd);
+    UserEnterExclusive();
+
+    wDragWidth = UserGetSystemMetrics(SM_CXDRAG);
+    wDragHeight= UserGetSystemMetrics(SM_CYDRAG);
+
+    rect.left = pt.x - wDragWidth;
+    rect.right = pt.x + wDragWidth;
+
+    rect.top = pt.y - wDragHeight;
+    rect.bottom = pt.y + wDragHeight;
+
+    co_UserSetCapture(hWnd);
+
+    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 NtUserDragDetect, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
+}
+
 BOOL APIENTRY
 NtUserPostMessage(HWND hWnd,
                   UINT Msg,
@@ -1680,7 +1799,7 @@ NtUserPostThreadMessage(DWORD idThread,
     ret = UserPostThreadMessage( idThread, Msg, wParam, lParam);
 
     UserLeave();
-    
+
     return ret;
 }
 
@@ -1694,118 +1813,22 @@ NtUserWaitMessage(VOID)
     ret = co_IntWaitMessage(NULL, 0, 0);
     DPRINT("NtUserWaitMessage Leave\n");
     UserLeave();
-    
+
     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.
-*/
-{
-    NTUSERGETMESSAGEINFO Info;
-    NTSTATUS Status;
-    PMSGMEMORY MsgMemoryEntry;
-    PVOID UserMem;
-    ULONG Size;
-    MSG Msg;
-    BOOL GotMessage;
-
-    if ( (MsgFilterMin|MsgFilterMax) & ~WM_MAXIMUM )
-    {
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
-        return FALSE;
-    }
-
-    UserEnterExclusive();
-
-    RtlZeroMemory(&Msg, sizeof(MSG));
-
-    GotMessage = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE, TRUE);
-
-    UserLeave();
-
-    Info.Msg = Msg;
-    /* See if this message type is present in the table */
-    MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
-
-    _SEH2_TRY
-    {
-        ProbeForWrite(UnsafeInfo, sizeof(NTUSERGETMESSAGEINFO), 1);
-        RtlCopyMemory(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO));
-
-        if (NULL == MsgMemoryEntry)
-        {
-            /* Not present, no copying needed */
-            UnsafeInfo->LParamSize = 0;
-        }
-        else
-        {
-            /* Determine required size */
-            Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam, Info.Msg.lParam);
-
-            /* Allocate required amount of user-mode memory */
-            Status = ZwAllocateVirtualMemory(NtCurrentProcess(), 
-                                             &UserMem, 
-                                             0,
-                                             &Size, 
-                                             MEM_COMMIT, 
-                                             PAGE_READWRITE);
-            if (! NT_SUCCESS(Status))
-            {
-                SetLastNtError(Status);
-                _SEH2_YIELD(return (BOOL) -1);
-            }
-
-            /* Transfer lParam data to user-mode mem */
-            ProbeForWrite(UserMem, Size, 1);
-            RtlCopyMemory(UserMem, (PVOID)Info.Msg.lParam, Size);
-
-            UnsafeInfo->LParamSize = Size;
-            UnsafeInfo->Msg.lParam = (LPARAM) UserMem;
-        }
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        SetLastNtError(_SEH2_GetExceptionCode());
-
-        if(UserMem != NULL)
-        {
-            ZwFreeVirtualMemory(NtCurrentProcess(), &UserMem, &Size, MEM_RELEASE);
-        }
-
-        _SEH2_YIELD(return (BOOL) -1);
-    }
-    _SEH2_END;
-    
-    return GotMessage;
-}
-
-
-BOOL APIENTRY
-NtUserGetMessageX(PMSG pMsg,
-                  HWND hWnd,
-                  UINT MsgFilterMin,
-                  UINT MsgFilterMax)
 {
     MSG Msg;
     BOOL Ret;
 
     if ( (MsgFilterMin|MsgFilterMax) & ~WM_MAXIMUM )
     {
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
@@ -1836,105 +1859,18 @@ NtUserGetMessageX(PMSG pMsg,
 }
 
 BOOL APIENTRY
-NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
+NtUserPeekMessage( PMSG pMsg,
                   HWND hWnd,
                   UINT MsgFilterMin,
                   UINT MsgFilterMax,
                   UINT RemoveMsg)
-{
-    NTSTATUS Status;
-    NTUSERGETMESSAGEINFO Info;
-    PMSGMEMORY MsgMemoryEntry;
-    PVOID UserMem = NULL;
-    ULONG Size;
-    MSG Msg;
-    BOOL Ret;
-
-    if ( RemoveMsg & PM_BADMSGFLAGS )
-    {
-        SetLastWin32Error(ERROR_INVALID_FLAGS);
-        return FALSE;
-    }
-
-    UserEnterExclusive();
-
-    RtlZeroMemory(&Msg, sizeof(MSG));
-
-    Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg, FALSE);
-
-    UserLeave();
-
-    if (Ret)
-    {
-        Info.Msg = Msg;
-        /* See if this message type is present in the table */
-        MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
-
-        _SEH2_TRY
-        {
-            ProbeForWrite(UnsafeInfo, sizeof(NTUSERGETMESSAGEINFO), 1);
-            RtlCopyMemory(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO));
-
-            if (NULL == MsgMemoryEntry)
-            {
-                /* Not present, no copying needed */
-                UnsafeInfo->LParamSize = 0;
-            }
-            else
-            {
-                /* Determine required size */
-                Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam, Info.Msg.lParam);
-
-                /* Allocate required amount of user-mode memory */
-                Status = ZwAllocateVirtualMemory(NtCurrentProcess(), 
-                                                 &UserMem, 
-                                                 0,
-                                                 &Size, 
-                                                 MEM_COMMIT, 
-                                                 PAGE_READWRITE);
-                if (! NT_SUCCESS(Status))
-                {
-                    SetLastNtError(Status);
-                    _SEH2_YIELD(return (BOOL) -1);
-                }
-
-                /* Transfer lParam data to user-mode mem */
-                ProbeForWrite(UserMem, Size, 1);
-                RtlCopyMemory(UserMem, (PVOID)Info.Msg.lParam, Size);
-
-                UnsafeInfo->LParamSize = Size;
-                UnsafeInfo->Msg.lParam = (LPARAM) UserMem;
-            }
-        }
-        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-        {
-            SetLastNtError(_SEH2_GetExceptionCode());
-            Ret = (BOOL) -1;
-
-            if(UserMem != NULL)
-            {
-                ZwFreeVirtualMemory(NtCurrentProcess(), &UserMem, &Size, MEM_RELEASE);
-            }
-        }
-        _SEH2_END;
-    }
-
-    return Ret;
-}
-
-BOOL APIENTRY
-NtUserPeekMessageX( PMSG pMsg,
-                    HWND hWnd,
-                    UINT MsgFilterMin,
-                    UINT MsgFilterMax,
-                    UINT RemoveMsg)
 {
     MSG Msg;
     BOOL Ret;
 
     if ( RemoveMsg & PM_BADMSGFLAGS )
     {
-        SetLastWin32Error(ERROR_INVALID_FLAGS);
+        EngSetLastError(ERROR_INVALID_FLAGS);
         return FALSE;
     }
 
@@ -1960,7 +1896,7 @@ NtUserPeekMessageX( PMSG pMsg,
         }
         _SEH2_END;
     }
-    
+
     return Ret;
 }
 
@@ -2064,7 +2000,7 @@ NtUserTranslateMessage(LPMSG lpMsg, UINT flags)
 
 BOOL APIENTRY
 NtUserMessageCall( HWND hWnd,
-                   UINT Msg, 
+                   UINT Msg,
                    WPARAM wParam,
                    LPARAM lParam,
                    ULONG_PTR ResultInfo,
@@ -2175,14 +2111,23 @@ NtUserMessageCall( HWND hWnd,
         break;
     case FNID_SENDMESSAGECALLBACK:
         {
-            PCALL_BACK_INFO CallBackInfo = (PCALL_BACK_INFO)ResultInfo;
+            CALL_BACK_INFO CallBackInfo;
             ULONG_PTR uResult;
 
-            if (!CallBackInfo)
-                break;
+            _SEH2_TRY
+            {
+                ProbeForRead((PVOID)ResultInfo, sizeof(CALL_BACK_INFO), 1);
+                RtlCopyMemory(&CallBackInfo, (PVOID)ResultInfo, sizeof(CALL_BACK_INFO));
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                Ret = FALSE;
+                _SEH2_YIELD(break);
+            }
+            _SEH2_END;
 
             if (!co_IntSendMessageWithCallBack(hWnd, Msg, wParam, lParam,
-                        CallBackInfo->CallBack, CallBackInfo->Context, &uResult))
+                        CallBackInfo.CallBack, CallBackInfo.Context, &uResult))
             {
                 DPRINT1("Callback failure!\n");
             }
@@ -2225,7 +2170,7 @@ NtUserMessageCall( HWND hWnd,
                 }
                 _SEH2_END;
             }
-            
+
             Ret = co_IntDoSendMessage( hWnd, Msg, wParam, lParam, &dsm );
 
             if (pdsm)
@@ -2382,7 +2327,7 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
     {
         ObDereferenceObject(Process);
         UserLeave();
-        SetLastWin32Error(ERROR_INVALID_PARAMETER);
+        EngSetLastError(ERROR_INVALID_PARAMETER);
         return WAIT_FAILED;
     }