ReactOS  0.4.13-dev-249-gcba1a2f
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 48 of file input.c.

49 {
50  DWORD Test, TO;
51 
52  if (gspv.iScrSaverTimeout > 0) // Zero means Off.
53  {
56  TO = 1000 * gspv.iScrSaverTimeout;
57  if (Test > TO)
58  {
59  TRACE("Screensaver Message Start! Tick %lu Timeout %d \n", Test, gspv.iScrSaverTimeout);
60 
61  if (ppiScrnSaver) // We are or we are not the screensaver, prevent reentry...
62  {
63  if (!(ppiScrnSaver->W32PF_flags & W32PF_IDLESCREENSAVER))
64  {
65  ppiScrnSaver->W32PF_flags |= W32PF_IDLESCREENSAVER;
66  ERR("Screensaver is Idle\n");
67  }
68  }
69  else
70  {
71  PUSER_MESSAGE_QUEUE ForegroundQueue = IntGetFocusMessageQueue();
72  if (ForegroundQueue && ForegroundQueue->spwndActive)
73  UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_START_SCREENSAVE, 1); // lParam 1 == Secure
74  else
76  }
77  }
78  }
79 }
BOOL FASTCALL UserPostMessage(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1181
PPROCESSINFO ppiScrnSaver
Definition: main.c:30
#define EngGetTickCount32()
Definition: eng.h:43
INT iScrSaverTimeout
Definition: sysparams.h:110
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1271
#define LN_START_SCREENSAVE
Definition: undocuser.h:119
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 360 of file input.c.

361 {
363  if (!MasterTimer)
364  {
365  ERR("Failed to allocate memory\n");
366  ASSERT(FALSE);
367  return STATUS_UNSUCCESSFUL;
368  }
370 
371  return STATUS_SUCCESS;
372 }
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:2745

Referenced by DriverEntry().

◆ IntBlockInput()

BOOL FASTCALL IntBlockInput ( PTHREADINFO  pti,
BOOL  BlockIt 
)

Definition at line 375 of file input.c.

376 {
377  PTHREADINFO OldBlock;
378  ASSERT(pti);
379 
380  if(!pti->rpdesk || ((pti->TIF_flags & TIF_INCLEANUP) && BlockIt))
381  {
382  /*
383  * Fail blocking if exiting the thread
384  */
385 
386  return FALSE;
387  }
388 
389  /*
390  * FIXME: Check access rights of the window station
391  * e.g. services running in the service window station cannot block input
392  */
393  if(!ThreadHasInputAccess(pti) ||
394  !IntIsActiveDesktop(pti->rpdesk))
395  {
397  return FALSE;
398  }
399 
400  ASSERT(pti->rpdesk);
401  OldBlock = pti->rpdesk->BlockInputThread;
402  if(OldBlock)
403  {
404  if(OldBlock != pti)
405  {
407  return FALSE;
408  }
409  pti->rpdesk->BlockInputThread = (BlockIt ? pti : NULL);
410  return OldBlock == NULL;
411  }
412 
413  pti->rpdesk->BlockInputThread = (BlockIt ? pti : NULL);
414  return OldBlock == NULL;
415 }
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  {
37  if (gpsi) gpsi->dwLastRITEventTickCount = LastInputTick;
38  }
39  return LastInputTick;
40 }
#define EngGetTickCount32()
Definition: eng.h:43
PSERVERINFO gpsi
Definition: main.c:27
static DWORD LastInputTick
Definition: input.c:21

Referenced by RawInputThreadMain().

◆ IsRemoveAttachThread()

BOOL FASTCALL IsRemoveAttachThread ( PTHREADINFO  pti)

Definition at line 437 of file input.c.

438 {
440  PATTACHINFO pai;
441  BOOL Ret = TRUE;
442  PTHREADINFO ptiFrom = NULL, ptiTo = NULL;
443 
444  do
445  {
446  if (!gpai) return TRUE;
447 
448  pai = gpai; // Bottom of the list.
449 
450  do
451  {
452  if (pai->pti2 == pti)
453  {
454  ptiFrom = pai->pti1;
455  ptiTo = pti;
456  break;
457  }
458  if (pai->pti1 == pti)
459  {
460  ptiFrom = pti;
461  ptiTo = pai->pti2;
462  break;
463  }
464  pai = pai->paiNext;
465 
466  } while (pai);
467 
468  if (!pai && !ptiFrom && !ptiTo) break;
469 
470  Status = UserAttachThreadInput(ptiFrom, ptiTo, FALSE);
471  if (!NT_SUCCESS(Status)) Ret = FALSE;
472 
473  } while (Ret);
474 
475  return Ret;
476 }
PTHREADINFO pti1
Definition: input.h:44
#define TRUE
Definition: types.h:120
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
Definition: input.c:479
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 664 of file input.c.

