- Fix MSVC build based on ThFabba suggestion
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / input.c
index c8ea14c..1430a51 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
- * PURPOSE:          Window classes
+ * PURPOSE:          General input functions
  * FILE:             subsystems/win32/win32k/ntuser/input.c
  * PROGRAMERS:       Casper S. Hornstrup (chorns@users.sourceforge.net)
  *                   Rafal Harabien (rafalh@reactos.org)
@@ -23,27 +23,15 @@ PATTACHINFO gpai = NULL;
 HANDLE ghKeyboardDevice;
 
 static DWORD LastInputTick = 0;
-static HANDLE MouseDeviceHandle;
-static HANDLE RawInputThreadHandle;
-static CLIENT_ID RawInputThreadId;
-static KEVENT InputThreadsStart;
-static BOOLEAN InputThreadsRunning = FALSE;
+static HANDLE ghMouseDevice;
 
 /* FUNCTIONS *****************************************************************/
 
-#define ClearMouseInput(mi) \
-  mi.dx = 0; \
-  mi.dy = 0; \
-  mi.mouseData = 0; \
-  mi.dwFlags = 0;
-
-#define SendMouseEvent(mi) \
-  if(mi.dx != 0 || mi.dy != 0) \
-    mi.dwFlags |= MOUSEEVENTF_MOVE; \
-  if(mi.dwFlags) \
-    IntMouseInput(&mi,FALSE); \
-  ClearMouseInput(mi);
-
+/*
+ * IntLastInputTick
+ *
+ * Updates or gets last input tick count
+ */
 static DWORD FASTCALL
 IntLastInputTick(BOOL bUpdate)
 {
@@ -57,6 +45,11 @@ IntLastInputTick(BOOL bUpdate)
     return LastInputTick;
 }
 
+/*
+ * DoTheScreenSaver
+ *
+ * Check if scrensaver should be started and sends message to SAS window
+ */
 VOID FASTCALL
 DoTheScreenSaver(VOID)
 {
@@ -93,325 +86,194 @@ DoTheScreenSaver(VOID)
     }
 }
 
-static VOID NTAPI
-IntProcessMouseInputData(PMOUSE_INPUT_DATA Data, ULONG InputCount)
-{
-    PMOUSE_INPUT_DATA mid;
-    MOUSEINPUT mi;
-    ULONG i;
-
-    ClearMouseInput(mi);
-    mi.time = 0;
-    mi.dwExtraInfo = 0;
-    for(i = 0; i < InputCount; i++)
-    {
-        mid = (Data + i);
-        mi.dx += mid->LastX;
-        mi.dy += mid->LastY;
-
-        /* Check if the mouse move is absolute */
-        if (mid->Flags == MOUSE_MOVE_ABSOLUTE)
-        {
-            /* Set flag to convert to screen location */
-            mi.dwFlags |= MOUSEEVENTF_ABSOLUTE;
-        }
-
-        if(mid->ButtonFlags)
-        {
-            if(mid->ButtonFlags & MOUSE_LEFT_BUTTON_DOWN)
-            {
-                mi.dwFlags |= MOUSEEVENTF_LEFTDOWN;
-                SendMouseEvent(mi);
-            }
-            if(mid->ButtonFlags & MOUSE_LEFT_BUTTON_UP)
-            {
-                mi.dwFlags |= MOUSEEVENTF_LEFTUP;
-                SendMouseEvent(mi);
-            }
-            if(mid->ButtonFlags & MOUSE_MIDDLE_BUTTON_DOWN)
-            {
-                mi.dwFlags |= MOUSEEVENTF_MIDDLEDOWN;
-                SendMouseEvent(mi);
-            }
-            if(mid->ButtonFlags & MOUSE_MIDDLE_BUTTON_UP)
-            {
-                mi.dwFlags |= MOUSEEVENTF_MIDDLEUP;
-                SendMouseEvent(mi);
-            }
-            if(mid->ButtonFlags & MOUSE_RIGHT_BUTTON_DOWN)
-            {
-                mi.dwFlags |= MOUSEEVENTF_RIGHTDOWN;
-                SendMouseEvent(mi);
-            }
-            if(mid->ButtonFlags & MOUSE_RIGHT_BUTTON_UP)
-            {
-                mi.dwFlags |= MOUSEEVENTF_RIGHTUP;
-                SendMouseEvent(mi);
-            }
-            if(mid->ButtonFlags & MOUSE_BUTTON_4_DOWN)
-            {
-                mi.mouseData |= XBUTTON1;
-                mi.dwFlags |= MOUSEEVENTF_XDOWN;
-                SendMouseEvent(mi);
-            }
-            if(mid->ButtonFlags & MOUSE_BUTTON_4_UP)
-            {
-                mi.mouseData |= XBUTTON1;
-                mi.dwFlags |= MOUSEEVENTF_XUP;
-                SendMouseEvent(mi);
-            }
-            if(mid->ButtonFlags & MOUSE_BUTTON_5_DOWN)
-            {
-                mi.mouseData |= XBUTTON2;
-                mi.dwFlags |= MOUSEEVENTF_XDOWN;
-                SendMouseEvent(mi);
-            }
-            if(mid->ButtonFlags & MOUSE_BUTTON_5_UP)
-            {
-                mi.mouseData |= XBUTTON2;
-                mi.dwFlags |= MOUSEEVENTF_XUP;
-                SendMouseEvent(mi);
-            }
-            if(mid->ButtonFlags & MOUSE_WHEEL)
-            {
-                mi.mouseData = mid->ButtonData;
-                mi.dwFlags |= MOUSEEVENTF_WHEEL;
-                SendMouseEvent(mi);
-            }
-        }
-    }
-
-    SendMouseEvent(mi);
-}
-
-static VOID APIENTRY
-MouseThreadMain(PVOID StartContext)
+/*
+ * OpenInputDevice
+ *
+ * Opens input device for asynchronous access
+ */
+static
+NTSTATUS NTAPI
+OpenInputDevice(PHANDLE pHandle, PFILE_OBJECT *ppObject, CONST WCHAR *pszDeviceName)
 {
-    UNICODE_STRING MouseDeviceName = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");
-    OBJECT_ATTRIBUTES MouseObjectAttributes;
-    IO_STATUS_BLOCK Iosb;
+    UNICODE_STRING DeviceName;
+    OBJECT_ATTRIBUTES ObjectAttributes;
     NTSTATUS Status;
-    MOUSE_ATTRIBUTES MouseAttr;
+    IO_STATUS_BLOCK Iosb;
 
-    KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
-                        LOW_REALTIME_PRIORITY + 3);
+    RtlInitUnicodeString(&DeviceName, pszDeviceName);
 
