ReactOS  0.4.12-dev-918-g6c6e7b8
input.c File Reference
#include <win32k.h>
Include dependency graph for input.c:

Go to the source code of this file.

Functions

 DBG_DEFAULT_CHANNEL (UserInput)
 
static DWORD FASTCALL IntLastInputTick (BOOL bUpdate)
 
VOID FASTCALL DoTheScreenSaver (VOID)
 
static NTSTATUS NTAPI OpenInputDevice (PHANDLE pHandle, PFILE_OBJECT *ppObject, CONST WCHAR *pszDeviceName)
 
VOID NTAPI RawInputThreadMain (VOID)
 
INIT_FUNCTION NTSTATUS NTAPI InitInputImpl (VOID)
 
BOOL FASTCALL IntBlockInput (PTHREADINFO pti, BOOL BlockIt)
 
BOOL APIENTRY NtUserBlockInput (BOOL BlockIt)
 
BOOL FASTCALL IsRemoveAttachThread (PTHREADINFO pti)
 
NTSTATUS FASTCALL UserAttachThreadInput (PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
 
BOOL APIENTRY NtUserAttachThreadInput (IN DWORD idAttach, IN DWORD idAttachTo, IN BOOL fAttach)
 
UINT APIENTRY NtUserSendInput (UINT nInputs, LPINPUT pInput, INT cbSize)
 

Variables

PTHREADINFO ptiRawInput
 
PKTIMER MasterTimer = NULL
 
PATTACHINFO gpai = NULL
 
INT paiCount = 0
 
HANDLE ghKeyboardDevice = NULL
 
static DWORD LastInputTick = 0
 
static HANDLE ghMouseDevice
 

Function Documentation

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( UserInput  )

◆ DoTheScreenSaver()

VOID FASTCALL DoTheScreenSaver ( VOID  )

Definition at line 50 of file input.c.

51 {
52  LARGE_INTEGER TickCount;
53  DWORD Test, TO;
54 
55  if (gspv.iScrSaverTimeout > 0) // Zero means Off.
56  {
57  KeQueryTickCount(&TickCount);
58  Test = MsqCalculateMessageTime(&TickCount);
60  TO = 1000 * gspv.iScrSaverTimeout;
61  if (Test > TO)
62  {
63  TRACE("Screensaver Message Start! Tick %lu Timeout %d \n", Test, gspv.iScrSaverTimeout);
64 
65  if (ppiScrnSaver) // We are or we are not the screensaver, prevent reentry...
66  {
67  if (!(ppiScrnSaver->W32PF_flags & W32PF_IDLESCREENSAVER))
68  {
69  ppiScrnSaver->W32PF_flags |= W32PF_IDLESCREENSAVER;
70  ERR("Screensaver is Idle\n");
71  }
72  }
73  else
74  {
75  PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
76  if (ForegroundQueue && ForegroundQueue->spwndActive)
77  UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_START_SCREENSAVE, 1); // lParam 1 == Secure
78  else
80  }
81  }
82  }
83 }
BOOL FASTCALL UserPostMessage(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1189
PPROCESSINFO ppiScrnSaver
Definition: main.c:30
INT iScrSaverTimeout
Definition: sysparams.h:110
static __inline LONG MsqCalculateMessageTime(IN PLARGE_INTEGER TickCount)
Definition: msgqueue.h:253
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1271
#define LN_START_SCREENSAVE
Definition: undocuser.h:119
VOID NTAPI KeQueryTickCount(IN PLARGE_INTEGER TickCount)
Definition: clock.c:165
HWND hwndSAS
Definition: winsta.c:24
#define TRACE(s)
Definition: solgame.cpp:4
SPIVALUES gspv
Definition: sysparams.c:17
unsigned long DWORD
Definition: ntddk_ex.h:95
#define W32PF_IDLESCREENSAVER
Definition: win32.h:27
#define WM_LOGONNOTIFY
Definition: undocuser.h:37
#define ERR(fmt,...)
Definition: debug.h:109
static DWORD LastInputTick
Definition: input.c:21

Referenced by HungAppSysTimerProc().

◆ InitInputImpl()

INIT_FUNCTION NTSTATUS NTAPI InitInputImpl ( VOID  )

Definition at line 364 of file input.c.

365 {
367  if (!MasterTimer)
368  {
369  ERR("Failed to allocate memory\n");
370  ASSERT(FALSE);
371  return STATUS_UNSUCCESSFUL;
372  }
374 
375  return STATUS_SUCCESS;
376 }
PKTIMER MasterTimer
Definition: input.c:16
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define USERTAG_SYSTEM
Definition: tags.h:281
#define ERR(fmt,...)
Definition: debug.h:109
return STATUS_SUCCESS
Definition: btrfs.c:2725

Referenced by DriverEntry().

◆ IntBlockInput()

BOOL FASTCALL IntBlockInput ( PTHREADINFO  pti,
BOOL  BlockIt 
)

Definition at line 379 of file input.c.

380 {
381  PTHREADINFO OldBlock;
382  ASSERT(pti);
383 
384  if(!pti->rpdesk || ((pti->TIF_flags & TIF_INCLEANUP) && BlockIt))
385  {
386  /*
387  * Fail blocking if exiting the thread
388  */
389 
390  return FALSE;
391  }
392 
393  /*
394  * FIXME: Check access rights of the window station
395  * e.g. services running in the service window station cannot block input
396  */
397  if(!ThreadHasInputAccess(pti) ||
398  !IntIsActiveDesktop(pti->rpdesk))
399  {
401  return FALSE;
402  }
403 
404  ASSERT(pti->rpdesk);
405  OldBlock = pti->rpdesk->BlockInputThread;
406  if(OldBlock)
407  {
408  if(OldBlock != pti)
409  {
411  return FALSE;
412  }
413  pti->rpdesk->BlockInputThread = (BlockIt ? pti : NULL);
414  return OldBlock == NULL;
415  }
416 
417  pti->rpdesk->BlockInputThread = (BlockIt ? pti : NULL);
418  return OldBlock == NULL;
419 }
FLONG TIF_flags
Definition: win32.h:94
struct _DESKTOP * rpdesk
Definition: win32.h:91
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
#define ThreadHasInputAccess(W32Thread)
Definition: input.h:68
smooth NULL
Definition: ftsmooth.c:416
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define IntIsActiveDesktop(Desktop)
Definition: desktop.h:198
#define TIF_INCLEANUP
Definition: ntuser.h:240
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27

Referenced by ExitThreadCallback(), and NtUserBlockInput().

◆ IntLastInputTick()

static DWORD FASTCALL IntLastInputTick ( BOOL  bUpdate)
static

Definition at line 32 of file input.c.

33 {
34  if (bUpdate)
35  {
36  LARGE_INTEGER TickCount;
37  KeQueryTickCount(&TickCount);
39  if (gpsi) gpsi->dwLastRITEventTickCount = LastInputTick;
40  }
41  return LastInputTick;
42 }
static __inline LONG MsqCalculateMessageTime(IN PLARGE_INTEGER TickCount)
Definition: msgqueue.h:253
PSERVERINFO gpsi
Definition: main.c:27
VOID NTAPI KeQueryTickCount(IN PLARGE_INTEGER TickCount)
Definition: clock.c:165
static DWORD LastInputTick
Definition: input.c:21

Referenced by RawInputThreadMain().

◆ IsRemoveAttachThread()

BOOL FASTCALL IsRemoveAttachThread ( PTHREADINFO  pti)

Definition at line 441 of file input.c.

442 {
444  PATTACHINFO pai;
445  BOOL Ret = TRUE;
446  PTHREADINFO ptiFrom = NULL, ptiTo = NULL;
447 
448  do
449  {
450  if (!gpai) return TRUE;
451 
452  pai = gpai; // Bottom of the list.
453 
454  do
455  {
456  if (pai->pti2 == pti)
457  {
458  ptiFrom = pai->pti1;
459  ptiTo = pti;
460  break;
461  }
462  if (pai->pti1 == pti)
463  {
464  ptiFrom = pti;
465  ptiTo = pai->pti2;
466  break;
467  }
468  pai = pai->paiNext;
469 
470  } while (pai);
471 
472  if (!pai && !ptiFrom && !ptiTo) break;
473 
474  Status = UserAttachThreadInput(ptiFrom, ptiTo, FALSE);
475  if (!NT_SUCCESS(Status)) Ret = FALSE;
476 
477  } while (Ret);
478 
479  return Ret;
480 }
PTHREADINFO pti1
Definition: input.h:44
#define TRUE
Definition: types.h:120
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
Definition: input.c:483
PATTACHINFO gpai
Definition: input.c:17
LONG NTSTATUS
Definition: precomp.h:26
struct _ATTACHINFO * paiNext
Definition: input.h:43
unsigned int BOOL
Definition: ntddk_ex.h:94
PTHREADINFO pti2
Definition: input.h:45
smooth NULL
Definition: ftsmooth.c:416
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:24

Referenced by ExitThreadCallback().

◆ NtUserAttachThreadInput()

BOOL APIENTRY NtUserAttachThreadInput ( IN DWORD  idAttach,
IN DWORD  idAttachTo,
IN BOOL  fAttach 
)

Definition at line 668 of file input.c.

672 {
674  PTHREADINFO pti, ptiTo;
675  BOOL Ret = FALSE;
676 
678  TRACE("Enter NtUserAttachThreadInput %s\n",(fAttach ? "TRUE" : "FALSE" ));
679 
680  pti = IntTID2PTI(UlongToHandle(idAttach));
681  ptiTo = IntTID2PTI(UlongToHandle(idAttachTo));
682 
683  if ( !pti || !ptiTo )
684  {
685  TRACE("AttachThreadInput pti or ptiTo NULL.\n");
687  goto Exit;
688  }
689 
690  Status = UserAttachThreadInput( pti, ptiTo, fAttach);
691  if (!NT_SUCCESS(Status))
692  {
693  TRACE("AttachThreadInput Error Status 0x%x. \n",Status);
695  }
696  else Ret = TRUE;
697 
698 Exit:
699  TRACE("Leave NtUserAttachThreadInput, ret=%d\n",Ret);
700  UserLeave();
701  return Ret;
702 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
#define TRUE
Definition: types.h:120
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
Definition: input.c:483
LONG NTSTATUS
Definition: precomp.h:26
PTHREADINFO FASTCALL IntTID2PTI(HANDLE id)
Definition: misc.c:41
unsigned int BOOL
Definition: ntddk_ex.h:94
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
#define TRACE(s)
Definition: solgame.cpp:4
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static void Exit(void)
Definition: sock.c:1331
#define UlongToHandle(ul)
Definition: basetsd.h:97
Status
Definition: gdiplustypes.h:24
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27

◆ NtUserBlockInput()

BOOL APIENTRY NtUserBlockInput ( BOOL  BlockIt)

Definition at line 423 of file input.c.

425 {
426  BOOL ret;
427 
428  TRACE("Enter NtUserBlockInput\n");
430 
432 
433  UserLeave();
434  TRACE("Leave NtUserBlockInput, ret=%i\n", ret);
435 
436  return ret;
437 }
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
unsigned int BOOL
Definition: ntddk_ex.h:94
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
#define TRACE(s)
Definition: solgame.cpp:4
int ret
BOOL FASTCALL IntBlockInput(PTHREADINFO pti, BOOL BlockIt)
Definition: input.c:379
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255

Referenced by BlockInput().

◆ NtUserSendInput()

UINT APIENTRY NtUserSendInput ( UINT  nInputs,
LPINPUT  pInput,
INT  cbSize 
)

Definition at line 711 of file input.c.

715 {
716  PTHREADINFO pti;
717  UINT uRet = 0;
718 
719  TRACE("Enter NtUserSendInput\n");
721 
723  ASSERT(pti);
724 
725  if (!pti->rpdesk)
726  {
727  goto cleanup;
728  }
729 
730  if (!nInputs || !pInput || cbSize != sizeof(INPUT))
731  {
733  goto cleanup;
734  }
735 
736  /*
737  * FIXME: Check access rights of the window station
738  * e.g. services running in the service window station cannot block input
739  */
740  if (!ThreadHasInputAccess(pti) ||
741  !IntIsActiveDesktop(pti->rpdesk))
742  {
744  goto cleanup;
745  }
746 
747  while (nInputs--)
748  {
749  INPUT SafeInput;
751 
752  Status = MmCopyFromCaller(&SafeInput, pInput++, sizeof(INPUT));
753  if (!NT_SUCCESS(Status))
754  {
756  goto cleanup;
757  }
758 
759  switch (SafeInput.type)
760  {
761  case INPUT_MOUSE:
762  if (UserSendMouseInput(&SafeInput.mi, TRUE))
763  uRet++;
764  break;
765  case INPUT_KEYBOARD:
766  if (UserSendKeyboardInput(&SafeInput.ki, TRUE))
767  uRet++;
768  break;
769  case INPUT_HARDWARE:
770  FIXME("INPUT_HARDWARE not supported!");
771  break;
772  default:
773  ERR("SendInput(): Invalid input type: 0x%x\n", SafeInput.type);
774  break;
775  }
776  }
777 
778 cleanup:
779  TRACE("Leave NtUserSendInput, ret=%u\n", uRet);
780  UserLeave();
781  return uRet;
782 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
#define TRUE
Definition: types.h:120
BOOL NTAPI UserSendMouseInput(MOUSEINPUT *pMouseInput, BOOL bInjected)
Definition: mouse.c:168
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
LONG NTSTATUS
Definition: precomp.h:26
#define MmCopyFromCaller
Definition: polytest.cpp:29
struct _DESKTOP * rpdesk
Definition: win32.h:91
MOUSEINPUT mi
Definition: winable.h:61
#define INPUT_KEYBOARD
Definition: winable.h:10
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
#define ThreadHasInputAccess(W32Thread)
Definition: input.h:68
#define FIXME(fmt,...)
Definition: debug.h:110
#define INPUT_MOUSE
Definition: winable.h:9
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
#define TRACE(s)
Definition: solgame.cpp:4
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define IntIsActiveDesktop(Desktop)
Definition: desktop.h:198
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
BOOL NTAPI UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
Definition: keyboard.c:973
#define INPUT_HARDWARE
Definition: winable.h:11
DWORD type
Definition: winable.h:59
unsigned int UINT
Definition: ndis.h:50
char * cleanup(char *str)
Definition: wpickclick.c:99
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
KEYBDINPUT ki
Definition: winable.h:62

Referenced by keybd_event(), mouse_event(), and SendInput().

◆ OpenInputDevice()

static NTSTATUS NTAPI OpenInputDevice ( PHANDLE  pHandle,
PFILE_OBJECT ppObject,
CONST WCHAR pszDeviceName 
)
static

Definition at line 92 of file input.c.

93 {
98 
99  RtlInitUnicodeString(&DeviceName, pszDeviceName);
100 
102  &DeviceName,
104  NULL,
105  NULL);
106 
107  Status = ZwOpenFile(pHandle,
110  &Iosb,
111  0,
112  0);
113  if (NT_SUCCESS(Status) && ppObject)
114  {
117  }
118 
119  return Status;
120 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define FILE_ALL_ACCESS
Definition: nt_native.h:651
LONG NTSTATUS
Definition: precomp.h:26
WCHAR DeviceName[]
Definition: adapter.cpp:21
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:496
smooth NULL
Definition: ftsmooth.c:416
return Iosb
Definition: create.c:4426
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
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 SYNCHRONIZE
Definition: nt_native.h:61
Status
Definition: gdiplustypes.h:24
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231

Referenced by RawInputThreadMain().

◆ RawInputThreadMain()

VOID NTAPI RawInputThreadMain ( VOID  )

Definition at line 128 of file input.c.

129 {
130  NTSTATUS MouStatus = STATUS_UNSUCCESSFUL, KbdStatus = STATUS_UNSUCCESSFUL, Status;
131  IO_STATUS_BLOCK MouIosb, KbdIosb;
132  PFILE_OBJECT pKbdDevice = NULL, pMouDevice = NULL;
134  //LARGE_INTEGER WaitTimeout;
135  PVOID WaitObjects[4], pSignaledObject = NULL;
137  ULONG cWaitObjects = 0, cMaxWaitObjects = 2;
138  MOUSE_INPUT_DATA MouseInput;
139  KEYBOARD_INPUT_DATA KeyInput;
141  HWINSTA hWinSta;
142 
143  ByteOffset.QuadPart = (LONGLONG)0;
144  //WaitTimeout.QuadPart = (LONGLONG)(-10000000);
145 
149 
150  TRACE("Raw Input Thread %p\n", ptiRawInput);
151 
154 
156  0,
157  NULL,
160  UserMode,
161  (PHANDLE)&hWinSta);
162  if (NT_SUCCESS(Status))
163  {
165  }
166  else
167  {
168  ASSERT(FALSE);
169  /* Failed to open the interactive winsta! What now? */
170  }
171 
173  StartTheTimers();
174  UserLeave();
175 
178 
180  for (;;)
181  {
182  if (!ghMouseDevice)
183  {
184  /* Check if mouse device already exists */
185  Status = OpenInputDevice(&ghMouseDevice, &pMouDevice, L"\\Device\\PointerClass0" );
186  if (NT_SUCCESS(Status))
187  {
188  ++cMaxWaitObjects;
189  TRACE("Mouse connected!\n");
190  }
191  }
192  if (!ghKeyboardDevice)
193  {
194  /* Check if keyboard device already exists */
195  Status = OpenInputDevice(&ghKeyboardDevice, &pKbdDevice, L"\\Device\\KeyboardClass0");
196  if (NT_SUCCESS(Status))
197  {
198  ++cMaxWaitObjects;
199  TRACE("Keyboard connected!\n");
200  // Get and load keyboard attributes.
203  // Register the Window hotkey.
205  // Register the Window Snap hotkey.
210  // Register the debug hotkeys.
212  UserLeave();
213  }
214  }
215 
216  /* Reset WaitHandles array */
217  cWaitObjects = 0;
218  WaitObjects[cWaitObjects++] = ShutdownEvent;
219  WaitObjects[cWaitObjects++] = MasterTimer;
220 
221  if (ghMouseDevice)
222  {
223  /* Try to read from mouse if previous reading is not pending */
224  if (MouStatus != STATUS_PENDING)
225  {
226  MouStatus = ZwReadFile(ghMouseDevice,
227  NULL,
228  NULL,
229  NULL,
230  &MouIosb,
231  &MouseInput,
232  sizeof(MOUSE_INPUT_DATA),
233  &ByteOffset,
234  NULL);
235  }
236 
237  if (MouStatus == STATUS_PENDING)
238  WaitObjects[cWaitObjects++] = &pMouDevice->Event;
239  }
240 
241  if (ghKeyboardDevice)
242  {
243  /* Try to read from keyboard if previous reading is not pending */
244  if (KbdStatus != STATUS_PENDING)
245  {
246  KbdStatus = ZwReadFile(ghKeyboardDevice,
247  NULL,
248  NULL,
249  NULL,
250  &KbdIosb,
251  &KeyInput,
252  sizeof(KEYBOARD_INPUT_DATA),
253  &ByteOffset,
254  NULL);
255 
256  }
257  if (KbdStatus == STATUS_PENDING)
258  WaitObjects[cWaitObjects++] = &pKbdDevice->Event;
259  }
260 
261  /* If all objects are pending, wait for them */
262  if (cWaitObjects == cMaxWaitObjects)
263  {
264  Status = KeWaitForMultipleObjects(cWaitObjects,
265  WaitObjects,
266  WaitAny,
267  UserRequest,
268  KernelMode,
269  TRUE,
270  NULL,//&WaitTimeout,
272 
273  if ((Status >= STATUS_WAIT_0) &&
274  (Status < (STATUS_WAIT_0 + (LONG)cWaitObjects)))
275  {
276  /* Some device has finished reading */
277  pSignaledObject = WaitObjects[Status - STATUS_WAIT_0];
278 
279  /* Check if it is mouse or keyboard and update status */
280  if ((MouStatus == STATUS_PENDING) &&
281  (pSignaledObject == &pMouDevice->Event))
282  {
283  MouStatus = MouIosb.Status;
284  }
285  else if ((KbdStatus == STATUS_PENDING) &&
286  (pSignaledObject == &pKbdDevice->Event))
287  {
288  KbdStatus = KbdIosb.Status;
289  }
290  else if (pSignaledObject == MasterTimer)
291  {
292  ProcessTimers();
293  }
294  else if (pSignaledObject == ShutdownEvent)
295  {
296  break;
297  }
298  else ASSERT(FALSE);
299  }
300  }
301 
302  /* Have we successed reading from mouse? */
303  if (NT_SUCCESS(MouStatus) && MouStatus != STATUS_PENDING)
304  {
305  TRACE("MouseEvent\n");
306 
307  /* Set LastInputTick */
309 
310  /* Process data */
312  UserProcessMouseInput(&MouseInput);
313  UserLeave();
314  }
315  else if (MouStatus != STATUS_PENDING)
316  ERR("Failed to read from mouse: %x.\n", MouStatus);
317 
318  /* Have we successed reading from keyboard? */
319  if (NT_SUCCESS(KbdStatus) && KbdStatus != STATUS_PENDING)
320  {
321  TRACE("KeyboardEvent: %s %04x\n",
322  (KeyInput.Flags & KEY_BREAK) ? "up" : "down",
323  KeyInput.MakeCode);
324 
325  /* Set LastInputTick */
327 
328  /* Process data */
330  UserProcessKeyboardInput(&KeyInput);
331  UserLeave();
332  }
333  else if (KbdStatus != STATUS_PENDING)
334  ERR("Failed to read from keyboard: %x.\n", KbdStatus);
335  }
336 
337  if (ghMouseDevice)
338  {
339  (void)ZwCancelIoFile(ghMouseDevice, &MouIosb);
341  ObDereferenceObject(pMouDevice);
343  }
344 
345  if (ghKeyboardDevice)
346  {
349  ObDereferenceObject(pKbdDevice);
351  }
352 
353  ERR("Raw Input Thread Exit!\n");
354 }
#define IDHK_SNAP_DOWN
Definition: hotkey.h:23
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
NTSYSAPI NTSTATUS NTAPI ZwCancelIoFile(_In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock)
#define TRUE
Definition: types.h:120
static NTSTATUS NTAPI OpenInputDevice(PHANDLE pHandle, PFILE_OBJECT *ppObject, CONST WCHAR *pszDeviceName)
Definition: input.c:92
POBJECT_TYPE ExWindowStationObjectType
Definition: win32k.c:25
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
PKTIMER MasterTimer
Definition: input.c:16
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
static HANDLE ghMouseDevice
Definition: input.c:22
VOID FASTCALL StartTheTimers(VOID)
Definition: timer.c:368
FLONG TIF_flags
Definition: win32.h:94
PWINSTATION_OBJECT InputWindowStation
Definition: winsta.c:21
#define PWND_BOTTOM
Definition: ntuser.h:731
LONG NTSTATUS
Definition: precomp.h:26
#define VK_LEFT
Definition: winuser.h:2178
#define LOW_REALTIME_PRIORITY
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
#define VK_DOWN
Definition: winuser.h:2181
VOID NTAPI UserInitKeyboard(HANDLE hKeyboardDevice)
Definition: keyboard.c:161
#define KEY_BREAK
Definition: ntddkbd.h:71
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:2739
#define TIF_SYSTEMTHREAD
Definition: ntuser.h:242
HANDLE ghKeyboardDevice
Definition: input.c:19
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:783
VOID FASTCALL StartDebugHotKeys(VOID)
Definition: hotkey.c:44
NTSTATUS NTAPI PoRequestShutdownEvent(OUT PVOID *Event)
Definition: poshtdwn.c:396
#define STATUS_WAIT_0
Definition: ntstatus.h:223
#define VK_UP
Definition: winuser.h:2179
#define IDHK_SNAP_RIGHT
Definition: hotkey.h:21
long LONG
Definition: pedump.c:60
smooth NULL
Definition: ftsmooth.c:416
static HANDLE ShutdownEvent
Definition: dcomlaunch.c:28
PTHREADINFO ptiRawInput
Definition: input.c:15
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
int64_t LONGLONG
Definition: typedefs.h:66
#define TRACE(s)
Definition: solgame.cpp:4
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define IDHK_SNAP_UP
Definition: hotkey.h:22
VOID NTAPI UserProcessMouseInput(PMOUSE_INPUT_DATA pMouseInputData)
Definition: mouse.c:40
* PFILE_OBJECT
Definition: iotypes.h:1954
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:586
struct _CLIENTINFO * pClientInfo
Definition: win32.h:93
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3376
BOOL FASTCALL UserSetProcessWindowStation(HWINSTA hWindowStation)
Definition: winsta.c:1346
static const WCHAR L[]
Definition: oid.c:1250
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
BOOL FASTCALL UserRegisterHotKey(PWND pWnd, int id, UINT fsModifiers, UINT vk)
Definition: hotkey.c:431
Status
Definition: gdiplustypes.h:24
#define VK_RIGHT
Definition: winuser.h:2180
#define ERR(fmt,...)
Definition: debug.h:109
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
VOID FASTCALL ProcessTimers(VOID)
Definition: timer.c:449
KPRIORITY NTAPI KeSetPriorityThread(IN PKTHREAD Thread, IN KPRIORITY Priority)
Definition: thrdobj.c:1327
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define IDHK_SNAP_LEFT
Definition: hotkey.h:20
VOID NTAPI UserProcessKeyboardInput(PKEYBOARD_INPUT_DATA pKeyInput)
Definition: keyboard.c:1053
unsigned int ULONG
Definition: retypes.h:1
_Must_inspect_result_ _In_ WAIT_TYPE _In_opt_ PLARGE_INTEGER _In_opt_ PKWAIT_BLOCK WaitBlockArray
Definition: fsrtlfuncs.h:1151
#define MOD_WIN
Definition: winuser.h:2598
#define IDHK_WINKEY
Definition: hotkey.h:16
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:716
static DWORD FASTCALL IntLastInputTick(BOOL bUpdate)
Definition: input.c:32
#define NT_ASSERT
Definition: rtlfuncs.h:3312

Referenced by UserSystemThreadProc().

◆ UserAttachThreadInput()

NTSTATUS FASTCALL UserAttachThreadInput ( PTHREADINFO  ptiFrom,
PTHREADINFO  ptiTo,
BOOL  fAttach 
)

Definition at line 483 of file input.c.

484 {
485  MSG msg;
486  PATTACHINFO pai;
487  PCURICON_OBJECT CurIcon;
488 
489  /* Can not be the same thread. */
490  if (ptiFrom == ptiTo) return STATUS_INVALID_PARAMETER;
491 
492  /* Do not attach to system threads or between different desktops. */
493  if (ptiFrom->TIF_flags & TIF_DONTATTACHQUEUE ||
494  ptiTo->TIF_flags & TIF_DONTATTACHQUEUE ||
495  ptiFrom->rpdesk != ptiTo->rpdesk)
496  return STATUS_ACCESS_DENIED;
497 
498  /* MSDN Note:
499  Keyboard and mouse events received by both threads are processed by the thread specified by the idAttachTo.
500  */
501 
502  /* If Attach set, allocate and link. */
503  if (fAttach)
504  {
506  if (!pai) return STATUS_NO_MEMORY;
507 
508  pai->paiNext = gpai;
509  pai->pti1 = ptiFrom;
510  pai->pti2 = ptiTo;
511  gpai = pai;
512  paiCount++;
513  ERR("Attach Allocated! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
514 
515  if (ptiTo->MessageQueue != ptiFrom->MessageQueue)
516  {
517 
518  ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
519 
520  if (ptiFrom->MessageQueue == gpqForeground)
521  {
522  ERR("ptiFrom is Foreground\n");
523  ptiTo->MessageQueue->spwndActive = ptiFrom->MessageQueue->spwndActive;
524  ptiTo->MessageQueue->spwndFocus = ptiFrom->MessageQueue->spwndFocus;
525  ptiTo->MessageQueue->spwndCapture = ptiFrom->MessageQueue->spwndCapture;
526  ptiTo->MessageQueue->QF_flags ^= ((ptiTo->MessageQueue->QF_flags ^ ptiFrom->MessageQueue->QF_flags) & QF_CAPTURELOCKED);
527  RtlCopyMemory(&ptiTo->MessageQueue->CaretInfo,
528  &ptiFrom->MessageQueue->CaretInfo,
529  sizeof(ptiTo->MessageQueue->CaretInfo));
532  gptiForeground = ptiTo;
533  }
534  else
535  {
536  ERR("ptiFrom NOT Foreground\n");
537  if ( ptiTo->MessageQueue->spwndActive == 0 )
538  ptiTo->MessageQueue->spwndActive = ptiFrom->MessageQueue->spwndActive;
539  if ( ptiTo->MessageQueue->spwndFocus == 0 )
540  ptiTo->MessageQueue->spwndFocus = ptiFrom->MessageQueue->spwndFocus;
541  }
542 
543  CurIcon = ptiFrom->MessageQueue->CursorObject;
544 
545  MsqDestroyMessageQueue(ptiFrom);
546 
547  if (CurIcon)
548  {
549  // Could be global. Keep it above the water line!
550  UserReferenceObject(CurIcon);
551  }
552 
553  if (CurIcon && UserObjectInDestroy(UserHMGetHandle(CurIcon)))
554  {
555  UserDereferenceObject(CurIcon);
556  CurIcon = NULL;
557  }
558 
559  ptiFrom->MessageQueue = ptiTo->MessageQueue;
560 
561  // Pass cursor From if To is null. Pass test_SetCursor parent_id == current pti ID.
562  if (CurIcon && ptiTo->MessageQueue->CursorObject == NULL)
563  {
564  ERR("ptiTo receiving ptiFrom Cursor\n");
565  ptiTo->MessageQueue->CursorObject = CurIcon;
566  }
567 
568  ptiFrom->MessageQueue->cThreads++;
569  ERR("ptiTo S Share count %u\n", ptiFrom->MessageQueue->cThreads);
570 
572  }
573  else
574  {
575  ERR("Attach Threads are already associated!\n");
576  }
577  }
578  else /* If clear, unlink and free it. */
579  {
580  BOOL Hit = FALSE;
581  PATTACHINFO *ppai;
582 
583  if (!gpai) return STATUS_INVALID_PARAMETER;
584 
585  /* Search list and free if found or return false. */
586  ppai = &gpai;
587  while (*ppai != NULL)
588  {
589  if ( (*ppai)->pti2 == ptiTo && (*ppai)->pti1 == ptiFrom )
590  {
591  pai = *ppai;
592  /* Remove it from the list */
593  *ppai = (*ppai)->paiNext;
595  paiCount--;
596  Hit = TRUE;
597  break;
598  }
599  ppai = &((*ppai)->paiNext);
600  }
601 
602  if (!Hit) return STATUS_INVALID_PARAMETER;
603 
604  ERR("Attach Free! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
605 
606  if (ptiTo->MessageQueue == ptiFrom->MessageQueue)
607  {
608  PWND spwndActive = ptiTo->MessageQueue->spwndActive;
609  PWND spwndFocus = ptiTo->MessageQueue->spwndFocus;
610 
611  if (gptiForeground == ptiFrom)
612  {
613  ERR("ptiTo is now pti FG.\n");
614  // MessageQueue foreground is set so switch threads.
615  gptiForeground = ptiTo;
616  }
617  ptiTo->MessageQueue->cThreads--;
618  ERR("ptiTo E Share count %u\n", ptiTo->MessageQueue->cThreads);
619  ASSERT(ptiTo->MessageQueue->cThreads >= 1);
620 
622 
623  ptiFrom->MessageQueue = MsqCreateMessageQueue(ptiFrom);
624 
625  if (spwndActive)
626  {
627  if (spwndActive->head.pti == ptiFrom)
628  {
629  ptiFrom->MessageQueue->spwndActive = spwndActive;
630  ptiTo->MessageQueue->spwndActive = 0;
631  }
632  }
633  if (spwndFocus)
634  {
635  if (spwndFocus->head.pti == ptiFrom)
636  {
637  ptiFrom->MessageQueue->spwndFocus = spwndFocus;
638  ptiTo->MessageQueue->spwndFocus = 0;
639  }
640  }
641  ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
642  }
643  else
644  {
645  ERR("Detaching Threads are not associated!\n");
646  }
647  }
648  /* Note that key state, which can be ascertained by calls to the GetKeyState
649  or GetKeyboardState function, is reset after a call to AttachThreadInput.
650  ATM which one?
651  */
652  RtlCopyMemory(ptiTo->MessageQueue->afKeyState, gafAsyncKeyState, sizeof(gafAsyncKeyState));
653 
654  ptiTo->MessageQueue->msgDblClk.message = 0;
655 
656  /* Generate mouse move message */
657  msg.message = WM_MOUSEMOVE;
658  msg.wParam = UserGetMouseButtonsState();
659  msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y);
660  msg.pt = gpsi->ptCursor;
662 
663  return STATUS_SUCCESS;
664 }
BYTE gafAsyncKeyState[256 *2/8]
Definition: keyboard.c:13
PUSER_MESSAGE_QUEUE gpqForeground
Definition: focus.c:12
PTHREADINFO pti1
Definition: input.h:44
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
VOID FASTCALL co_MsqInsertMouseMessage(MSG *Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook)
Definition: msgqueue.c:582
PATTACHINFO gpai
Definition: input.c:17
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define TIF_DONTATTACHQUEUE
Definition: ntuser.h:246
FLONG TIF_flags
Definition: win32.h:94
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define MAKELPARAM(l, h)
Definition: winuser.h:3915
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:610
struct _DESKTOP * rpdesk
Definition: win32.h:91
PSERVERINFO gpsi
Definition: main.c:27
WORD FASTCALL UserGetMouseButtonsState(VOID)
Definition: mouse.c:22
#define IntReferenceMessageQueue(MsgQueue)
Definition: msgqueue.h:217
struct _ATTACHINFO * paiNext
Definition: input.h:43
PTHREADINFO gptiForeground
Definition: focus.c:14
unsigned int BOOL
Definition: ntddk_ex.h:94
#define QF_CAPTURELOCKED
Definition: msgqueue.h:111
PTHREADINFO pti2
Definition: input.h:45
THRDESKHEAD head
Definition: ntuser.h:659
#define USERTAG_ATTACHINFO
Definition: tags.h:196
INT paiCount
Definition: input.c:18
smooth NULL
Definition: ftsmooth.c:416
BOOL FASTCALL UserObjectInDestroy(HANDLE h)
Definition: object.c:669
#define UserHMGetHandle(obj)
Definition: ntuser.h:208
#define IntDereferenceMessageQueue(MsgQueue)
Definition: msgqueue.h:220
VOID FASTCALL MsqDestroyMessageQueue(_In_ PTHREADINFO pti)
Definition: msgqueue.c:2457
PUSER_MESSAGE_QUEUE FASTCALL MsqCreateMessageQueue(PTHREADINFO pti)
Definition: msgqueue.c:2430
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define ERR(fmt,...)
Definition: debug.h:109
Definition: ntuser.h:657
struct _USER_MESSAGE_QUEUE * MessageQueue
Definition: win32.h:88
VOID FASTCALL IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue)
Definition: desktop.c:1283
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define WM_MOUSEMOVE
Definition: winuser.h:1751
#define msg(x)
Definition: auth_time.c:54
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
INT iCursorLevel
Definition: win32.h:126
return STATUS_SUCCESS
Definition: btrfs.c:2725
VOID FASTCALL UserReferenceObject(PVOID obj)
Definition: object.c:697

Referenced by co_IntSetParent(), co_UserCreateWindowEx(), co_UserDestroyWindow(), IntCreateWindow(), IntProcessOwnerSwap(), IsRemoveAttachThread(), and NtUserAttachThreadInput().

Variable Documentation

◆ ghKeyboardDevice

HANDLE ghKeyboardDevice = NULL

Definition at line 19 of file input.c.

Referenced by ProcessKeyEvent(), and RawInputThreadMain().

◆ ghMouseDevice

HANDLE ghMouseDevice
static

Definition at line 22 of file input.c.

Referenced by RawInputThreadMain().

◆ gpai

PATTACHINFO gpai = NULL

Definition at line 17 of file input.c.

Referenced by IsRemoveAttachThread(), and UserAttachThreadInput().

◆ LastInputTick

DWORD LastInputTick = 0
static

Definition at line 21 of file input.c.

Referenced by DoTheScreenSaver(), and IntLastInputTick().

◆ MasterTimer

PKTIMER MasterTimer = NULL

Definition at line 16 of file input.c.

Referenced by InitInputImpl(), IntSetTimer(), ProcessTimers(), and RawInputThreadMain().

◆ paiCount

INT paiCount = 0

Definition at line 18 of file input.c.

Referenced by UserAttachThreadInput().

◆ ptiRawInput

PTHREADINFO ptiRawInput

Definition at line 15 of file input.c.

Referenced by IntSetTimer(), and RawInputThreadMain().