ReactOS  0.4.15-dev-5137-g826bd41
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)
 
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:1346
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:1307
#define LN_START_SCREENSAVE
Definition: undocuser.h:120
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:110
static DWORD LastInputTick
Definition: input.c:21
int Test
Definition: ehthrow.cxx:21

Referenced by HungAppSysTimerProc().

◆ InitInputImpl()

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
#define FALSE
Definition: types.h:117
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
#define ASSERT(a)
Definition: mode.c:44
#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:282
#define ERR(fmt,...)
Definition: debug.h:110
#define STATUS_SUCCESS
Definition: shellext.h:65

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:91
struct _DESKTOP * rpdesk
Definition: win32.h:88
#define FALSE
Definition: types.h:117
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define ThreadHasInputAccess(W32Thread)
Definition: input.h:68
#define ASSERT(a)
Definition: mode.c:44
#define IntIsActiveDesktop(Desktop)
Definition: desktop.h:172
#define NULL
Definition: types.h:112
#define TIF_INCLEANUP
Definition: ntuser.h:254
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:28

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: imm.c:17
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
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
Definition: input.c:480
PATTACHINFO gpai
Definition: input.c:17
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
struct _ATTACHINFO * paiNext
Definition: input.h:43
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
PTHREADINFO pti2
Definition: input.h:45
Status
Definition: gdiplustypes.h:24
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define NULL
Definition: types.h:112

Referenced by ExitThreadCallback().

◆ NtUserAttachThreadInput()

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

Definition at line 665 of file input.c.