668 {
670  PTHREADINFO pti, ptiTo;
671  BOOL Ret = FALSE;
672 
674  TRACE("Enter NtUserAttachThreadInput %s\n",(fAttach ? "TRUE" : "FALSE" ));
675 
676  pti = IntTID2PTI(UlongToHandle(idAttach));
677  ptiTo = IntTID2PTI(UlongToHandle(idAttachTo));
678 
679  if ( !pti || !ptiTo )
680  {
681  TRACE("AttachThreadInput pti or ptiTo NULL.\n");
683  goto Exit;
684  }
685 
686  Status = UserAttachThreadInput( pti, ptiTo, fAttach);
687  if (!NT_SUCCESS(Status))
688  {
689  TRACE("AttachThreadInput Error Status 0x%x. \n",Status);
691  }
692  else Ret = TRUE;
693 
694 Exit:
695  TRACE("Leave NtUserAttachThreadInput, ret=%d\n",Ret);
696  UserLeave();
697  return Ret;
698 }
#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:479
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 419 of file input.c.

421 {
422  BOOL ret;
423 
424  TRACE("Enter NtUserBlockInput\n");
426 
428 
429  UserLeave();
430  TRACE("Leave NtUserBlockInput, ret=%i\n", ret);
431 
432  return ret;
433 }
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:375
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255

Referenced by BlockInput().

◆ NtUserSendInput()

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

Definition at line 707 of file input.c.

711 {
712  PTHREADINFO pti;
713  UINT uRet = 0;
714 
715  TRACE("Enter NtUserSendInput\n");
717 
719  ASSERT(pti);
720 
721  if (!pti->rpdesk)
722  {
723  goto cleanup;
724  }
725 
726  if (!nInputs || !pInput || cbSize != sizeof(INPUT))
727  {
729  goto cleanup;
730  }
731 
732  /*
733  * FIXME: Check access rights of the window station
734  * e.g. services running in the service window station cannot block input
735  */
736  if (!ThreadHasInputAccess(pti) ||
737  !IntIsActiveDesktop(pti->rpdesk))
738  {
740  goto cleanup;
741  }
742 
743  while (nInputs--)
744  {
745  INPUT SafeInput;
747 
748  Status = MmCopyFromCaller(&SafeInput, pInput++, sizeof(INPUT));
749  if (!NT_SUCCESS(Status))
750  {
752  goto cleanup;
753  }
754 
755  switch (SafeInput.type)
756  {
757  case INPUT_MOUSE:
758  if (UserSendMouseInput(&SafeInput.mi, TRUE))
759  uRet++;
760  break;
761  case INPUT_KEYBOARD:
762  if (UserSendKeyboardInput(&SafeInput.ki, TRUE))
763  uRet++;
764  break;
765  case INPUT_HARDWARE:
766  FIXME("INPUT_HARDWARE not supported!");
767  break;
768  default:
769  ERR("SendInput(): Invalid input type: 0x%x\n", SafeInput.type);
770  break;
771  }
772  }
773 
774 cleanup:
775  TRACE("Leave NtUserSendInput, ret=%u\n", uRet);
776  UserLeave();
777  return uRet;
778 }
#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 88 of file input.c.

89 {
94 
95  RtlInitUnicodeString(&DeviceName, pszDeviceName);
96 
98  &DeviceName,
100  NULL,
101  NULL);
102 
103  Status = ZwOpenFile(pHandle,
106  &Iosb,
107  0,
108  0);
109  if (NT_SUCCESS(Status) && ppObject)
110  {
113  }
114 
115  return Status;
116 }
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 124 of file input.c.