-    InitializeObjectAttributes(&MouseObjectAttributes,
-                               &MouseDeviceName,
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &DeviceName,
                                0,
                                NULL,
                                NULL);
-    do
-    {
-        LARGE_INTEGER DueTime;
-        KEVENT Event;
-        DueTime.QuadPart = (LONGLONG)(-10000000);
-        KeInitializeEvent(&Event, NotificationEvent, FALSE);
-        Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &DueTime);
-        Status = ZwOpenFile(&MouseDeviceHandle,
-                            FILE_ALL_ACCESS,
-                            &MouseObjectAttributes,
-                            &Iosb,
-                            0,
-                            FILE_SYNCHRONOUS_IO_ALERT);
-    } while (!NT_SUCCESS(Status));
-
-    /* Need to setup basic win32k for this thread to process WH_MOUSE_LL messages. */
-    /*Status = Win32kInitWin32Thread(PsGetCurrentThread());
-    if (!NT_SUCCESS(Status))
+
+    Status = ZwOpenFile(pHandle,
+                        FILE_ALL_ACCESS,
+                        &ObjectAttributes,
+                        &Iosb,
+                        0,
+                        0);
+    if (NT_SUCCESS(Status) && ppObject)
     {
-        ERR("Win32K: Failed making mouse thread a win32 thread.\n");
-        return; //(Status);
-    }*/
+        Status = ObReferenceObjectByHandle(*pHandle, SYNCHRONIZE, NULL, KernelMode, (PVOID*)ppObject, NULL);
+        ASSERT(NT_SUCCESS(Status));
+    }
+
+    return Status;
+}
+
+/*
+ * RawInputThreadMain
+ *
+ * Reads data from input devices and supports win32 timers
+ */
+VOID NTAPI
+RawInputThreadMain()
+{
+    NTSTATUS MouStatus = STATUS_UNSUCCESSFUL, KbdStatus = STATUS_UNSUCCESSFUL, Status;
+    IO_STATUS_BLOCK MouIosb, KbdIosb;
+    PFILE_OBJECT pKbdDevice, pMouDevice;
+    LARGE_INTEGER WaitTimeout, ByteOffset;
+    PVOID WaitObjects[3], pSignaledObject = NULL;
+    ULONG cWaitObjects = 0, cMaxWaitObjects = 1;
+    MOUSE_INPUT_DATA MouseInput;
+    KEYBOARD_INPUT_DATA KeyInput;
+    
+    ByteOffset.QuadPart = (LONGLONG)0;
+    WaitTimeout.QuadPart = (LONGLONG)(-10000000);
 
-    ptiMouse = PsGetCurrentThreadWin32Thread();
-    ptiMouse->TIF_flags |= TIF_SYSTEMTHREAD;
-    TRACE("Mouse Thread 0x%x \n", ptiMouse);
+    ptiRawInput = PsGetCurrentThreadWin32Thread();
+    ptiRawInput->TIF_flags |= TIF_SYSTEMTHREAD;
+    TRACE("Raw Input Thread 0x%x\n", ptiRawInput);
 
     KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
                         LOW_REALTIME_PRIORITY + 3);
 
