ReactOS 0.4.17-dev-1321-g5c122a9
input.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: General input functions
5 * FILE: win32ss/user/ntuser/input.c
6 * PROGRAMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Rafal Harabien (rafalh@reactos.org)
8 */
9
10#include <win32k.h>
12
13/* LastRITEventTickCount update cycle has been adjusted from 60s to 1s since NT6 */
14#if (NTDDI_VERSION < NTDDI_VISTA)
15#define LAST_RIT_EVENT_UPDATE_INTERVAL 60000UL
16#else
17#define LAST_RIT_EVENT_UPDATE_INTERVAL 1000UL
18#endif
19
20static
26
27/* GLOBALS *******************************************************************/
28
36
39
40/* FUNCTIONS *****************************************************************/
41
42/*
43 * IntLastInputTick
44 *
45 * Updates or gets last input tick count
46 */
47static DWORD FASTCALL
49{
50 if (bUpdate)
51 {
53 if (gpsi)
54 {
55 gpsi->dwLastRITEventTickCount = LastInputTick;
56 if (gpsi->dwLastRITEventTickCount - gpsi->dwLastSystemRITEventTickCountUpdate >
58 {
59 SharedUserData->LastSystemRITEventTickCount = LastInputTick;
60 gpsi->dwLastSystemRITEventTickCountUpdate = LastInputTick;
61 }
62 }
63 }
64 return LastInputTick;
65}
66
67/*
68 * DoTheScreenSaver
69 *
70 * Check if screensaver should be started and sends message to SAS window
71 */
74{
75 DWORD Test, TO;
76
77 if (gspv.iScrSaverTimeout > 0) // Zero means Off.
78 {
81 TO = 1000 * gspv.iScrSaverTimeout;
82 if (Test > TO)
83 {
84 TRACE("Screensaver Message Start! Tick %lu Timeout %d \n", Test, gspv.iScrSaverTimeout);
85
86 if (ppiScrnSaver) // We are or we are not the screensaver, prevent reentry...
87 {
88 if (!(ppiScrnSaver->W32PF_flags & W32PF_IDLESCREENSAVER))
89 {
90 ppiScrnSaver->W32PF_flags |= W32PF_IDLESCREENSAVER;
91 ERR("Screensaver is Idle\n");
92 }
93 }
94 else
95 {
97 if (ForegroundQueue && ForegroundQueue->spwndActive)
99 else
101 }
102 }
103 }
104}
105
106/*
107 * CreateInputDevice
108 *
109 * Create input device structure
110 *
111 */
112static
117{
119
121 if (!DeviceInfo)
122 {
123 ERR("Failed to allocate memory for INPUT_DEVICE_INFO\n");
124 return NULL;
125 }
126
128 DeviceInfo->DeviceType = DeviceType;
129 DeviceInfo->DeviceName.Buffer = (PWCH)(DeviceInfo + 1);
130 DeviceInfo->DeviceName.MaximumLength = DeviceName->Length + sizeof(UNICODE_NULL);
132
134 DeviceInfo->pNextDeviceInfo = gpInputDeviceInfo;
137
139 return DeviceInfo;
140}
141
142/*
143 * OpenInputDevice
144 *
145 * Opens input device for asynchronous access
146 */
147static
151{
155
157 &DeviceInfo->DeviceName,
159 NULL,
160 NULL);
161
162 Status = ZwOpenFile(&DeviceInfo->Handle,
165 &Iosb,
166 0,
167 0);
168 if (!NT_SUCCESS(Status))
169 {
170 ERR("ZwOpenFile('%wZ') failed with status 0x%08x\n", &DeviceInfo->DeviceName, Status);
171 return Status;
172 }
173
174 if (DeviceInfo->DeviceType == RIM_TYPEKEYBOARD)
175 {
177 NULL,
178 NULL,
179 NULL,
180 &DeviceInfo->Iosb,
182 NULL, 0,
183 &DeviceInfo->Keyboard.Attributes,
184 sizeof(DeviceInfo->Keyboard.Attributes));
185 if (!NT_SUCCESS(Status))
186 {
187 ERR("ZwDeviceIoControlFile('%wZ', IOCTL_KEYBOARD_QUERY_ATTRIBUTES) failed with status 0x%08x\n", &DeviceInfo->DeviceName, Status);
188 }
189 }
190 else if (DeviceInfo->DeviceType == RIM_TYPEMOUSE)
191 {
193 NULL,
194 NULL,
195 NULL,
196 &DeviceInfo->Iosb,
198 NULL, 0,
199 &DeviceInfo->Mouse.Attributes,
200 sizeof(DeviceInfo->Mouse.Attributes));
201 if (!NT_SUCCESS(Status))
202 {
203 ERR("ZwDeviceIoControlFile('%wZ', IOCTL_MOUSE_QUERY_ATTRIBUTES) failed with status 0x%08x\n", &DeviceInfo->DeviceName, Status);
204 }
205 }
206
207 return STATUS_SUCCESS;
208}
209
210static
211VOID
214{
215 ASSERT(DeviceInfo->Handle);
216 (void)ZwCancelIoFile(DeviceInfo->Handle, &DeviceInfo->Iosb);
218
219 if (DeviceInfo->Handle == ghKeyboardDevice)
221}
222
223static
224VOID
227{
231
232 ByteOffset.QuadPart = (LONGLONG)0;
233
234 if (DeviceInfo->DeviceType == RIM_TYPEKEYBOARD)
235 {
236 Buffer = &DeviceInfo->Keyboard.Data,
237 BufferSize = sizeof(DeviceInfo->Keyboard.Data);
238 }
239 else if (DeviceInfo->DeviceType == RIM_TYPEMOUSE)
240 {
241 Buffer = &DeviceInfo->Mouse.Data,
242 BufferSize = sizeof(DeviceInfo->Mouse.Data);
243 }
244 else
245 return;
246
247 DeviceInfo->Status = ZwReadFile(
248 DeviceInfo->Handle,
249 NULL,
252 &DeviceInfo->Iosb,
253 Buffer,
255 &ByteOffset,
256 NULL);
257}
258
259static
265{
267
268 if (DeviceInfo->Handle && NT_SUCCESS(IoStatusBlock->Status))
269 {
270 if (DeviceInfo->DeviceType == RIM_TYPEKEYBOARD)
271 {
272 TRACE("KeyboardEvent: %s %04x\n",
273 (DeviceInfo->Keyboard.Data.Flags & KEY_BREAK) ? "up" : "down",
274 DeviceInfo->Keyboard.Data.MakeCode);
275
276 /* Set LastInputTick */
278
279 /* Process data */
282 UserLeave();
283 }
284 else if (DeviceInfo->DeviceType == RIM_TYPEMOUSE)
285 {
286 TRACE("MouseEvent\n");
287
288 /* Set LastInputTick */
290
291 /* Process data */
294 UserLeave();
295 }
296 }
297
299}
300
301static
302VOID
304 VOID)
305{
308 DWORD NumberOfMice = 0;
309 DWORD MaxNumberOfButtons = 0;
310 BOOL HasMouseWheel = FALSE;
311#if (_WIN32_WINNT >= 0x0600)
312 BOOL HasHorizontalMouseWheel = FALSE;
313#endif
314 DWORD MaxFunctionKeys = 0;
315
317 for (DeviceInfo = gpInputDeviceInfo; DeviceInfo; DeviceInfo = DeviceInfo->pNextDeviceInfo)
318 {
319 if (!DeviceInfo->Handle)
320 {
322 if (NT_SUCCESS(Status))
323 {
324 if (DeviceInfo->DeviceType == RIM_TYPEKEYBOARD)
325 {
326 TRACE("Keyboard connected!\n");
327 if (!ghKeyboardDevice)
328 {
329 // Get and load keyboard attributes.
332 // Register the Window hotkey.
334 // Register the Window Snap hotkey.
339 // Register the debug hotkeys.
341 UserLeave();
342 }
343 }
344 else if (DeviceInfo->DeviceType == RIM_TYPEMOUSE)
345 {
346 TRACE("Mouse connected!\n");
347 }
349 }
350 }
351
352 if (DeviceInfo->DeviceType == RIM_TYPEKEYBOARD)
353 {
354 if (DeviceInfo->Keyboard.Attributes.KeyboardIdentifier.Type == 4 /* Enhanced 101- or 102-key keyboard */ ||
355 DeviceInfo->Keyboard.Attributes.KeyboardIdentifier.Type == 7 /* Japanese keyboard */ ||
356 DeviceInfo->Keyboard.Attributes.KeyboardIdentifier.Type == 8 /* Korean keyboard */)
357 {
358 DWORD FunctionKeys = DeviceInfo->Keyboard.Attributes.NumberOfFunctionKeys;
359 /* Keep current keyboard description */
360 gKeyboardInfo = DeviceInfo->Keyboard.Attributes;
361 if (FunctionKeys > MaxFunctionKeys)
362 MaxFunctionKeys = FunctionKeys;
363 }
364 }
365 else if (DeviceInfo->DeviceType == RIM_TYPEMOUSE)
366 {
367 DWORD MouseIdentifier = DeviceInfo->Mouse.Attributes.MouseIdentifier & ~HORIZONTAL_WHEEL_PRESENT;
368 DWORD NumberOfButtons = DeviceInfo->Mouse.Attributes.NumberOfButtons;
369
370 NumberOfMice++;
371 if (NumberOfButtons > MaxNumberOfButtons)
372 MaxNumberOfButtons = NumberOfButtons;
373 HasMouseWheel |= MouseIdentifier == WHEELMOUSE_I8042_HARDWARE
374 || MouseIdentifier == WHEELMOUSE_SERIAL_HARDWARE
375 || MouseIdentifier == WHEELMOUSE_HID_HARDWARE;
376#if (_WIN32_WINNT >= 0x0600)
377 HasHorizontalMouseWheel |= DeviceInfo->Mouse.Attributes.MouseIdentifier & HORIZONTAL_WHEEL_PRESENT;
378#endif
379 }
380 }
382
383 /* Update metrics */
384 gpsi->aiSysMet[SM_MOUSEPRESENT] = NumberOfMice > 0 ? 1 : 0;
385 gpsi->aiSysMet[SM_CMOUSEBUTTONS] = MaxNumberOfButtons;
386 gpsi->aiSysMet[SM_MOUSEWHEELPRESENT] = HasMouseWheel ? 1 : 0;
387#if (_WIN32_WINNT >= 0x0600)
388 gpsi->aiSysMet[SM_MOUSEHORIZONTALWHEELPRESENT] = HasHorizontalMouseWheel ? 1 : 0;
389#endif
390 /* FIXME: show/hide cursor depending of mouse presence */
391 TRACE("Mouse present %u, buttons %u, wheel %u\n",
392 gpsi->aiSysMet[SM_MOUSEPRESENT],
393 gpsi->aiSysMet[SM_CMOUSEBUTTONS],
394 gpsi->aiSysMet[SM_MOUSEWHEELPRESENT]);
395
396 gKeyboardInfo.NumberOfFunctionKeys = MaxFunctionKeys;
397 TRACE("Keyboard type %u, subtype %u and number of func keys %u\n",
401}
402
403/*
404 * RawInputThreadMain
405 *
406 * Reads data from input devices and supports win32 timers
407 */
410{
413 //LARGE_INTEGER WaitTimeout;
414 PVOID WaitObjects[3], pSignaledObject = NULL;
417 HWINSTA hWinSta;
420 UNICODE_STRING LegacyMouseName = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");
421 UNICODE_STRING LegacyKeyboardName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass0");
422
426
427 //WaitTimeout.QuadPart = (LONGLONG)(-10000000);
428
432
433 TRACE("Raw Input Thread %p\n", ptiRawInput);
434
437
439 0,
440 NULL,
443 UserMode,
444 (PHANDLE)&hWinSta);
445 if (NT_SUCCESS(Status))
446 {
448 }
449 else
450 {
451 ASSERT(FALSE);
452 /* Failed to open the interactive winsta! What now? */
453 }
454
459
460 Mouse = CreateInputDevice(RIM_TYPEMOUSE, &LegacyMouseName);
461 ASSERT(Mouse);
462 Keyboard = CreateInputDevice(RIM_TYPEKEYBOARD, &LegacyKeyboardName);
464
467 UserLeave();
468
470 ghKeyboardDevice = Keyboard->Handle;
471
473 for (;;)
474 {
475 /* Reset WaitHandles array */
476 WaitObjects[0] = ShutdownEvent;
477 WaitObjects[1] = MasterTimer;
478 WaitObjects[2] = gDeviceListChangedEvent;
479
481 WaitObjects,
482 WaitAny,
485 TRUE,
486 NULL,//&WaitTimeout,
488
489 if ((Status >= STATUS_WAIT_0) &&
490 (Status < (STATUS_WAIT_0 + RTL_NUMBER_OF(WaitObjects))))
491 {
492 /* Some device has finished reading */
493 pSignaledObject = WaitObjects[Status - STATUS_WAIT_0];
494
495 if (pSignaledObject == gDeviceListChangedEvent)
496 {
498 }
499 else if (pSignaledObject == MasterTimer)
500 {
502 }
503 else if (pSignaledObject == ShutdownEvent)
504 {
505 break;
506 }
507 else ASSERT(FALSE);
508 }
509 }
510
512 while (gpInputDeviceInfo)
513 {
515 gpInputDeviceInfo = DeviceInfo->pNextDeviceInfo;
518 }
521
525
526 ERR("Raw Input Thread Exit!\n");
527}
528
529/*
530 * InitInputImpl
531 *
532 * Inits input implementation
533 */
534CODE_SEG("INIT")
536NTAPI
538{
540 if (!MasterTimer)
541 {
542 ERR("Failed to allocate memory\n");
543 ASSERT(FALSE);
544 return STATUS_UNSUCCESSFUL;
545 }
547
548 return STATUS_SUCCESS;
549}
550
553{
554 PTHREADINFO OldBlock;
555 ASSERT(pti);
556
557 if(!pti->rpdesk || ((pti->TIF_flags & TIF_INCLEANUP) && BlockIt))
558 {
559 /*
560 * Fail blocking if exiting the thread
561 */
562
563 return FALSE;
564 }
565
566 /*
567 * FIXME: Check access rights of the window station
568 * e.g. services running in the service window station cannot block input
569 */
570 if(!ThreadHasInputAccess(pti) ||
572 {
574 return FALSE;
575 }
576
577 ASSERT(pti->rpdesk);
578 OldBlock = pti->rpdesk->BlockInputThread;
579 if(OldBlock)
580 {
581 if(OldBlock != pti)
582 {
584 return FALSE;
585 }
586 pti->rpdesk->BlockInputThread = (BlockIt ? pti : NULL);
587 return OldBlock == NULL;
588 }
589
590 pti->rpdesk->BlockInputThread = (BlockIt ? pti : NULL);
591 return OldBlock == NULL;
592}
593
594BOOL
597 BOOL BlockIt)
598{
599 BOOL ret;
600
601 TRACE("Enter NtUserBlockInput\n");
603
605
606 UserLeave();
607 TRACE("Leave NtUserBlockInput, ret=%i\n", ret);
608
609 return ret;
610}
611
612BOOL
615{
617 PATTACHINFO pai;
618 BOOL Ret = TRUE;
619 PTHREADINFO ptiFrom = NULL, ptiTo = NULL;
620
621 do
622 {
623 if (!gpai) return TRUE;
624
625 pai = gpai; // Bottom of the list.
626
627 do
628 {
629 if (pai->pti2 == pti)
630 {
631 ptiFrom = pai->pti1;
632 ptiTo = pti;
633 break;
634 }
635 if (pai->pti1 == pti)
636 {
637 ptiFrom = pti;
638 ptiTo = pai->pti2;
639 break;
640 }
641 pai = pai->paiNext;
642
643 } while (pai);
644
645 if (!pai && !ptiFrom && !ptiTo) break;
646
647 Status = UserAttachThreadInput(ptiFrom, ptiTo, FALSE);
648 if (!NT_SUCCESS(Status)) Ret = FALSE;
649
650 } while (Ret);
651
652 return Ret;
653}
654
657{
658 MSG msg;
659 PATTACHINFO pai;
660 PCURICON_OBJECT CurIcon;
661
662 /* Can not be the same thread. */
663 if (ptiFrom == ptiTo) return STATUS_INVALID_PARAMETER;
664
665 /* Do not attach to system threads or between different desktops. */
666 if (ptiFrom->TIF_flags & TIF_DONTATTACHQUEUE ||
668 ptiFrom->rpdesk != ptiTo->rpdesk)
670
671 /* MSDN Note:
672 Keyboard and mouse events received by both threads are processed by the thread specified by the idAttachTo.
673 */
674
675 /* If Attach set, allocate and link. */
676 if (fAttach)
677 {
679 if (!pai) return STATUS_NO_MEMORY;
680
681 pai->paiNext = gpai;
682 pai->pti1 = ptiFrom;
683 pai->pti2 = ptiTo;
684 gpai = pai;
685 paiCount++;
686 ERR("Attach Allocated! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
687
688 if (ptiTo->MessageQueue != ptiFrom->MessageQueue)
689 {
690
691 ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
692
693 if (ptiFrom->MessageQueue == gpqForeground)
694 {
695 ERR("ptiFrom is Foreground\n");
696 ptiTo->MessageQueue->spwndActive = ptiFrom->MessageQueue->spwndActive;
697 ptiTo->MessageQueue->spwndFocus = ptiFrom->MessageQueue->spwndFocus;
698 ptiTo->MessageQueue->spwndCapture = ptiFrom->MessageQueue->spwndCapture;
699 ptiTo->MessageQueue->QF_flags ^= ((ptiTo->MessageQueue->QF_flags ^ ptiFrom->MessageQueue->QF_flags) & QF_CAPTURELOCKED);
700 RtlCopyMemory(&ptiTo->MessageQueue->CaretInfo,
701 &ptiFrom->MessageQueue->CaretInfo,
702 sizeof(ptiTo->MessageQueue->CaretInfo));
705 gptiForeground = ptiTo;
706 }
707 else
708 {
709 ERR("ptiFrom NOT Foreground\n");
710 if ( ptiTo->MessageQueue->spwndActive == 0 )
711 ptiTo->MessageQueue->spwndActive = ptiFrom->MessageQueue->spwndActive;
712 if ( ptiTo->MessageQueue->spwndFocus == 0 )
713 ptiTo->MessageQueue->spwndFocus = ptiFrom->MessageQueue->spwndFocus;
714 }
715
716 CurIcon = ptiFrom->MessageQueue->CursorObject;
717
718 MsqDestroyMessageQueue(ptiFrom);
719
720 if (CurIcon)
721 {
722 // Could be global. Keep it above the water line!
723 UserReferenceObject(CurIcon);
724 }
725
726 if (CurIcon && UserObjectInDestroy(UserHMGetHandle(CurIcon)))
727 {
728 UserDereferenceObject(CurIcon);
729 CurIcon = NULL;
730 }
731
732 ptiFrom->MessageQueue = ptiTo->MessageQueue;
733
734 // Pass cursor From if To is null. Pass test_SetCursor parent_id == current pti ID.
735 if (CurIcon && ptiTo->MessageQueue->CursorObject == NULL)
736 {
737 ERR("ptiTo receiving ptiFrom Cursor\n");
738 ptiTo->MessageQueue->CursorObject = CurIcon;
739 }
740
741 ptiFrom->MessageQueue->cThreads++;
742 ERR("ptiTo S Share count %u\n", ptiFrom->MessageQueue->cThreads);
743
745 }
746 else
747 {
748 ERR("Attach Threads are already associated!\n");
749 }
750 }
751 else /* If clear, unlink and free it. */
752 {
753 BOOL Hit = FALSE;
754 PATTACHINFO *ppai;
755
756 if (!gpai) return STATUS_INVALID_PARAMETER;
757
758 /* Search list and free if found or return false. */
759 ppai = &gpai;
760 while (*ppai != NULL)
761 {
762 if ( (*ppai)->pti2 == ptiTo && (*ppai)->pti1 == ptiFrom )
763 {
764 pai = *ppai;
765 /* Remove it from the list */
766 *ppai = (*ppai)->paiNext;
768 paiCount--;
769 Hit = TRUE;
770 break;
771 }
772 ppai = &((*ppai)->paiNext);
773 }
774
775 if (!Hit) return STATUS_INVALID_PARAMETER;
776
777 ERR("Attach Free! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
778
779 if (ptiTo->MessageQueue == ptiFrom->MessageQueue)
780 {
781 PWND spwndActive = ptiTo->MessageQueue->spwndActive;
782 PWND spwndFocus = ptiTo->MessageQueue->spwndFocus;
783
784 if (gptiForeground == ptiFrom)
785 {
786 ERR("ptiTo is now pti FG.\n");
787 // MessageQueue foreground is set so switch threads.
788 gptiForeground = ptiTo;
789 }
790 ptiTo->MessageQueue->cThreads--;
791 ERR("ptiTo E Share count %u\n", ptiTo->MessageQueue->cThreads);
792 ASSERT(ptiTo->MessageQueue->cThreads >= 1);
793
795
796 ptiFrom->MessageQueue = MsqCreateMessageQueue(ptiFrom);
797
798 if (spwndActive)
799 {
800 if (spwndActive->head.pti == ptiFrom)
801 {
802 ptiFrom->MessageQueue->spwndActive = spwndActive;
803 ptiTo->MessageQueue->spwndActive = 0;
804 }
805 }
806 if (spwndFocus)
807 {
808 if (spwndFocus->head.pti == ptiFrom)
809 {
810 ptiFrom->MessageQueue->spwndFocus = spwndFocus;
811 ptiTo->MessageQueue->spwndFocus = 0;
812 }
813 }
814 ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
815 }
816 else
817 {
818 ERR("Detaching Threads are not associated!\n");
819 }
820 }
821 /* Note that key state, which can be ascertained by calls to the GetKeyState
822 or GetKeyboardState function, is reset after a call to AttachThreadInput.
823 ATM which one?
824 */
825 RtlCopyMemory(ptiTo->MessageQueue->afKeyState, gafAsyncKeyState, sizeof(gafAsyncKeyState));
826
827 ptiTo->MessageQueue->msgDblClk.message = 0;
828
829 /* Generate mouse move message */
830 msg.message = WM_MOUSEMOVE;
831 msg.wParam = UserGetMouseButtonsState();
832 msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y);
833 msg.pt = gpsi->ptCursor;
835
836 return STATUS_SUCCESS;
837}
838
839BOOL
842 IN DWORD idAttach,
843 IN DWORD idAttachTo,
844 IN BOOL fAttach)
845{
847 PTHREADINFO pti, ptiTo;
848 BOOL Ret = FALSE;
849
851 TRACE("Enter NtUserAttachThreadInput %s\n",(fAttach ? "TRUE" : "FALSE" ));
852
853 pti = IntTID2PTI(UlongToHandle(idAttach));
854 ptiTo = IntTID2PTI(UlongToHandle(idAttachTo));
855
856 if ( !pti || !ptiTo )
857 {
858 TRACE("AttachThreadInput pti or ptiTo NULL.\n");
860 goto Exit;
861 }
862
863 Status = UserAttachThreadInput( pti, ptiTo, fAttach);
864 if (!NT_SUCCESS(Status))
865 {
866 TRACE("AttachThreadInput Error Status 0x%x. \n",Status);
868 }
869 else Ret = TRUE;
870
871Exit:
872 TRACE("Leave NtUserAttachThreadInput, ret=%d\n",Ret);
873 UserLeave();
874 return Ret;
875}
876
877/*
878 * NtUserSendInput
879 *
880 * Generates input events from software
881 */
882UINT
885 UINT nInputs,
886 LPINPUT pInput,
887 INT cbSize)
888{
889 PTHREADINFO pti;
890 UINT uRet = 0;
891
892 TRACE("Enter NtUserSendInput\n");
894
896 ASSERT(pti);
897
898 if (!pti->rpdesk)
899 {
900 goto cleanup;
901 }
902
903 if (!nInputs || !pInput || cbSize != sizeof(INPUT))
904 {
906 goto cleanup;
907 }
908
909 /*
910 * FIXME: Check access rights of the window station
911 * e.g. services running in the service window station cannot block input
912 */
913 if (!ThreadHasInputAccess(pti) ||
915 {
917 goto cleanup;
918 }
919
920 while (nInputs--)
921 {
922 INPUT SafeInput;
924
925 Status = MmCopyFromCaller(&SafeInput, pInput++, sizeof(INPUT));
926 if (!NT_SUCCESS(Status))
927 {
929 goto cleanup;
930 }
931
932 switch (SafeInput.type)
933 {
934 case INPUT_MOUSE:
935 if (UserSendMouseInput(&SafeInput.mi, TRUE))
936 uRet++;
937 break;
938 case INPUT_KEYBOARD:
939 if (UserSendKeyboardInput(&SafeInput.ki, TRUE))
940 uRet++;
941 break;
942 case INPUT_HARDWARE:
943 FIXME("INPUT_HARDWARE not supported!\n");
944 break;
945 default:
946 ERR("SendInput(): Invalid input type: 0x%x\n", SafeInput.type);
947 break;
948 }
949 }
950
951cleanup:
952 TRACE("Leave NtUserSendInput, ret=%u\n", uRet);
953 UserLeave();
954 return uRet;
955}
956
957/* EOF */
#define CODE_SEG(...)
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define msg(x)
Definition: auth_time.c:54
LONG NTSTATUS
Definition: precomp.h:26
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERR(fmt,...)
Definition: precomp.h:57
#define UlongToHandle(ul)
Definition: basetsd.h:91
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
static HANDLE ShutdownEvent
Definition: dcomlaunch.c:28
#define BufferSize
Definition: mmc.h:75
#define IntIsActiveDesktop(Desktop)
Definition: desktop.h:174
PTHREADINFO gptiForeground
Definition: focus.c:15
_In_ ULONG BufferSize
Definition: dispmprt.h:490
_In_ PIO_STATUS_BLOCK IoStatusBlock
Definition: dispmprt.h:608
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define APIENTRY
Definition: api.h:79
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
static void cleanup(void)
Definition: main.c:1335
return ret
Definition: mutex.c:147
#define L(x)
Definition: resources.c:13
return Iosb
Definition: create.c:4403
#define EngGetTickCount32()
Definition: eng.h:43
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define ExDeleteResourceLite(res)
Definition: env_spec_w32.h:647
#define NonPagedPool
Definition: env_spec_w32.h:307
#define PagedPool
Definition: env_spec_w32.h:308
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:732
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
PUSER_MESSAGE_QUEUE gpqForeground
Definition: focus.c:13
_Must_inspect_result_ _In_ WAIT_TYPE _In_opt_ PLARGE_INTEGER _In_opt_ PKWAIT_BLOCK WaitBlockArray
Definition: fsrtlfuncs.h:1153
Status
Definition: gdiplustypes.h:24
unsigned int UINT
Definition: sysinfo.c:13
#define IDHK_SNAP_LEFT
Definition: hotkey.h:20
#define IDHK_WINKEY
Definition: hotkey.h:16
#define IDHK_SNAP_UP
Definition: hotkey.h:22
#define IDHK_SNAP_DOWN
Definition: hotkey.h:23
#define IDHK_SNAP_RIGHT
Definition: hotkey.h:21
@ Keyboard
Definition: i8042prt.h:115
@ Mouse
Definition: i8042prt.h:116
PSERVERINFO gpsi
Definition: imm.c:18
#define TIF_INCLEANUP
Definition: ntuser.h:266
#define TIF_DONTATTACHQUEUE
Definition: ntuser.h:272
#define UserHMGetHandle(obj)
Definition: ntuser.h:233
#define PWND_BOTTOM
Definition: ntuser.h:773
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:806
#define TIF_SYSTEMTHREAD
Definition: ntuser.h:268
#define LOW_REALTIME_PRIORITY
DeviceType
Definition: mmdrv.h:42
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
VOID FASTCALL co_MsqInsertMouseMessage(MSG *Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook)
Definition: msgqueue.c:580
VOID FASTCALL MsqDestroyMessageQueue(_In_ PTHREADINFO pti)
Definition: msgqueue.c:2434
PUSER_MESSAGE_QUEUE FASTCALL MsqCreateMessageQueue(PTHREADINFO pti)
Definition: msgqueue.c:2407
#define QF_CAPTURELOCKED
Definition: msgqueue.h:114
#define IntReferenceMessageQueue(MsgQueue)
Definition: msgqueue.h:220
#define IntDereferenceMessageQueue(MsgQueue)
Definition: msgqueue.h:223
#define KernelMode
Definition: asm.h:38
#define UserMode
Definition: asm.h:39
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE _In_opt_ PVOID ApcContext
Definition: iofuncs.h:727
NTSYSAPI NTSTATUS NTAPI ZwCancelIoFile(_In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock)
NTSYSAPI NTSTATUS NTAPI ZwOpenFile(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _Out_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG ShareAccess, _In_ ULONG OpenOptions)
#define _In_
Definition: no_sal2.h:158
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define FASTCALL
Definition: nt_native.h:50
#define FILE_ALL_ACCESS
Definition: nt_native.h:651
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
WCHAR * PWCH
Definition: ntbasedef.h:422
#define UNICODE_NULL
#define KEY_BREAK
Definition: ntddkbd.h:71
#define IOCTL_KEYBOARD_QUERY_ATTRIBUTES
Definition: ntddkbd.h:32
#define WHEELMOUSE_I8042_HARDWARE
Definition: ntddmou.h:102
#define WHEELMOUSE_SERIAL_HARDWARE
Definition: ntddmou.h:103
#define IOCTL_MOUSE_QUERY_ATTRIBUTES
Definition: ntddmou.h:32
#define HORIZONTAL_WHEEL_PRESENT
Definition: ntddmou.h:106
#define WHEELMOUSE_HID_HARDWARE
Definition: ntddmou.h:105
@ SynchronizationEvent
@ WaitAny
NTSYSAPI NTSTATUS NTAPI ZwDeviceIoControlFile(IN HANDLE DeviceHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, IN PVOID UserApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer, IN ULONG InputBufferSize, OUT PVOID OutputBuffer, IN ULONG OutputBufferSize)
NTSTATUS NTAPI KeWaitForMultipleObjects(IN ULONG Count, IN PVOID Object[], IN WAIT_TYPE WaitType, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL, OUT PKWAIT_BLOCK WaitBlockArray OPTIONAL)
Definition: wait.c:599
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:829
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_WAIT_0
Definition: ntstatus.h:330
PWINSTATION_OBJECT InputWindowStation
Definition: winsta.c:21
HWND hwndSAS
Definition: winsta.c:24
BOOL FASTCALL UserSetProcessWindowStation(HWINSTA hWindowStation)
Definition: winsta.c:1614
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3411
NTSTATUS NTAPI ObOpenObjectByPointer(IN PVOID Object, IN ULONG HandleAttributes, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PHANDLE Handle)
Definition: obhandle.c:2769
#define MmCopyFromCaller
Definition: polytest.cpp:29
NTSTATUS NTAPI PoRequestShutdownEvent(OUT PVOID *Event)
Definition: poshtdwn.c:384
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define MAKELPARAM(l, h)
Definition: winuser.h:4116
#define SM_CMOUSEBUTTONS
Definition: winuser.h:1017
#define MOD_WIN
Definition: winuser.h:2686
#define SM_MOUSEPRESENT
Definition: winuser.h:991
#define SM_MOUSEWHEELPRESENT
Definition: winuser.h:1046
#define VK_UP
Definition: winuser.h:2261
#define WM_MOUSEMOVE
Definition: winuser.h:1803
#define VK_LEFT
Definition: winuser.h:2260
#define VK_RIGHT
Definition: winuser.h:2262
#define VK_DOWN
Definition: winuser.h:2263
#define SharedUserData
#define STATUS_SUCCESS
Definition: shellext.h:65
static void Exit(void)
Definition: sock.c:1330
#define TRACE(s)
Definition: solgame.cpp:4
WCHAR Data[ANYSIZE_ARRAY]
PTHREADINFO pti2
Definition: input.h:46
struct _ATTACHINFO * paiNext
Definition: input.h:44
PTHREADINFO pti1
Definition: input.h:45
KEYBOARD_ID KeyboardIdentifier
Definition: ntddkbd.h:124
USHORT NumberOfFunctionKeys
Definition: ntddkbd.h:126
UCHAR Subtype
Definition: ntddkbd.h:102
UCHAR Type
Definition: ntddkbd.h:101
INT iScrSaverTimeout
Definition: sysparams.h:110
struct _CLIENTINFO * pClientInfo
Definition: win32.h:95
INT iCursorLevel
Definition: win32.h:128
FLONG TIF_flags
Definition: win32.h:96
struct _DESKTOP * rpdesk
Definition: win32.h:93
struct _USER_MESSAGE_QUEUE * MessageQueue
Definition: win32.h:90
Definition: ntuser.h:698
THRDESKHEAD head
Definition: ntuser.h:699
KEYBDINPUT ki
Definition: winable.h:62
DWORD type
Definition: winable.h:59
MOUSEINPUT mi
Definition: winable.h:61
UINT32 cbSize
KPRIORITY NTAPI KeSetPriorityThread(IN PKTHREAD Thread, IN KPRIORITY Priority)
Definition: thrdobj.c:1300
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
unsigned char UCHAR
Definition: typedefs.h:53
int64_t LONGLONG
Definition: typedefs.h:68
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define WM_LOGONNOTIFY
Definition: undocuser.h:39
#define LN_START_SCREENSAVE
Definition: undocuser.h:122
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3281
#define W32PF_IDLESCREENSAVER
Definition: win32.h:27
POBJECT_TYPE ExWindowStationObjectType
Definition: win32k.c:21
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:30
VOID FASTCALL IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue)
Definition: desktop.c:1347
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1335
BOOL FASTCALL UserRegisterHotKey(PWND pWnd, int id, UINT fsModifiers, UINT vk)
Definition: hotkey.c:447
VOID FASTCALL SetDebugHotKeys(VOID)
Definition: hotkey.c:46
PATTACHINFO gpai
Definition: input.c:31
static PINPUT_DEVICE_INFO CreateInputDevice(_In_ UCHAR DeviceType, _In_ PUNICODE_STRING DeviceName)
Definition: input.c:114
BOOL APIENTRY NtUserBlockInput(BOOL BlockIt)
Definition: input.c:596
static NTSTATUS NTAPI OpenInputDevice(_In_ PINPUT_DEVICE_INFO DeviceInfo)
Definition: input.c:149
static PKEVENT gDeviceListChangedEvent
Definition: input.c:38
BOOL FASTCALL IsRemoveAttachThread(PTHREADINFO pti)
Definition: input.c:614
BOOL FASTCALL IntBlockInput(PTHREADINFO pti, BOOL BlockIt)
Definition: input.c:552
UINT APIENTRY NtUserSendInput(UINT nInputs, LPINPUT pInput, INT cbSize)
Definition: input.c:884
static VOID NTAPI RITReadApc(_In_ PVOID ApcContext, _In_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG Reserved)
Definition: input.c:261
VOID FASTCALL DoTheScreenSaver(VOID)
Definition: input.c:73
HANDLE ghKeyboardDevice
Definition: input.c:33
VOID NTAPI RawInputThreadMain(VOID)
Definition: input.c:409
INT paiCount
Definition: input.c:32
PTHREADINFO ptiRawInput
Definition: input.c:29
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
Definition: input.c:656
static VOID StartReadInputDevice(_In_ PINPUT_DEVICE_INFO DeviceInfo)
Definition: input.c:225
NTSTATUS NTAPI InitInputImpl(VOID)
Definition: input.c:537
static DWORD FASTCALL IntLastInputTick(BOOL bUpdate)
Definition: input.c:48
static DWORD LastInputTick
Definition: input.c:37
static VOID ProcessDeviceChanges(VOID)
Definition: input.c:303
PINPUT_DEVICE_INFO gpInputDeviceInfo
Definition: input.c:34
static VOID CloseInputDevice(_In_ PINPUT_DEVICE_INFO DeviceInfo)
Definition: input.c:212
BOOL APIENTRY NtUserAttachThreadInput(IN DWORD idAttach, IN DWORD idAttachTo, IN BOOL fAttach)
Definition: input.c:841
PKTIMER MasterTimer
Definition: input.c:30
PERESOURCE gpDeviceInfoListMutex
Definition: input.c:35
#define LAST_RIT_EVENT_UPDATE_INTERVAL
Definition: input.c:17
KEYBOARD_ATTRIBUTES gKeyboardInfo
Definition: keyboard.c:17
WORD FASTCALL UserGetMouseButtonsState(VOID)
Definition: mouse.c:22
BYTE gafAsyncKeyState[256 *2/8]
Definition: keyboard.c:13
BOOL NTAPI UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
Definition: keyboard.c:1314
#define ThreadHasInputAccess(W32Thread)
Definition: input.h:103
VOID NTAPI UserProcessKeyboardInput(PINPUT_DEVICE_INFO pDeviceInfo, PKEYBOARD_INPUT_DATA pKeyInput)
Definition: keyboard.c:1455
FORCEINLINE VOID ReleaseDeviceInfoListMutex(VOID)
Definition: input.h:165
VOID NTAPI UserProcessMouseInput(PINPUT_DEVICE_INFO pDeviceInfo, PMOUSE_INPUT_DATA pMouseInputData)
Definition: mouse.c:104
BOOL NTAPI UserSendMouseInput(MOUSEINPUT *pMouseInput, BOOL bInjected)
Definition: mouse.c:235
VOID NTAPI UserInitKeyboard(HANDLE hKeyboardDevice)
Definition: keyboard.c:178
FORCEINLINE VOID AcquireDeviceInfoListMutex(VOID)
Definition: input.h:157
PPROCESSINFO ppiScrnSaver
Definition: main.c:30
BOOL FASTCALL UserPostMessage(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1397
PTHREADINFO FASTCALL IntTID2PTI(HANDLE id)
Definition: misc.c:41
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:647
BOOL FASTCALL UserObjectInDestroy(HANDLE h)
Definition: object.c:707
VOID FASTCALL UserReferenceObject(PVOID obj)
Definition: object.c:754
SPIVALUES gspv
Definition: sysparams.c:17
#define USERTAG_SYSTEM
Definition: tags.h:282
#define USERTAG_ATTACHINFO
Definition: tags.h:197
#define USERTAG_PNP
Definition: tags.h:264
VOID FASTCALL ProcessTimers(VOID)
Definition: timer.c:452
VOID FASTCALL StartTheTimers(VOID)
Definition: timer.c:374
#define INPUT_HARDWARE
Definition: winable.h:11
#define INPUT_KEYBOARD
Definition: winable.h:10
#define INPUT_MOUSE
Definition: winable.h:9
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:21
_Reserved_ PVOID Reserved
Definition: winddi.h:3974
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define EVENT_INCREMENT
Definition: iotypes.h:597
@ UserRequest
Definition: ketypes.h:473
#define NT_ASSERT
Definition: rtlfuncs.h:3334