125 {
126  NTSTATUS MouStatus = STATUS_UNSUCCESSFUL, KbdStatus = STATUS_UNSUCCESSFUL, Status;
127  IO_STATUS_BLOCK MouIosb, KbdIosb;
128  PFILE_OBJECT pKbdDevice = NULL, pMouDevice = NULL;
130  //LARGE_INTEGER WaitTimeout;
131  PVOID WaitObjects[4], pSignaledObject = NULL;
133  ULONG cWaitObjects = 0, cMaxWaitObjects = 2;
134  MOUSE_INPUT_DATA MouseInput;
135  KEYBOARD_INPUT_DATA KeyInput;
137  HWINSTA hWinSta;
138 
139  ByteOffset.QuadPart = (LONGLONG)0;
140  //WaitTimeout.QuadPart = (LONGLONG)(-10000000);
141 
145 
146  TRACE("Raw Input Thread %p\n", ptiRawInput);
147 
150 
152  0,
153  NULL,
156  UserMode,
157  (PHANDLE)&hWinSta);
158  if (NT_SUCCESS(Status))
159  {
161  }
162  else
163  {
164  ASSERT(FALSE);
165  /* Failed to open the interactive winsta! What now? */
166  }
167 
169  StartTheTimers();
170  UserLeave();
171 
174 
176  for (;;)
177  {
178  if (!ghMouseDevice)
179  {
180  /* Check if mouse device already exists */
181  Status = OpenInputDevice(&ghMouseDevice, &pMouDevice, L"\\Device\\PointerClass0" );
182  if (NT_SUCCESS(Status))
183  {
184  ++cMaxWaitObjects;
185  TRACE("Mouse connected!\n");
186  }
187  }
188  if (!ghKeyboardDevice)
189  {
190  /* Check if keyboard device already exists */
191  Status = OpenInputDevice(&ghKeyboardDevice, &pKbdDevice, L"\\Device\\KeyboardClass0");
192  if (NT_SUCCESS(Status))
193  {
194  ++cMaxWaitObjects;
195  TRACE("Keyboard connected!\n");
196  // Get and load keyboard attributes.
199  // Register the Window hotkey.
201  // Register the Window Snap hotkey.
206  // Register the debug hotkeys.
208  UserLeave();
209  }
210  }
211 
212  /* Reset WaitHandles array */
213  cWaitObjects = 0;
214  WaitObjects[cWaitObjects++] = ShutdownEvent;
215  WaitObjects[cWaitObjects++] = MasterTimer;
216 
217  if (ghMouseDevice)
218  {
219  /* Try to read from mouse if previous reading is not pending */
220  if (MouStatus != STATUS_PENDING)
221  {
222  MouStatus = ZwReadFile(ghMouseDevice,
223  NULL,
224  NULL,
225  NULL,
226  &MouIosb,
227  &MouseInput,
228  sizeof(MOUSE_INPUT_DATA),
229  &ByteOffset,
230  NULL);
231  }
232 
233  if (MouStatus == STATUS_PENDING)
234  WaitObjects[cWaitObjects++] = &pMouDevice->Event;
235  }
236 
237  if (ghKeyboardDevice)
238  {
239  /* Try to read from keyboard if previous reading is not pending */
240  if (KbdStatus != STATUS_PENDING)
241  {
242  KbdStatus = ZwReadFile(ghKeyboardDevice,
243  NULL,
244  NULL,
245  NULL,
246  &KbdIosb,
247  &KeyInput,
248  sizeof(KEYBOARD_INPUT_DATA),
249  &ByteOffset,
250  NULL);
251 
252  }
253  if (KbdStatus == STATUS_PENDING)
254  WaitObjects[cWaitObjects++] = &pKbdDevice->Event;
255  }
256 
257  /* If all objects are pending, wait for them */
258  if (cWaitObjects == cMaxWaitObjects)
259  {
260  Status = KeWaitForMultipleObjects(cWaitObjects,
261  WaitObjects,
262  WaitAny,
263  UserRequest,
264  KernelMode,
265  TRUE,
266  NULL,//&WaitTimeout,
268 
269  if ((Status >= STATUS_WAIT_0) &&
270  (Status < (STATUS_WAIT_0 + (LONG)cWaitObjects)))
271  {
272  /* Some device has finished reading */
273  pSignaledObject = WaitObjects[Status - STATUS_WAIT_0];
274 
275  /* Check if it is mouse or keyboard and update status */
276  if ((MouStatus == STATUS_PENDING) &&
277  (pSignaledObject == &pMouDevice->Event))
278  {
279  MouStatus = MouIosb.Status;
280  }
281  else if ((KbdStatus == STATUS_PENDING) &&
282  (pSignaledObject == &pKbdDevice->Event))
283  {
284  KbdStatus = KbdIosb.Status;
285  }
286  else if (pSignaledObject == MasterTimer)
287  {
288  ProcessTimers();
289  }
290  else if (pSignaledObject == ShutdownEvent)
291  {
292  break;
293  }
294  else ASSERT(FALSE);
295  }
296  }
297 
298  /* Have we successed reading from mouse? */
299  if (NT_SUCCESS(MouStatus) && MouStatus != STATUS_PENDING)
300  {
301  TRACE("MouseEvent\n");
302 
303  /* Set LastInputTick */
305 
306  /* Process data */
308  UserProcessMouseInput(&MouseInput);
309  UserLeave();
310  }
311  else if (MouStatus != STATUS_PENDING)
312  ERR("Failed to read from mouse: %x.\n", MouStatus);
313 
314  /* Have we successed reading from keyboard? */
315  if (NT_SUCCESS(KbdStatus) && KbdStatus != STATUS_PENDING)
316  {
317  TRACE("KeyboardEvent: %s %04x\n",
318  (KeyInput.Flags & KEY_BREAK) ? "up" : "down",
319  KeyInput.MakeCode);
320 
321  /* Set LastInputTick */
323 
324  /* Process data */
326  UserProcessKeyboardInput(&KeyInput);
327  UserLeave();
328  }
329  else if (KbdStatus != STATUS_PENDING)
330  ERR("Failed to read from keyboard: %x.\n", KbdStatus);
331  }
332 
333  if (ghMouseDevice)
334  {
335  (void)ZwCancelIoFile(ghMouseDevice, &MouIosb);
337  ObDereferenceObject(pMouDevice);
339  }
340 
341  if (ghKeyboardDevice)
342  {
345  ObDereferenceObject(pKbdDevice);
347  }
348 
349  ERR("Raw Input Thread Exit!\n");
350 }
#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:88
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:781
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:446
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:1051
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 479 of file input.c.