+    UserEnterExclusive();
+    StartTheTimers();
+    UserLeave();
+
     for(;;)
     {
-        /*
-         * Wait to start input.
-         */
-        TRACE("Mouse Input Thread Waiting for start event\n");
-        Status = KeWaitForSingleObject(&InputThreadsStart,
-                                       0,
-                                       KernelMode,
-                                       TRUE,
-                                       NULL);
-        TRACE("Mouse Input Thread Starting...\n");
+        if (!ghMouseDevice)
+        {
+            /* Check if mouse device already exists */
+            Status = OpenInputDevice(&ghMouseDevice, &pMouDevice, L"\\Device\\PointerClass0" );
+            if (NT_SUCCESS(Status))
+            {
+                ++cMaxWaitObjects;
+                TRACE("Mouse connected!\n");
+            }
+        }
+        if (!ghKeyboardDevice)
+        {
+            /* Check if keyboard device already exists */
+            Status = OpenInputDevice(&ghKeyboardDevice, &pKbdDevice, L"\\Device\\KeyboardClass0");
+            if (NT_SUCCESS(Status))
+            {
+                ++cMaxWaitObjects;
+                TRACE("Keyboard connected!\n");
+            }
+        }
+
+        /* Reset WaitHandles array */
+        cWaitObjects = 0;
+        WaitObjects[cWaitObjects++] = MasterTimer;
 
-        /*FIXME: Does mouse attributes need to be used for anything */
-        Status = ZwDeviceIoControlFile(MouseDeviceHandle,
+        if (ghMouseDevice)
+        {
+            /* Try to read from mouse if previous reading is not pending */
+            if (MouStatus != STATUS_PENDING)
+            {
+                MouStatus = ZwReadFile(ghMouseDevice,
                                        NULL,
                                        NULL,
                                        NULL,
-                                       &Iosb,
-                                       IOCTL_MOUSE_QUERY_ATTRIBUTES,
-                                       &MouseAttr, sizeof(MOUSE_ATTRIBUTES),
-                                       NULL, 0);
-        if(!NT_SUCCESS(Status))
-        {
-            TRACE("Failed to get mouse attributes\n");
+                                       &MouIosb,
+                                       &MouseInput,
+                                       sizeof(MOUSE_INPUT_DATA),
+                                       &ByteOffset,
+                                       NULL);
+            }
+            
+            if (MouStatus == STATUS_PENDING)
+                WaitObjects[cWaitObjects++] = &pMouDevice->Event;
         }
 
-        /*
-         * Receive and process mouse input.
-         */
-        while(InputThreadsRunning)
+        if (ghKeyboardDevice)
         {
-            MOUSE_INPUT_DATA MouseInput;
-            Status = ZwReadFile(MouseDeviceHandle,
-                                NULL,
-                                NULL,
-                                NULL,
-                                &Iosb,
-                                &MouseInput,
-                                sizeof(MOUSE_INPUT_DATA),
-                                NULL,
-                                NULL);
-            if(Status == STATUS_ALERTED && !InputThreadsRunning)
-            {
-                break;
-            }
-            if(Status == STATUS_PENDING)
+            /* Try to read from keyboard if previous reading is not pending */
+            if (KbdStatus != STATUS_PENDING)
             {
-                NtWaitForSingleObject(MouseDeviceHandle, FALSE, NULL);
-                Status = Iosb.Status;
+                KbdStatus = ZwReadFile(ghKeyboardDevice,
+                                       NULL,
+                                       NULL,
+                                       NULL,
+                                       &KbdIosb,
+                                       &KeyInput,
+                                       sizeof(KEYBOARD_INPUT_DATA),
+                                       &ByteOffset,
+                                       NULL);
+                
             }
-            if(!NT_SUCCESS(Status))
+            if (KbdStatus == STATUS_PENDING)
+                WaitObjects[cWaitObjects++] = &pKbdDevice->Event;
+        }
+
+        /* If all objects are pending, wait for them */
+        if (cWaitObjects == cMaxWaitObjects)
+        {
+            Status = KeWaitForMultipleObjects(cWaitObjects,
+                                              WaitObjects,
+                                              WaitAny,
+                                              UserRequest,
+                                              KernelMode,
+                                              TRUE,
+                                              NULL,//&WaitTimeout,
+                                              NULL);
+
+            if (Status >= STATUS_WAIT_0 && Status < STATUS_WAIT_0 + cWaitObjects)
             {
-                ERR("Win32K: Failed to read from mouse.\n");
-                return; //(Status);
+                /* Some device has finished reading */
+                pSignaledObject = WaitObjects[Status - STATUS_WAIT_0];
+
+                /* Check if it is mouse or keyboard and update status */
+                if (pSignaledObject == &pMouDevice->Event)
+                    MouStatus = MouIosb.Status;
+                else if (pSignaledObject == &pKbdDevice->Event)
+                    KbdStatus = KbdIosb.Status;
+                else if (pSignaledObject == MasterTimer)
+                {
+                    /* FIXME: where it should go? */
+                    ProcessTimers();
+                }
+                else ASSERT(FALSE);
             }
+        }
+
+        /* Have we successed reading from mouse? */
+        if (NT_SUCCESS(MouStatus) && MouStatus != STATUS_PENDING)
+        {
             TRACE("MouseEvent\n");
+
+            /* Set LastInputTick */
             IntLastInputTick(TRUE);
 
+            /* Process data */
             UserEnterExclusive();
-
-            IntProcessMouseInputData(&MouseInput, Iosb.Information / sizeof(MOUSE_INPUT_DATA));
-
+            UserProcessMouseInput(&MouseInput, MouIosb.Information / sizeof(MOUSE_INPUT_DATA));
             UserLeave();
         }
-        TRACE("Mouse Input Thread Stopped...\n");
-    }
-}
-
-VOID NTAPI
-KeyboardThreadMain(PVOID StartContext)
-{
-    UNICODE_STRING KeyboardDeviceName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass0");
-    OBJECT_ATTRIBUTES KeyboardObjectAttributes;
-    IO_STATUS_BLOCK Iosb;
-    NTSTATUS Status;
-
-    InitializeObjectAttributes(&KeyboardObjectAttributes,
-                               &KeyboardDeviceName,
-                               0,
-                               NULL,
-                               NULL);
-    do
-    {
-        LARGE_INTEGER DueTime;
-        KEVENT Event;
-        DueTime.QuadPart = (LONGLONG)(-100000000);
-        KeInitializeEvent(&Event, NotificationEvent, FALSE);
-        Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &DueTime);
-        Status = ZwOpenFile(&ghKeyboardDevice,
-                            FILE_READ_ACCESS,//FILE_ALL_ACCESS,
-                            &KeyboardObjectAttributes,
-                            &Iosb,
-                            0,
-                            FILE_SYNCHRONOUS_IO_ALERT);
-    } while (!NT_SUCCESS(Status));
-
-    UserInitKeyboard(ghKeyboardDevice);
-
-    /* Not sure if converting this thread to a win32 thread is such
-       a great idea. Since we're posting keyboard messages to the focus
-       window message queue, we'll be (indirectly) doing sendmessage
-       stuff from this thread (for WH_KEYBOARD_LL processing), which
-       means we need our own message queue. If keyboard messages were
-       instead queued to the system message queue, the thread removing
-       the message from the system message queue would be responsible
-       for WH_KEYBOARD_LL processing and we wouldn't need this thread
-       to be a win32 thread. */
-    /*Status = Win32kInitWin32Thread(PsGetCurrentThread());
-    if (!NT_SUCCESS(Status))
-    {
-        ERR("Win32K: Failed making keyboard thread a win32 thread.\n");
-        return; //(Status);
-    }*/
+        else if (MouStatus != STATUS_PENDING)
+            ERR("Failed to read from mouse: %x.\n", MouStatus);
 