669 {
671  PTHREADINFO pti, ptiTo;
672  BOOL Ret = FALSE;
673 
675  TRACE("Enter NtUserAttachThreadInput %s\n",(fAttach ? "TRUE" : "FALSE" ));
676 
677  pti = IntTID2PTI(UlongToHandle(idAttach));
678  ptiTo = IntTID2PTI(UlongToHandle(idAttachTo));
679 
680  if ( !pti || !ptiTo )
681  {
682  TRACE("AttachThreadInput pti or ptiTo NULL.\n");
684  goto Exit;
685  }
686 
687  Status = UserAttachThreadInput( pti, ptiTo, fAttach);
688  if (!NT_SUCCESS(Status))
689  {
690  TRACE("AttachThreadInput Error Status 0x%x. \n",Status);
692  }
693  else Ret = TRUE;
694 
695 Exit:
696  TRACE("Leave NtUserAttachThreadInput, ret=%d\n",Ret);
697  UserLeave();
698  return Ret;
699 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
Definition: input.c:480
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
PTHREADINFO FASTCALL IntTID2PTI(HANDLE id)
Definition: misc.c:42
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:249
Status
Definition: gdiplustypes.h:24
#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
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:258
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:28

◆ 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:249
#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:258

Referenced by BlockInput().

◆ NtUserSendInput()

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

Definition at line 708 of file input.c.

712 {
713  PTHREADINFO pti;
714  UINT uRet = 0;
715 
716  TRACE("Enter NtUserSendInput\n");
718 
720  ASSERT(pti);
721 
722  if (!pti->rpdesk)
723  {
724  goto cleanup;
725  }
726 
727  if (!nInputs || !pInput || cbSize != sizeof(INPUT))
728  {
730  goto cleanup;
731  }
732 
733  /*
734  * FIXME: Check access rights of the window station
735  * e.g. services running in the service window station cannot block input
736  */
737  if (!ThreadHasInputAccess(pti) ||
738  !IntIsActiveDesktop(pti->rpdesk))
739  {
741  goto cleanup;
742  }
743 
744  while (nInputs--)
745  {
746  INPUT SafeInput;
748 
749  Status = MmCopyFromCaller(&SafeInput, pInput++, sizeof(INPUT));
750  if (!NT_SUCCESS(Status))
751  {
753  goto cleanup;
754  }
755 
756  switch (SafeInput.type)
757  {
758  case INPUT_MOUSE:
759  if (UserSendMouseInput(&SafeInput.mi, TRUE))
760  uRet++;
761  break;
762  case INPUT_KEYBOARD:
763  if (UserSendKeyboardInput(&SafeInput.ki, TRUE))
764  uRet++;
765  break;
766  case INPUT_HARDWARE:
767  FIXME("INPUT_HARDWARE not supported!\n");
768  break;
769  default:
770  ERR("SendInput(): Invalid input type: 0x%x\n", SafeInput.type);
771  break;
772  }
773  }
774 
775 cleanup:
776  TRACE("Leave NtUserSendInput, ret=%u\n", uRet);
777  UserLeave();
778  return uRet;
779 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
BOOL NTAPI UserSendMouseInput(MOUSEINPUT *pMouseInput, BOOL bInjected)
Definition: mouse.c:168
#define TRUE
Definition: types.h:120
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:88
MOUSEINPUT mi
Definition: winable.h:61
#define INPUT_KEYBOARD
Definition: winable.h:10
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define ThreadHasInputAccess(W32Thread)
Definition: input.h:68
#define FIXME(fmt,...)
Definition: debug.h:111
#define INPUT_MOUSE
Definition: winable.h:9
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:249
Status
Definition: gdiplustypes.h:24
#define TRACE(s)
Definition: solgame.cpp:4
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define IntIsActiveDesktop(Desktop)
Definition: desktop.h:172
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:37
#define ERR(fmt,...)
Definition: debug.h:110
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:258
BOOL NTAPI UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
Definition: keyboard.c:986
#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:28
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
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3272
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:494
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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
#define NULL
Definition: types.h:112
return Iosb
Definition: create.c:4402
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106

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)
static NTSTATUS NTAPI OpenInputDevice(PHANDLE pHandle, PFILE_OBJECT *ppObject, CONST WCHAR *pszDeviceName)
Definition: input.c:88
POBJECT_TYPE ExWindowStationObjectType
Definition: win32k.c:21
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
#define TRUE
Definition: types.h:120
static HANDLE ghMouseDevice
Definition: input.c:22
VOID FASTCALL StartTheTimers(VOID)
Definition: timer.c:368
FLONG TIF_flags
Definition: win32.h:91
PWINSTATION_OBJECT InputWindowStation
Definition: winsta.c:21
#define PWND_BOTTOM
Definition: ntuser.h:748
LONG NTSTATUS
Definition: precomp.h:26
#define VK_LEFT
Definition: winuser.h:2214
#define LOW_REALTIME_PRIORITY
#define VK_DOWN
Definition: winuser.h:2217
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:2742
#define TIF_SYSTEMTHREAD
Definition: ntuser.h:256
HANDLE ghKeyboardDevice
Definition: input.c:19
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:801
VOID FASTCALL StartDebugHotKeys(VOID)
Definition: hotkey.c:44
NTSTATUS NTAPI PoRequestShutdownEvent(OUT PVOID *Event)
Definition: poshtdwn.c:399
#define STATUS_WAIT_0
Definition: ntstatus.h:237
#define L(x)
Definition: ntvdm.h:50
#define VK_UP
Definition: winuser.h:2215
#define IDHK_SNAP_RIGHT
Definition: hotkey.h:21
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
static HANDLE ShutdownEvent
Definition: dcomlaunch.c:28
PTHREADINFO ptiRawInput
Definition: input.c:15
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:249
Status
Definition: gdiplustypes.h:24
int64_t LONGLONG
Definition: typedefs.h:68
#define TRACE(s)
Definition: solgame.cpp:4
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define IDHK_SNAP_UP
Definition: hotkey.h:22
#define ObDereferenceObject
Definition: obfuncs.h:203
VOID NTAPI UserProcessMouseInput(PMOUSE_INPUT_DATA pMouseInputData)
Definition: mouse.c:40
* PFILE_OBJECT
Definition: iotypes.h:1998
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:90
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
BOOL FASTCALL UserSetProcessWindowStation(HWINSTA hWindowStation)
Definition: winsta.c:1382
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:454
BOOL FASTCALL UserRegisterHotKey(PWND pWnd, int id, UINT fsModifiers, UINT vk)
Definition: hotkey.c:431
#define VK_RIGHT
Definition: winuser.h:2216
#define ERR(fmt,...)
Definition: debug.h:110
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:258
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:1067
#define NULL
Definition: types.h:112
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:2634
#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:725
static DWORD FASTCALL IntLastInputTick(BOOL bUpdate)
Definition: input.c:32
#define NT_ASSERT
Definition: rtlfuncs.h:3310

Referenced by UserSystemThreadProc().

◆ UserAttachThreadInput()

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

Definition at line 480 of file input.c.

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

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().