/*
* 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)
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)
{
return LastInputTick;
}
+/*
+ * DoTheScreenSaver
+ *
+ * Check if scrensaver should be started and sends message to SAS window
+ */
VOID FASTCALL
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);
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)
{
switch (Type)
{
- case 0: KeyboardThreadMain(NULL); break;
- case 1: MouseThreadMain(NULL); break;
+ case 0: RawInputThreadMain(); break;
default: ERR("Wrong type: %x\n", 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
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)
{
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;
{
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;
return TRUE;
}
+/*
+ * NtUserSendInput
+ *
+ * Generates input events from software
+ */
UINT
APIENTRY
NtUserSendInput(
INT cbSize)
{
PTHREADINFO pti;
- UINT cnt;
- DECLARE_RETURN(UINT);
+ UINT uRet = 0;
TRACE("Enter NtUserSendInput\n");
UserEnterExclusive();
if (!pti->rpdesk)
{
- RETURN( 0);
+ goto cleanup;
}
if (!nInputs || !pInput || cbSize != sizeof(INPUT))
{
EngSetLastError(ERROR_INVALID_PARAMETER);
- RETURN( 0);
+ goto cleanup;
}
/*
* 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;
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);
}
}
- 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 */