-    ptiKeyboard = PsGetCurrentThreadWin32Thread();
-    ptiKeyboard->TIF_flags |= TIF_SYSTEMTHREAD;
-    TRACE("Keyboard Thread 0x%x \n", ptiKeyboard);
-
-    KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
-                        LOW_REALTIME_PRIORITY + 3);
-
-    for (;;)
-    {
-        /*
-         * Wait to start input.
-         */
-        TRACE("Keyboard Input Thread Waiting for start event\n");
-        Status = KeWaitForSingleObject(&InputThreadsStart,
-                                       0,
-                                       KernelMode,
-                                       TRUE,
-                                       NULL);
-
-        TRACE("Keyboard Input Thread Starting...\n");
-        /*
-         * Receive and process keyboard input.
-         */
-        while (InputThreadsRunning)
+        /* Have we successed reading from keyboard? */
+        if (NT_SUCCESS(KbdStatus) && KbdStatus != STATUS_PENDING)
         {
-            KEYBOARD_INPUT_DATA KeyInput;
-
-            TRACE("KeyInput @ %08x\n", &KeyInput);
-
-            Status = ZwReadFile (ghKeyboardDevice,
-                                 NULL,
-                                 NULL,
-                                 NULL,
-                                 &Iosb,
-                                 &KeyInput,
-                                 sizeof(KEYBOARD_INPUT_DATA),
-                                 NULL,
-                                 NULL);
-
-            if (Status == STATUS_ALERTED && !InputThreadsRunning)
-            {
-                break;
-            }
-            if (Status == STATUS_PENDING)
-            {
-                NtWaitForSingleObject(ghKeyboardDevice, FALSE, NULL);
-                Status = Iosb.Status;
-            }
-            if (!NT_SUCCESS(Status))
-            {
-                ERR("Win32K: Failed to read from keyboard.\n");
-                return; //(Status);
-            }
-
-            TRACE("KeyRaw: %s %04x\n",
+            TRACE("KeyboardEvent: %s %04x\n",
                   (KeyInput.Flags & KEY_BREAK) ? "up" : "down",
-                  KeyInput.MakeCode );
-
-            if (Status == STATUS_ALERTED && !InputThreadsRunning)
-                break;
-
-            if (!NT_SUCCESS(Status))
-            {
-                ERR("Win32K: Failed to read from keyboard.\n");
-                return; //(Status);
-            }
+                  KeyInput.MakeCode);
 
             /* Set LastInputTick */
             IntLastInputTick(TRUE);
@@ -421,77 +283,18 @@ KeyboardThreadMain(PVOID StartContext)
             UserProcessKeyboardInput(&KeyInput);
             UserLeave();
         }
-
-        TRACE("KeyboardInput Thread Stopped...\n");
+        else if (KbdStatus != STATUS_PENDING)
+            ERR("Failed to read from keyboard: %x.\n", KbdStatus);
     }
+    ERR("Raw Input Thread Exit!\n");
 }
 
-
-static PVOID Objects[2];
 /*
-    Raw Input Thread.
-    Since this relies on InputThreadsStart, just fake it.
+ * CreateSystemThreads
+ *
+ * Called form dedicated thread in CSRSS. RIT is started in context of this
+ * thread because it needs valid Win32 process with TEB initialized
  */
-static VOID APIENTRY
-RawInputThreadMain(PVOID StartContext)
-{
-    NTSTATUS Status;
-    LARGE_INTEGER DueTime;
-
-    DueTime.QuadPart = (LONGLONG)(-10000000);
-
-    do
-    {
-        KEVENT Event;
-        KeInitializeEvent(&Event, NotificationEvent, FALSE);
-        Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &DueTime);
-    } while (!NT_SUCCESS(Status));
-
-
-    Objects[0] = &InputThreadsStart;
-    Objects[1] = MasterTimer;
-
-    // This thread requires win32k!
-    Status = Win32kInitWin32Thread(PsGetCurrentThread());
-    if (!NT_SUCCESS(Status))
-    {
-        ERR("Win32K: Failed making Raw Input thread a win32 thread.\n");
-        return; //(Status);
-    }
-
-    ptiRawInput = PsGetCurrentThreadWin32Thread();
-    ptiRawInput->TIF_flags |= TIF_SYSTEMTHREAD;
-    TRACE("Raw Input Thread 0x%x \n", ptiRawInput);
-
-    KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
-                        LOW_REALTIME_PRIORITY + 3);
-
-    UserEnterExclusive();
-    StartTheTimers();
-    UserLeave();
-
-    //
-    // ATM, we just have one job to handle, merge the other two later.
-    //
-    for(;;)
-    {
-        TRACE("Raw Input Thread Waiting for start event\n");
-
-        Status = KeWaitForMultipleObjects( 2,
-                                           Objects,
-                                           WaitAll, //WaitAny,
-                                           WrUserRequest,
-                                           KernelMode,
-                                           TRUE,
-                                           NULL,
-                                           NULL);
-        TRACE("Raw Input Thread Starting...\n");
-
-        ProcessTimers();
-    }
-    ERR("Raw Input Thread Exit!\n");
-}
-
 DWORD NTAPI
 CreateSystemThreads(UINT Type)
 {
@@ -499,8 +302,7 @@ CreateSystemThreads(UINT Type)
 
     switch (Type)
     {
-        case 0: KeyboardThreadMain(NULL); break;
-        case 1: MouseThreadMain(NULL); break;
+        case 0: RawInputThreadMain(); break;
         default: ERR("Wrong type: %x\n", Type);
     }
 
@@ -509,52 +311,43 @@ CreateSystemThreads(UINT Type)
     return 0;
 }
 