480 {
481  MSG msg;
482  PATTACHINFO pai;
483  PCURICON_OBJECT CurIcon;
484 
485  /* Can not be the same thread. */
486  if (ptiFrom == ptiTo) return STATUS_INVALID_PARAMETER;
487 
488  /* Do not attach to system threads or between different desktops. */
489  if (ptiFrom->TIF_flags & TIF_DONTATTACHQUEUE ||
490  ptiTo->TIF_flags & TIF_DONTATTACHQUEUE ||
491  ptiFrom->rpdesk != ptiTo->rpdesk)
492  return STATUS_ACCESS_DENIED;
493 
494  /* MSDN Note:
495  Keyboard and mouse events received by both threads are processed by the thread specified by the idAttachTo.
496  */
497 
498  /* If Attach set, allocate and link. */
499  if (fAttach)
500  {
502  if (!pai) return STATUS_NO_MEMORY;
503 
504  pai->paiNext = gpai;
505  pai->pti1 = ptiFrom;
506  pai->pti2 = ptiTo;
507  gpai = pai;
508  paiCount++;
509  ERR("Attach Allocated! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
510 
511  if (ptiTo->MessageQueue != ptiFrom->MessageQueue)
512  {
513 
514  ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
515 
516  if (ptiFrom->MessageQueue == gpqForeground)
517  {
518  ERR("ptiFrom is Foreground\n");
519  ptiTo->MessageQueue->spwndActive = ptiFrom->MessageQueue->spwndActive;
520  ptiTo->MessageQueue->spwndFocus = ptiFrom->MessageQueue->spwndFocus;
521  ptiTo->MessageQueue->spwndCapture = ptiFrom->MessageQueue->spwndCapture;
522  ptiTo->MessageQueue->QF_flags ^= ((ptiTo->MessageQueue->QF_flags ^ ptiFrom->MessageQueue->QF_flags) & QF_CAPTURELOCKED);
523  RtlCopyMemory(&ptiTo->MessageQueue->CaretInfo,
524  &ptiFrom->MessageQueue->CaretInfo,
525  sizeof(ptiTo->MessageQueue->CaretInfo));
528  gptiForeground = ptiTo;
529  }
530  else
531  {
532  ERR("ptiFrom NOT Foreground\n");
533  if ( ptiTo->MessageQueue->spwndActive == 0 )
534  ptiTo->MessageQueue->spwndActive = ptiFrom->MessageQueue->spwndActive;
535  if ( ptiTo->MessageQueue->spwndFocus == 0 )
536  ptiTo->MessageQueue->spwndFocus = ptiFrom->MessageQueue->spwndFocus;
537  }
538 
539  CurIcon = ptiFrom->MessageQueue->CursorObject;
540 
541  MsqDestroyMessageQueue(ptiFrom);
542 
543  if (CurIcon)
544  {
545  // Could be global. Keep it above the water line!
546  UserReferenceObject(CurIcon);
547  }
548 
549  if (CurIcon && UserObjectInDestroy(UserHMGetHandle(CurIcon)))
550  {
551  UserDereferenceObject(CurIcon);
552  CurIcon = NULL;
553  }
554 
555  ptiFrom->MessageQueue = ptiTo->MessageQueue;
556 
557  // Pass cursor From if To is null. Pass test_SetCursor parent_id == current pti ID.
558  if (CurIcon && ptiTo->MessageQueue->CursorObject == NULL)
559  {
560  ERR("ptiTo receiving ptiFrom Cursor\n");
561  ptiTo->MessageQueue->CursorObject = CurIcon;
562  }
563 
564  ptiFrom->MessageQueue->cThreads++;
565  ERR("ptiTo S Share count %u\n", ptiFrom->MessageQueue->cThreads);
566 
568  }
569  else
570  {
571  ERR("Attach Threads are already associated!\n");
572  }
573  }
574  else /* If clear, unlink and free it. */
575  {
576  BOOL Hit = FALSE;
577  PATTACHINFO *ppai;
578 
579  if (!gpai) return STATUS_INVALID_PARAMETER;
580 
581  /* Search list and free if found or return false. */
582  ppai = &gpai;
583  while (*ppai != NULL)
584  {
585  if ( (*ppai)->pti2 == ptiTo && (*ppai)->pti1 == ptiFrom )
586  {
587  pai = *ppai;
588  /* Remove it from the list */
589  *ppai = (*ppai)->paiNext;
591  paiCount--;
592  Hit = TRUE;
593  break;
594  }
595  ppai = &((*ppai)->paiNext);
596  }
597 
598  if (!Hit) return STATUS_INVALID_PARAMETER;
599 
600  ERR("Attach Free! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
601 
602  if (ptiTo->MessageQueue == ptiFrom->MessageQueue)
603  {
604  PWND spwndActive = ptiTo->MessageQueue->spwndActive;
605  PWND spwndFocus = ptiTo->MessageQueue->spwndFocus;
606 
607  if (gptiForeground == ptiFrom)
608  {
609  ERR("ptiTo is now pti FG.\n");
610  // MessageQueue foreground is set so switch threads.
611  gptiForeground = ptiTo;
612  }
613  ptiTo->MessageQueue->cThreads--;
614  ERR("ptiTo E Share count %u\n", ptiTo->MessageQueue->cThreads);
615  ASSERT(ptiTo->MessageQueue->cThreads >= 1);
616 
618 
619  ptiFrom->MessageQueue = MsqCreateMessageQueue(ptiFrom);
620 
621  if (spwndActive)
622  {
623  if (spwndActive->head.pti == ptiFrom)
624  {
625  ptiFrom->MessageQueue->spwndActive = spwndActive;
626  ptiTo->MessageQueue->spwndActive = 0;
627  }
628  }
629  if (spwndFocus)
630  {
631  if (spwndFocus->head.pti == ptiFrom)
632  {
633  ptiFrom->MessageQueue->spwndFocus = spwndFocus;
634  ptiTo->MessageQueue->spwndFocus = 0;
635  }
636  }
637  ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
638  }
639  else
640  {
641  ERR("Detaching Threads are not associated!\n");
642  }
643  }
644  /* Note that key state, which can be ascertained by calls to the GetKeyState
645  or GetKeyboardState function, is reset after a call to AttachThreadInput.
646  ATM which one?
647  */
648  RtlCopyMemory(ptiTo->MessageQueue->afKeyState, gafAsyncKeyState, sizeof(gafAsyncKeyState));
649 
650  ptiTo->MessageQueue->msgDblClk.message = 0;
651 
652  /* Generate mouse move message */
653  msg.message = WM_MOUSEMOVE;
654  msg.wParam = UserGetMouseButtonsState();
655  msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y);
656  msg.pt = gpsi->ptCursor;
658 
659  return STATUS_SUCCESS;
660 }
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:580
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:2449
PUSER_MESSAGE_QUEUE FASTCALL MsqCreateMessageQueue(PTHREADINFO pti)
Definition: msgqueue.c:2422
#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:2745
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().