+/*
+ * InitInputImpl
+ *
+ * Inits input implementation
+ */
 INIT_FUNCTION
 NTSTATUS
 NTAPI
 InitInputImpl(VOID)
 {
-    NTSTATUS Status;
-
-    KeInitializeEvent(&InputThreadsStart, NotificationEvent, FALSE);
-
     MasterTimer = ExAllocatePoolWithTag(NonPagedPool, sizeof(KTIMER), USERTAG_SYSTEM);
     if (!MasterTimer)
     {
-        ERR("Win32K: Failed making Raw Input thread a win32 thread.\n");
+        ERR("Failed to allocate memory\n");
         ASSERT(FALSE);
         return STATUS_UNSUCCESSFUL;
     }
     KeInitializeTimer(MasterTimer);
 
     /* Initialize the default keyboard layout */
-    if(!UserInitDefaultKeyboardLayout())
+    if (!UserInitDefaultKeyboardLayout())
     {
         ERR("Failed to initialize default keyboard layout!\n");
     }
 
-    Status = PsCreateSystemThread(&RawInputThreadHandle,
-                                  THREAD_ALL_ACCESS,
-                                  NULL,
-                                  NULL,
-                                  &RawInputThreadId,
-                                  RawInputThreadMain,
-                                  NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        ERR("Win32K: Failed to create raw thread.\n");
-    }
-
-    InputThreadsRunning = TRUE;
-    KeSetEvent(&InputThreadsStart, IO_NO_INCREMENT, FALSE);
-
     return STATUS_SUCCESS;
 }
 
+/*
+ * CleanupInputImp
+ *
+ * Cleans input implementation
+ */
 NTSTATUS FASTCALL
 CleanupInputImp(VOID)
 {
-    return(STATUS_SUCCESS);
+    return STATUS_SUCCESS;
 }
 
 BOOL FASTCALL
@@ -618,175 +411,6 @@ NtUserBlockInput(
     return ret;
 }
 
-BOOL FASTCALL
-IntMouseInput(MOUSEINPUT *mi, BOOL Injected)
-{
-    const UINT SwapBtnMsg[2][2] =
-    {
-        {WM_LBUTTONDOWN, WM_RBUTTONDOWN},
-        {WM_LBUTTONUP, WM_RBUTTONUP}
-    };
-    const WPARAM SwapBtn[2] =
-    {
-        MK_LBUTTON, MK_RBUTTON
-    };
-    POINT MousePos;
-    PSYSTEM_CURSORINFO CurInfo;
-    BOOL SwapButtons;
-    MSG Msg;
-
-    ASSERT(mi);
-
-    CurInfo = IntGetSysCursorInfo();
-
-    if(!mi->time)
-    {
-        LARGE_INTEGER LargeTickCount;
-        KeQueryTickCount(&LargeTickCount);
-        mi->time = MsqCalculateMessageTime(&LargeTickCount);
-    }
-
-    SwapButtons = gspv.bMouseBtnSwap;
-
-    MousePos = gpsi->ptCursor;
-
-    if(mi->dwFlags & MOUSEEVENTF_MOVE)
-    {
-        if(mi->dwFlags & MOUSEEVENTF_ABSOLUTE)
-        {
-            MousePos.x = mi->dx * UserGetSystemMetrics(SM_CXVIRTUALSCREEN) >> 16;
-            MousePos.y = mi->dy * UserGetSystemMetrics(SM_CYVIRTUALSCREEN) >> 16;
-        }
-        else
-        {
-            MousePos.x += mi->dx;
-            MousePos.y += mi->dy;
-        }
-    }
-
-    /*
-     * Insert the messages into the system queue
-     */
-    Msg.wParam = 0;
-    Msg.lParam = MAKELPARAM(MousePos.x, MousePos.y);
-    Msg.pt = MousePos;
-
-    if (IS_KEY_DOWN(gafAsyncKeyState, VK_SHIFT))
-    {
-        Msg.wParam |= MK_SHIFT;
-    }
-
-    if (IS_KEY_DOWN(gafAsyncKeyState, VK_CONTROL))
-    {
-        Msg.wParam |= MK_CONTROL;
-    }
-
-    if(mi->dwFlags & MOUSEEVENTF_MOVE)
-    {
-        UserSetCursorPos(MousePos.x, MousePos.y, Injected, mi->dwExtraInfo, TRUE);
-    }
-    if(mi->dwFlags & MOUSEEVENTF_LEFTDOWN)
-    {
-        SET_KEY_DOWN(gafAsyncKeyState, VK_LBUTTON, TRUE);
-        Msg.message = SwapBtnMsg[0][SwapButtons];
-        CurInfo->ButtonsDown |= SwapBtn[SwapButtons];
-        Msg.wParam |= CurInfo->ButtonsDown;
-        co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
-    }
-    else if(mi->dwFlags & MOUSEEVENTF_LEFTUP)
-    {
-        SET_KEY_DOWN(gafAsyncKeyState, VK_LBUTTON, FALSE);
-        Msg.message = SwapBtnMsg[1][SwapButtons];
-        CurInfo->ButtonsDown &= ~SwapBtn[SwapButtons];
-        Msg.wParam |= CurInfo->ButtonsDown;
-        co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
-    }
-    if(mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN)
-    {
-        SET_KEY_DOWN(gafAsyncKeyState, VK_MBUTTON, TRUE);
-        Msg.message = WM_MBUTTONDOWN;
-        CurInfo->ButtonsDown |= MK_MBUTTON;
-        Msg.wParam |= CurInfo->ButtonsDown;
-        co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
-    }
-    else if(mi->dwFlags & MOUSEEVENTF_MIDDLEUP)
-    {
-        SET_KEY_DOWN(gafAsyncKeyState, VK_MBUTTON, FALSE);
-        Msg.message = WM_MBUTTONUP;
-        CurInfo->ButtonsDown &= ~MK_MBUTTON;
-        Msg.wParam |= CurInfo->ButtonsDown;
-        co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
-    }
-    if(mi->dwFlags & MOUSEEVENTF_RIGHTDOWN)
-    {
-        SET_KEY_DOWN(gafAsyncKeyState, VK_RBUTTON, TRUE);
-        Msg.message = SwapBtnMsg[0][!SwapButtons];
-        CurInfo->ButtonsDown |= SwapBtn[!SwapButtons];
-        Msg.wParam |= CurInfo->ButtonsDown;
-        co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
-    }
-    else if(mi->dwFlags & MOUSEEVENTF_RIGHTUP)
-    {
-        SET_KEY_DOWN(gafAsyncKeyState, VK_RBUTTON, FALSE);
-        Msg.message = SwapBtnMsg[1][!SwapButtons];
-        CurInfo->ButtonsDown &= ~SwapBtn[!SwapButtons];
-        Msg.wParam |= CurInfo->ButtonsDown;
-        co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
-    }
-
-    if((mi->dwFlags & (MOUSEEVENTF_XDOWN | MOUSEEVENTF_XUP)) &&
-            (mi->dwFlags & MOUSEEVENTF_WHEEL))
-    {
-        /* fail because both types of events use the mouseData field */
-        return FALSE;
-    }
-
-    if(mi->dwFlags & MOUSEEVENTF_XDOWN)
-    {
-        Msg.message = WM_XBUTTONDOWN;
-        if(mi->mouseData & XBUTTON1)
-        {
-            SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON1, TRUE);
-            CurInfo->ButtonsDown |= MK_XBUTTON1;
-            Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
-            co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
-        }
-        if(mi->mouseData & XBUTTON2)
-        {
-            SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON2, TRUE);
-            CurInfo->ButtonsDown |= MK_XBUTTON2;
-            Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2);
-            co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
-        }
-    }
-    else if(mi->dwFlags & MOUSEEVENTF_XUP)
-    {
-        Msg.message = WM_XBUTTONUP;
-        if(mi->mouseData & XBUTTON1)
-        {
-            SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON1, FALSE);
-            CurInfo->ButtonsDown &= ~MK_XBUTTON1;
-            Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
-            co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
-        }
-        if(mi->mouseData & XBUTTON2)
-        {
-            SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON2, FALSE);
-            CurInfo->ButtonsDown &= ~MK_XBUTTON2;
-            Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2);
-            co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
-        }
-    }
-    if(mi->dwFlags & MOUSEEVENTF_WHEEL)
-    {
-        Msg.message = WM_MOUSEWHEEL;
-        Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, mi->mouseData);
-        co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
-    }
-
-    return TRUE;
-}
-
 BOOL FASTCALL
 UserAttachThreadInput(PTHREADINFO pti, PTHREADINFO ptiTo, BOOL fAttach)
 {
@@ -796,16 +420,16 @@ UserAttachThreadInput(PTHREADINFO pti, PTHREADINFO ptiTo, BOOL fAttach)
     if (pti == ptiTo) return FALSE;
 
     /* Do not attach to system threads or between different desktops. */
-    if ( pti->TIF_flags & TIF_DONTATTACHQUEUE ||
+    if (pti->TIF_flags & TIF_DONTATTACHQUEUE ||
             ptiTo->TIF_flags & TIF_DONTATTACHQUEUE ||
-            pti->rpdesk != ptiTo->rpdesk )
+            pti->rpdesk != ptiTo->rpdesk)
         return FALSE;
 
     /* If Attach set, allocate and link. */
-    if ( fAttach )
+    if (fAttach)
     {
         pai = ExAllocatePoolWithTag(PagedPool, sizeof(ATTACHINFO), USERTAG_ATTACHINFO);
-        if ( !pai ) return FALSE;
+        if (!pai) return FALSE;
 
         pai->paiNext = gpai;
         pai->pti1 = pti;
@@ -816,19 +440,19 @@ UserAttachThreadInput(PTHREADINFO pti, PTHREADINFO ptiTo, BOOL fAttach)
     {
         PATTACHINFO paiprev = NULL;
 
-        if ( !gpai ) return FALSE;
+        if (!gpai) return FALSE;
 
         pai = gpai;
 
         /* Search list and free if found or return false. */
         do
         {
-            if ( pai->pti2 == ptiTo && pai->pti1 == pti ) break;
+            if (pai->pti2 == ptiTo && pai->pti1 == pti) break;
             paiprev = pai;
             pai = pai->paiNext;
         } while (pai);
 
-        if ( !pai ) return FALSE;
+        if (!pai) return FALSE;
 
         if (paiprev) paiprev->paiNext = pai->paiNext;
 
@@ -838,6 +462,11 @@ UserAttachThreadInput(PTHREADINFO pti, PTHREADINFO ptiTo, BOOL fAttach)
     return TRUE;
 }
 
+/*
+ * NtUserSendInput
+ *
+ * Generates input events from software
+ */
 UINT
 APIENTRY
 NtUserSendInput(
@@ -846,8 +475,7 @@ NtUserSendInput(
     INT cbSize)
 {
     PTHREADINFO pti;
-    UINT cnt;
-    DECLARE_RETURN(UINT);
+    UINT uRet = 0;
 
     TRACE("Enter NtUserSendInput\n");
     UserEnterExclusive();
@@ -857,13 +485,13 @@ NtUserSendInput(
 
     if (!pti->rpdesk)
     {
-        RETURN( 0);
+        goto cleanup;
     }
 
     if (!nInputs || !pInput || cbSize != sizeof(INPUT))
     {
         EngSetLastError(ERROR_INVALID_PARAMETER);
-        RETURN( 0);
+        goto cleanup;
     }
 
     /*
@@ -871,13 +499,12 @@ NtUserSendInput(
      *         e.g. services running in the service window station cannot block input
      */
     if (!ThreadHasInputAccess(pti) ||
-            !IntIsActiveDesktop(pti->rpdesk))
+        !IntIsActiveDesktop(pti->rpdesk))
     {
         EngSetLastError(ERROR_ACCESS_DENIED);
-        RETURN( 0);
+        goto cleanup;
     }
 
-    cnt = 0;
     while (nInputs--)
     {
         INPUT SafeInput;
@@ -887,20 +514,21 @@ NtUserSendInput(
         if (!NT_SUCCESS(Status))
         {
             SetLastNtError(Status);
-            RETURN( cnt);
+            goto cleanup;
         }
 
         switch (SafeInput.type)
         {
             case INPUT_MOUSE:
                 if (IntMouseInput(&SafeInput.mi, TRUE))
-                    cnt++;
+                    uRet++;
                 break;
             case INPUT_KEYBOARD:
                 if (UserSendKeyboardInput(&SafeInput.ki, TRUE))
-                    cnt++;
+                    uRet++;
                 break;
             case INPUT_HARDWARE:
+                FIXME("INPUT_HARDWARE not supported!");
                 break;
             default:
                 ERR("SendInput(): Invalid input type: 0x%x\n", SafeInput.type);
@@ -908,276 +536,10 @@ NtUserSendInput(
         }
     }
 
-    RETURN( cnt);
-
-CLEANUP:
-    TRACE("Leave NtUserSendInput, ret=%i\n", _ret_);
-    UserLeave();
-    END_CLEANUP;
-}
-
-BOOL
-FASTCALL
-IntQueryTrackMouseEvent(
-    LPTRACKMOUSEEVENT lpEventTrack)
-{
-    PDESKTOP pDesk;
-    PTHREADINFO pti;
-
-    pti = PsGetCurrentThreadWin32Thread();
-    pDesk = pti->rpdesk;
-
-    /* Always cleared with size set and return true. */
-    RtlZeroMemory(lpEventTrack , sizeof(TRACKMOUSEEVENT));
-    lpEventTrack->cbSize = sizeof(TRACKMOUSEEVENT);
-
-    if ( pDesk->dwDTFlags & (DF_TME_LEAVE | DF_TME_HOVER) &&
-            pDesk->spwndTrack &&
-            pti->MessageQueue == pDesk->spwndTrack->head.pti->MessageQueue )
-    {
-        if ( pDesk->htEx != HTCLIENT )
-            lpEventTrack->dwFlags |= TME_NONCLIENT;
-
-        if ( pDesk->dwDTFlags & DF_TME_LEAVE )
-            lpEventTrack->dwFlags |= TME_LEAVE;
-
-        if ( pDesk->dwDTFlags & DF_TME_HOVER )
-        {
-            lpEventTrack->dwFlags |= TME_HOVER;
-            lpEventTrack->dwHoverTime = pDesk->dwMouseHoverTime;
-        }
-        lpEventTrack->hwndTrack = UserHMGetHandle(pDesk->spwndTrack);
-    }
-    return TRUE;
-}
-
-BOOL
-FASTCALL
-IntTrackMouseEvent(
-    LPTRACKMOUSEEVENT lpEventTrack)
-{
-    PDESKTOP pDesk;
-    PTHREADINFO pti;
-    PWND pWnd;
-    POINT point;
-
-    pti = PsGetCurrentThreadWin32Thread();
-    pDesk = pti->rpdesk;
-
-    if (!(pWnd = UserGetWindowObject(lpEventTrack->hwndTrack)))
-        return FALSE;
-
-    /* Tracking spwndTrack same as pWnd */
-    if ( lpEventTrack->dwFlags & TME_CANCEL ) // Canceled mode.
-    {
-        if ( lpEventTrack->dwFlags & TME_LEAVE )
-            pDesk->dwDTFlags &= ~DF_TME_LEAVE;
-
-        if ( lpEventTrack->dwFlags & TME_HOVER )
-        {
-            if ( pDesk->dwDTFlags & DF_TME_HOVER )
-            {   // Kill hover timer.
-                IntKillTimer(pWnd, ID_EVENT_SYSTIMER_MOUSEHOVER, TRUE);
-                pDesk->dwDTFlags &= ~DF_TME_HOVER;
-            }
-        }
-    }
-    else // Not Canceled.
-    {
-       pDesk->spwndTrack = pWnd;
-        if ( lpEventTrack->dwFlags & TME_LEAVE )
-            pDesk->dwDTFlags |= DF_TME_LEAVE;
-
-        if ( lpEventTrack->dwFlags & TME_HOVER )
-        {
-            pDesk->dwDTFlags |= DF_TME_HOVER;
-
-            if ( !lpEventTrack->dwHoverTime || lpEventTrack->dwHoverTime == HOVER_DEFAULT )
-                pDesk->dwMouseHoverTime = gspv.iMouseHoverTime; // use the system default hover time-out.
-            else
-                pDesk->dwMouseHoverTime = lpEventTrack->dwHoverTime;
-            // Start timer for the hover period.
-            IntSetTimer( pWnd, ID_EVENT_SYSTIMER_MOUSEHOVER, pDesk->dwMouseHoverTime, SystemTimerProc, TMRF_SYSTEM);
-            // Get windows thread message points.
-            point = pWnd->head.pti->ptLast;
-            // Set desktop mouse hover from the system default hover rectangle.
-            RECTL_vSetRect(&pDesk->rcMouseHover,
-                           point.x - gspv.iMouseHoverWidth  / 2,
-                           point.y - gspv.iMouseHoverHeight / 2,
-                           point.x + gspv.iMouseHoverWidth  / 2,
-                           point.y + gspv.iMouseHoverHeight / 2);
-        }
-    }
-    return TRUE;
-}
-
-BOOL
-APIENTRY
-NtUserTrackMouseEvent(
-    LPTRACKMOUSEEVENT lpEventTrack)
-{
-    TRACKMOUSEEVENT saveTME;
-    BOOL Ret = FALSE;
-
-    TRACE("Enter NtUserTrackMouseEvent\n");
-    UserEnterExclusive();
-
-    _SEH2_TRY
-    {
-        ProbeForRead(lpEventTrack, sizeof(TRACKMOUSEEVENT), 1);
-        RtlCopyMemory(&saveTME, lpEventTrack, sizeof(TRACKMOUSEEVENT));
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        SetLastNtError(_SEH2_GetExceptionCode());
-        _SEH2_YIELD(goto Exit;)
-    }
-    _SEH2_END;
-
-    if ( saveTME.cbSize != sizeof(TRACKMOUSEEVENT) )
-    {
-        EngSetLastError(ERROR_INVALID_PARAMETER);
-        goto Exit;
-    }
-
-    if (saveTME.dwFlags & ~(TME_CANCEL | TME_QUERY | TME_NONCLIENT | TME_LEAVE | TME_HOVER) )
-    {
-        EngSetLastError(ERROR_INVALID_FLAGS);
-        goto Exit;
-    }
-
-    if ( saveTME.dwFlags & TME_QUERY )
-    {
-        Ret = IntQueryTrackMouseEvent(&saveTME);
-        _SEH2_TRY
-        {
-            ProbeForWrite(lpEventTrack, sizeof(TRACKMOUSEEVENT), 1);
-            RtlCopyMemory(lpEventTrack, &saveTME, sizeof(TRACKMOUSEEVENT));
-        }
-        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-        {
-            SetLastNtError(_SEH2_GetExceptionCode());
-            Ret = FALSE;
-        }
-        _SEH2_END;
-    }
-    else
-    {
-        Ret = IntTrackMouseEvent(&saveTME);
-    }
-
-Exit:
-    TRACE("Leave NtUserTrackMouseEvent, ret=%i\n", Ret);
-    UserLeave();
-    return Ret;
-}
-
-extern MOUSEMOVEPOINT MouseHistoryOfMoves[];
-extern INT gcur_count;
-
-DWORD
-APIENTRY
-NtUserGetMouseMovePointsEx(
-    UINT cbSize,
-    LPMOUSEMOVEPOINT lpptIn,
-    LPMOUSEMOVEPOINT lpptOut,
-    int nBufPoints,
-    DWORD resolution)
-{
-    MOUSEMOVEPOINT Safeppt;
-    //BOOL Hit;
-    INT Count = -1;
-    DECLARE_RETURN(DWORD);
-
-    TRACE("Enter NtUserGetMouseMovePointsEx\n");
-    UserEnterExclusive();
-
-    if ((cbSize != sizeof(MOUSEMOVEPOINT)) || (nBufPoints < 0) || (nBufPoints > 64))
-    {
-        EngSetLastError(ERROR_INVALID_PARAMETER);
-        RETURN( -1);
-    }
-
-    if (!lpptIn || (!lpptOut && nBufPoints))
-    {
-        EngSetLastError(ERROR_NOACCESS);
-        RETURN( -1);
-    }
-
-    _SEH2_TRY
-    {
-        ProbeForRead( lpptIn, cbSize, 1);
-        RtlCopyMemory(&Safeppt, lpptIn, cbSize);
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        SetLastNtError(_SEH2_GetExceptionCode());
-        _SEH2_YIELD(RETURN( -1))
-    }
-    _SEH2_END;
-
-    // http://msdn.microsoft.com/en-us/library/ms646259(v=vs.85).aspx
-    // This explains the math issues in transforming points.
-    Count = gcur_count; // FIFO is forward so retrieve backward.
-    //Hit = FALSE;
-    do
-    {
-        if (Safeppt.x == 0 && Safeppt.y == 0)
-            break; // No test.
-        // Finds the point, it returns the last nBufPoints prior to and including the supplied point.
-        if (MouseHistoryOfMoves[Count].x == Safeppt.x && MouseHistoryOfMoves[Count].y == Safeppt.y)
-        {
-            if ( Safeppt.time ) // Now test time and it seems to be absolute.
-            {
-                if (Safeppt.time == MouseHistoryOfMoves[Count].time)
-                {
-                    //Hit = TRUE;
-                    break;
-                }
-                else
-                {
-                    if (--Count < 0) Count = 63;
-                    continue;
-                }
-            }
-            //Hit = TRUE;
-            break;
-        }
-        if (--Count < 0) Count = 63;
-    }
-    while ( Count != gcur_count);
-
-    switch(resolution)
-    {
-        case GMMP_USE_DISPLAY_POINTS:
-            if (nBufPoints)
-            {
-                _SEH2_TRY
-                {
-                    ProbeForWrite(lpptOut, cbSize, 1);
-                }
-                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-                {
-                    SetLastNtError(_SEH2_GetExceptionCode());
-                    _SEH2_YIELD(RETURN( -1))
-                }
-                _SEH2_END;
-            }
-            Count = nBufPoints;
-            break;
-        case GMMP_USE_HIGH_RESOLUTION_POINTS:
-            break;
-        default:
-            EngSetLastError(ERROR_POINT_NOT_FOUND);
-            RETURN( -1);
-    }
-
-    RETURN( Count);
-
-CLEANUP:
-    TRACE("Leave NtUserGetMouseMovePointsEx, ret=%i\n", _ret_);
+cleanup:
+    TRACE("Leave NtUserSendInput, ret=%i\n", uRet);
     UserLeave();
-    END_CLEANUP;
+    return uRet;
 }
 
 /* EOF */