ReactOS 0.4.17-dev-1321-g5c122a9
input.c File Reference
#include <win32k.h>
Include dependency graph for input.c:

Go to the source code of this file.

Macros

#define LAST_RIT_EVENT_UPDATE_INTERVAL   1000UL
 

Functions

 DBG_DEFAULT_CHANNEL (UserInput)
 
static VOID NTAPI RITReadApc (_In_ PVOID ApcContext, _In_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG Reserved)
 
static DWORD FASTCALL IntLastInputTick (BOOL bUpdate)
 
VOID FASTCALL DoTheScreenSaver (VOID)
 
static PINPUT_DEVICE_INFO CreateInputDevice (_In_ UCHAR DeviceType, _In_ PUNICODE_STRING DeviceName)
 
static NTSTATUS NTAPI OpenInputDevice (_In_ PINPUT_DEVICE_INFO DeviceInfo)
 
static VOID CloseInputDevice (_In_ PINPUT_DEVICE_INFO DeviceInfo)
 
static VOID StartReadInputDevice (_In_ PINPUT_DEVICE_INFO DeviceInfo)
 
static VOID ProcessDeviceChanges (VOID)
 
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
 
PINPUT_DEVICE_INFO gpInputDeviceInfo = NULL
 
PERESOURCE gpDeviceInfoListMutex = NULL
 
static DWORD LastInputTick = 0
 
static PKEVENT gDeviceListChangedEvent
 

Macro Definition Documentation

◆ LAST_RIT_EVENT_UPDATE_INTERVAL

#define LAST_RIT_EVENT_UPDATE_INTERVAL   1000UL

Definition at line 17 of file input.c.

Function Documentation

◆ CloseInputDevice()

static VOID CloseInputDevice ( _In_ PINPUT_DEVICE_INFO  DeviceInfo)
static

Definition at line 212 of file input.c.

214{
215 ASSERT(DeviceInfo->Handle);
216 (void)ZwCancelIoFile(DeviceInfo->Handle, &DeviceInfo->Iosb);
218
219 if (DeviceInfo->Handle == ghKeyboardDevice)
221}
#define NULL
Definition: types.h:112
#define ASSERT(a)
Definition: mode.c:44
#define KernelMode
Definition: asm.h:38
NTSYSAPI NTSTATUS NTAPI ZwCancelIoFile(_In_ HANDLE FileHandle, _Out_ PIO_STATUS_BLOCK IoStatusBlock)
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3411
HANDLE ghKeyboardDevice
Definition: input.c:33

Referenced by RawInputThreadMain().

◆ CreateInputDevice()

static PINPUT_DEVICE_INFO CreateInputDevice ( _In_ UCHAR  DeviceType,
_In_ PUNICODE_STRING  DeviceName 
)
static

Definition at line 114 of file input.c.

117{
119
121 if (!DeviceInfo)
122 {
123 ERR("Failed to allocate memory for INPUT_DEVICE_INFO\n");
124 return NULL;
125 }
126
128 DeviceInfo->DeviceType = DeviceType;
129 DeviceInfo->DeviceName.Buffer = (PWCH)(DeviceInfo + 1);
130 DeviceInfo->DeviceName.MaximumLength = DeviceName->Length + sizeof(UNICODE_NULL);
132
134 DeviceInfo->pNextDeviceInfo = gpInputDeviceInfo;
137
139 return DeviceInfo;
140}
#define ERR(fmt,...)
Definition: precomp.h:57
#define FALSE
Definition: types.h:117
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define PagedPool
Definition: env_spec_w32.h:308
DeviceType
Definition: mmdrv.h:42
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
WCHAR * PWCH
Definition: ntbasedef.h:422
#define UNICODE_NULL
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3281
static PKEVENT gDeviceListChangedEvent
Definition: input.c:38
PINPUT_DEVICE_INFO gpInputDeviceInfo
Definition: input.c:34
FORCEINLINE VOID ReleaseDeviceInfoListMutex(VOID)
Definition: input.h:165
FORCEINLINE VOID AcquireDeviceInfoListMutex(VOID)
Definition: input.h:157
#define USERTAG_PNP
Definition: tags.h:264
#define EVENT_INCREMENT
Definition: iotypes.h:597

Referenced by RawInputThreadMain().

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( UserInput  )

◆ DoTheScreenSaver()

VOID FASTCALL DoTheScreenSaver ( VOID  )

Definition at line 73 of file input.c.

74{
75 DWORD Test, TO;
76
77 if (gspv.iScrSaverTimeout > 0) // Zero means Off.
78 {
81 TO = 1000 * gspv.iScrSaverTimeout;
82 if (Test > TO)
83 {
84 TRACE("Screensaver Message Start! Tick %lu Timeout %d \n", Test, gspv.iScrSaverTimeout);
85
86 if (ppiScrnSaver) // We are or we are not the screensaver, prevent reentry...
87 {
88 if (!(ppiScrnSaver->W32PF_flags & W32PF_IDLESCREENSAVER))
89 {
90 ppiScrnSaver->W32PF_flags |= W32PF_IDLESCREENSAVER;
91 ERR("Screensaver is Idle\n");
92 }
93 }
94 else
95 {
97 if (ForegroundQueue && ForegroundQueue->spwndActive)
99 else
101 }
102 }
103 }
104}
#define EngGetTickCount32()
Definition: eng.h:43
unsigned long DWORD
Definition: ntddk_ex.h:95
HWND hwndSAS
Definition: winsta.c:24
#define TRACE(s)
Definition: solgame.cpp:4
INT iScrSaverTimeout
Definition: sysparams.h:110
#define WM_LOGONNOTIFY
Definition: undocuser.h:39
#define LN_START_SCREENSAVE
Definition: undocuser.h:122
#define W32PF_IDLESCREENSAVER
Definition: win32.h:27
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1335
static DWORD LastInputTick
Definition: input.c:37
PPROCESSINFO ppiScrnSaver
Definition: main.c:30
BOOL FASTCALL UserPostMessage(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1397
SPIVALUES gspv
Definition: sysparams.c:17

Referenced by HungAppSysTimerProc().

◆ InitInputImpl()

NTSTATUS NTAPI InitInputImpl ( VOID  )

Definition at line 537 of file input.c.

538{
540 if (!MasterTimer)
541 {
542 ERR("Failed to allocate memory\n");
543 ASSERT(FALSE);
544 return STATUS_UNSUCCESSFUL;
545 }
547
548 return STATUS_SUCCESS;
549}
#define NonPagedPool
Definition: env_spec_w32.h:307
#define STATUS_SUCCESS
Definition: shellext.h:65
VOID NTAPI KeInitializeTimer(OUT PKTIMER Timer)
Definition: timerobj.c:233
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
PKTIMER MasterTimer
Definition: input.c:30
#define USERTAG_SYSTEM
Definition: tags.h:282

Referenced by DriverEntry().

◆ IntBlockInput()

BOOL FASTCALL IntBlockInput ( PTHREADINFO  pti,
BOOL  BlockIt 
)

Definition at line 552 of file input.c.

553{
554 PTHREADINFO OldBlock;
555 ASSERT(pti);
556
557 if(!pti->rpdesk || ((pti->TIF_flags & TIF_INCLEANUP) && BlockIt))
558 {
559 /*
560 * Fail blocking if exiting the thread
561 */
562
563 return FALSE;
564 }
565
566 /*
567 * FIXME: Check access rights of the window station
568 * e.g. services running in the service window station cannot block input
569 */
570 if(!ThreadHasInputAccess(pti) ||
572 {
574 return FALSE;
575 }
576
577 ASSERT(pti->rpdesk);
578 OldBlock = pti->rpdesk->BlockInputThread;
579 if(OldBlock)
580 {
581 if(OldBlock != pti)
582 {
584 return FALSE;
585 }
586 pti->rpdesk->BlockInputThread = (BlockIt ? pti : NULL);
587 return OldBlock == NULL;
588 }
589
590 pti->rpdesk->BlockInputThread = (BlockIt ? pti : NULL);
591 return OldBlock == NULL;
592}
#define IntIsActiveDesktop(Desktop)
Definition: desktop.h:174
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define TIF_INCLEANUP
Definition: ntuser.h:266
FLONG TIF_flags
Definition: win32.h:96
struct _DESKTOP * rpdesk
Definition: win32.h:93
#define ThreadHasInputAccess(W32Thread)
Definition: input.h:103
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:21

Referenced by ExitThreadCallback(), and NtUserBlockInput().

◆ IntLastInputTick()

static DWORD FASTCALL IntLastInputTick ( BOOL  bUpdate)
static

Definition at line 48 of file input.c.

49{
50 if (bUpdate)
51 {
53 if (gpsi)
54 {
55 gpsi->dwLastRITEventTickCount = LastInputTick;
56 if (gpsi->dwLastRITEventTickCount - gpsi->dwLastSystemRITEventTickCountUpdate >
58 {
59 SharedUserData->LastSystemRITEventTickCount = LastInputTick;
60 gpsi->dwLastSystemRITEventTickCountUpdate = LastInputTick;
61 }
62 }
63 }
64 return LastInputTick;
65}
PSERVERINFO gpsi
Definition: imm.c:18
#define SharedUserData
#define LAST_RIT_EVENT_UPDATE_INTERVAL
Definition: input.c:17

Referenced by RITReadApc().

◆ IsRemoveAttachThread()

BOOL FASTCALL IsRemoveAttachThread ( PTHREADINFO  pti)

Definition at line 614 of file input.c.

615{
617 PATTACHINFO pai;
618 BOOL Ret = TRUE;
619 PTHREADINFO ptiFrom = NULL, ptiTo = NULL;
620
621 do
622 {
623 if (!gpai) return TRUE;
624
625 pai = gpai; // Bottom of the list.
626
627 do
628 {
629 if (pai->pti2 == pti)
630 {
631 ptiFrom = pai->pti1;
632 ptiTo = pti;
633 break;
634 }
635 if (pai->pti1 == pti)
636 {
637 ptiFrom = pti;
638 ptiTo = pai->pti2;
639 break;
640 }
641 pai = pai->paiNext;
642
643 } while (pai);
644
645 if (!pai && !ptiFrom && !ptiTo) break;
646
647 Status = UserAttachThreadInput(ptiFrom, ptiTo, FALSE);
648 if (!NT_SUCCESS(Status)) Ret = FALSE;
649
650 } while (Ret);
651
652 return Ret;
653}
LONG NTSTATUS
Definition: precomp.h:26
#define TRUE
Definition: types.h:120
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
unsigned int BOOL
Definition: ntddk_ex.h:94
Status
Definition: gdiplustypes.h:24
PTHREADINFO pti2
Definition: input.h:46
struct _ATTACHINFO * paiNext
Definition: input.h:44
PTHREADINFO pti1
Definition: input.h:45
PATTACHINFO gpai
Definition: input.c:31
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO ptiFrom, PTHREADINFO ptiTo, BOOL fAttach)
Definition: input.c:656

Referenced by ExitThreadCallback().

◆ NtUserAttachThreadInput()

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

Definition at line 841 of file input.c.

845{
847 PTHREADINFO pti, ptiTo;
848 BOOL Ret = FALSE;
849
851 TRACE("Enter NtUserAttachThreadInput %s\n",(fAttach ? "TRUE" : "FALSE" ));
852
853 pti = IntTID2PTI(UlongToHandle(idAttach));
854 ptiTo = IntTID2PTI(UlongToHandle(idAttachTo));
855
856 if ( !pti || !ptiTo )
857 {
858 TRACE("AttachThreadInput pti or ptiTo NULL.\n");
860 goto Exit;
861 }
862
863 Status = UserAttachThreadInput( pti, ptiTo, fAttach);
864 if (!NT_SUCCESS(Status))
865 {
866 TRACE("AttachThreadInput Error Status 0x%x. \n",Status);
868 }
869 else Ret = TRUE;
870
871Exit:
872 TRACE("Leave NtUserAttachThreadInput, ret=%d\n",Ret);
873 UserLeave();
874 return Ret;
875}
#define UlongToHandle(ul)
Definition: basetsd.h:91
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
static void Exit(void)
Definition: sock.c:1330
PTHREADINFO FASTCALL IntTID2PTI(HANDLE id)
Definition: misc.c:41
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)

◆ NtUserBlockInput()

BOOL APIENTRY NtUserBlockInput ( BOOL  BlockIt)

Definition at line 596 of file input.c.

598{
599 BOOL ret;
600
601 TRACE("Enter NtUserBlockInput\n");
603
605
606 UserLeave();
607 TRACE("Leave NtUserBlockInput, ret=%i\n", ret);
608
609 return ret;
610}
return ret
Definition: mutex.c:147
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:829
BOOL FASTCALL IntBlockInput(PTHREADINFO pti, BOOL BlockIt)
Definition: input.c:552

Referenced by BlockInput().

◆ NtUserSendInput()

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

Definition at line 884 of file input.c.

888{
889 PTHREADINFO pti;
890 UINT uRet = 0;
891
892 TRACE("Enter NtUserSendInput\n");
894
896 ASSERT(pti);
897
898 if (!pti->rpdesk)
899 {
900 goto cleanup;
901 }
902
903 if (!nInputs || !pInput || cbSize != sizeof(INPUT))
904 {
906 goto cleanup;
907 }
908
909 /*
910 * FIXME: Check access rights of the window station
911 * e.g. services running in the service window station cannot block input
912 */
913 if (!ThreadHasInputAccess(pti) ||
915 {
917 goto cleanup;
918 }
919
920 while (nInputs--)
921 {
922 INPUT SafeInput;
924
925 Status = MmCopyFromCaller(&SafeInput, pInput++, sizeof(INPUT));
926 if (!NT_SUCCESS(Status))
927 {
929 goto cleanup;
930 }
931
932 switch (SafeInput.type)
933 {
934 case INPUT_MOUSE:
935 if (UserSendMouseInput(&SafeInput.mi, TRUE))
936 uRet++;
937 break;
938 case INPUT_KEYBOARD:
939 if (UserSendKeyboardInput(&SafeInput.ki, TRUE))
940 uRet++;
941 break;
942 case INPUT_HARDWARE:
943 FIXME("INPUT_HARDWARE not supported!\n");
944 break;
945 default:
946 ERR("SendInput(): Invalid input type: 0x%x\n", SafeInput.type);
947 break;
948 }
949 }
950
951cleanup:
952 TRACE("Leave NtUserSendInput, ret=%u\n", uRet);
953 UserLeave();
954 return uRet;
955}
#define FIXME(fmt,...)
Definition: precomp.h:53
static void cleanup(void)
Definition: main.c:1335
unsigned int UINT
Definition: sysinfo.c:13
#define MmCopyFromCaller
Definition: polytest.cpp:29
KEYBDINPUT ki
Definition: winable.h:62
DWORD type
Definition: winable.h:59
MOUSEINPUT mi
Definition: winable.h:61
UINT32 cbSize
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:30
BOOL NTAPI UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
Definition: keyboard.c:1314
BOOL NTAPI UserSendMouseInput(MOUSEINPUT *pMouseInput, BOOL bInjected)
Definition: mouse.c:235
#define INPUT_HARDWARE
Definition: winable.h:11
#define INPUT_KEYBOARD
Definition: winable.h:10
#define INPUT_MOUSE
Definition: winable.h:9

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

◆ OpenInputDevice()

static NTSTATUS NTAPI OpenInputDevice ( _In_ PINPUT_DEVICE_INFO  DeviceInfo)
static

Definition at line 149 of file input.c.

151{
155
157 &DeviceInfo->DeviceName,
159 NULL,
160 NULL);
161
162 Status = ZwOpenFile(&DeviceInfo->Handle,
165 &Iosb,
166 0,
167 0);
168 if (!NT_SUCCESS(Status))
169 {
170 ERR("ZwOpenFile('%wZ') failed with status 0x%08x\n", &DeviceInfo->DeviceName, Status);
171 return Status;
172 }
173
174 if (DeviceInfo->DeviceType == RIM_TYPEKEYBOARD)
175 {
177 NULL,
178 NULL,
179 NULL,
180 &DeviceInfo->Iosb,
182 NULL, 0,
183 &DeviceInfo->Keyboard.Attributes,
184 sizeof(DeviceInfo->Keyboard.Attributes));
185 if (!NT_SUCCESS(Status))
186 {
187 ERR("ZwDeviceIoControlFile('%wZ', IOCTL_KEYBOARD_QUERY_ATTRIBUTES) failed with status 0x%08x\n", &DeviceInfo->DeviceName, Status);
188 }
189 }
190 else if (DeviceInfo->DeviceType == RIM_TYPEMOUSE)
191 {
193 NULL,
194 NULL,
195 NULL,
196 &DeviceInfo->Iosb,
198 NULL, 0,
199 &DeviceInfo->Mouse.Attributes,
200 sizeof(DeviceInfo->Mouse.Attributes));
201 if (!NT_SUCCESS(Status))
202 {
203 ERR("ZwDeviceIoControlFile('%wZ', IOCTL_MOUSE_QUERY_ATTRIBUTES) failed with status 0x%08x\n", &DeviceInfo->DeviceName, Status);
204 }
205 }
206
207 return STATUS_SUCCESS;
208}
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
return Iosb
Definition: create.c:4403
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
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 FILE_ALL_ACCESS
Definition: nt_native.h:651
#define IOCTL_KEYBOARD_QUERY_ATTRIBUTES
Definition: ntddkbd.h:32
#define IOCTL_MOUSE_QUERY_ATTRIBUTES
Definition: ntddmou.h:32
NTSYSAPI NTSTATUS NTAPI ZwDeviceIoControlFile(IN HANDLE DeviceHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, IN PVOID UserApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer, IN ULONG InputBufferSize, OUT PVOID OutputBuffer, IN ULONG OutputBufferSize)
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231

Referenced by ProcessDeviceChanges().

◆ ProcessDeviceChanges()

static VOID ProcessDeviceChanges ( VOID  )
static

Definition at line 303 of file input.c.

305{
308 DWORD NumberOfMice = 0;
309 DWORD MaxNumberOfButtons = 0;
310 BOOL HasMouseWheel = FALSE;
311#if (_WIN32_WINNT >= 0x0600)
312 BOOL HasHorizontalMouseWheel = FALSE;
313#endif
314 DWORD MaxFunctionKeys = 0;
315
317 for (DeviceInfo = gpInputDeviceInfo; DeviceInfo; DeviceInfo = DeviceInfo->pNextDeviceInfo)
318 {
319 if (!DeviceInfo->Handle)
320 {
322 if (NT_SUCCESS(Status))
323 {
324 if (DeviceInfo->DeviceType == RIM_TYPEKEYBOARD)
325 {
326 TRACE("Keyboard connected!\n");
327 if (!ghKeyboardDevice)
328 {
329 // Get and load keyboard attributes.
332 // Register the Window hotkey.
334 // Register the Window Snap hotkey.
339 // Register the debug hotkeys.
341 UserLeave();
342 }
343 }
344 else if (DeviceInfo->DeviceType == RIM_TYPEMOUSE)
345 {
346 TRACE("Mouse connected!\n");
347 }
349 }
350 }
351
352 if (DeviceInfo->DeviceType == RIM_TYPEKEYBOARD)
353 {
354 if (DeviceInfo->Keyboard.Attributes.KeyboardIdentifier.Type == 4 /* Enhanced 101- or 102-key keyboard */ ||
355 DeviceInfo->Keyboard.Attributes.KeyboardIdentifier.Type == 7 /* Japanese keyboard */ ||
356 DeviceInfo->Keyboard.Attributes.KeyboardIdentifier.Type == 8 /* Korean keyboard */)
357 {
358 DWORD FunctionKeys = DeviceInfo->Keyboard.Attributes.NumberOfFunctionKeys;
359 /* Keep current keyboard description */
360 gKeyboardInfo = DeviceInfo->Keyboard.Attributes;
361 if (FunctionKeys > MaxFunctionKeys)
362 MaxFunctionKeys = FunctionKeys;
363 }
364 }
365 else if (DeviceInfo->DeviceType == RIM_TYPEMOUSE)
366 {
367 DWORD MouseIdentifier = DeviceInfo->Mouse.Attributes.MouseIdentifier & ~HORIZONTAL_WHEEL_PRESENT;
368 DWORD NumberOfButtons = DeviceInfo->Mouse.Attributes.NumberOfButtons;
369
370 NumberOfMice++;
371 if (NumberOfButtons > MaxNumberOfButtons)
372 MaxNumberOfButtons = NumberOfButtons;
373 HasMouseWheel |= MouseIdentifier == WHEELMOUSE_I8042_HARDWARE
374 || MouseIdentifier == WHEELMOUSE_SERIAL_HARDWARE
375 || MouseIdentifier == WHEELMOUSE_HID_HARDWARE;
376#if (_WIN32_WINNT >= 0x0600)
377 HasHorizontalMouseWheel |= DeviceInfo->Mouse.Attributes.MouseIdentifier & HORIZONTAL_WHEEL_PRESENT;
378#endif
379 }
380 }
382
383 /* Update metrics */
384 gpsi->aiSysMet[SM_MOUSEPRESENT] = NumberOfMice > 0 ? 1 : 0;
385 gpsi->aiSysMet[SM_CMOUSEBUTTONS] = MaxNumberOfButtons;
386 gpsi->aiSysMet[SM_MOUSEWHEELPRESENT] = HasMouseWheel ? 1 : 0;
387#if (_WIN32_WINNT >= 0x0600)
388 gpsi->aiSysMet[SM_MOUSEHORIZONTALWHEELPRESENT] = HasHorizontalMouseWheel ? 1 : 0;
389#endif
390 /* FIXME: show/hide cursor depending of mouse presence */
391 TRACE("Mouse present %u, buttons %u, wheel %u\n",
392 gpsi->aiSysMet[SM_MOUSEPRESENT],
393 gpsi->aiSysMet[SM_CMOUSEBUTTONS],
394 gpsi->aiSysMet[SM_MOUSEWHEELPRESENT]);
395
396 gKeyboardInfo.NumberOfFunctionKeys = MaxFunctionKeys;
397 TRACE("Keyboard type %u, subtype %u and number of func keys %u\n",
401}
#define IDHK_SNAP_LEFT
Definition: hotkey.h:20
#define IDHK_WINKEY
Definition: hotkey.h:16
#define IDHK_SNAP_UP
Definition: hotkey.h:22
#define IDHK_SNAP_DOWN
Definition: hotkey.h:23
#define IDHK_SNAP_RIGHT
Definition: hotkey.h:21
#define PWND_BOTTOM
Definition: ntuser.h:773
#define WHEELMOUSE_I8042_HARDWARE
Definition: ntddmou.h:102
#define WHEELMOUSE_SERIAL_HARDWARE
Definition: ntddmou.h:103
#define HORIZONTAL_WHEEL_PRESENT
Definition: ntddmou.h:106
#define WHEELMOUSE_HID_HARDWARE
Definition: ntddmou.h:105
#define SM_CMOUSEBUTTONS
Definition: winuser.h:1017
#define MOD_WIN
Definition: winuser.h:2686
#define SM_MOUSEPRESENT
Definition: winuser.h:991
#define SM_MOUSEWHEELPRESENT
Definition: winuser.h:1046
#define VK_UP
Definition: winuser.h:2261
#define VK_LEFT
Definition: winuser.h:2260
#define VK_RIGHT
Definition: winuser.h:2262
#define VK_DOWN
Definition: winuser.h:2263
KEYBOARD_ID KeyboardIdentifier
Definition: ntddkbd.h:124
USHORT NumberOfFunctionKeys
Definition: ntddkbd.h:126
UCHAR Subtype
Definition: ntddkbd.h:102
UCHAR Type
Definition: ntddkbd.h:101
BOOL FASTCALL UserRegisterHotKey(PWND pWnd, int id, UINT fsModifiers, UINT vk)
Definition: hotkey.c:447
VOID FASTCALL SetDebugHotKeys(VOID)
Definition: hotkey.c:46
static NTSTATUS NTAPI OpenInputDevice(_In_ PINPUT_DEVICE_INFO DeviceInfo)
Definition: input.c:149
static VOID StartReadInputDevice(_In_ PINPUT_DEVICE_INFO DeviceInfo)
Definition: input.c:225
KEYBOARD_ATTRIBUTES gKeyboardInfo
Definition: keyboard.c:17
VOID NTAPI UserInitKeyboard(HANDLE hKeyboardDevice)
Definition: keyboard.c:178

Referenced by RawInputThreadMain().

◆ RawInputThreadMain()

VOID NTAPI RawInputThreadMain ( VOID  )

Definition at line 409 of file input.c.

410{
413 //LARGE_INTEGER WaitTimeout;
414 PVOID WaitObjects[3], pSignaledObject = NULL;
417 HWINSTA hWinSta;
420 UNICODE_STRING LegacyMouseName = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");
421 UNICODE_STRING LegacyKeyboardName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass0");
422
426
427 //WaitTimeout.QuadPart = (LONGLONG)(-10000000);
428
432
433 TRACE("Raw Input Thread %p\n", ptiRawInput);
434
437
439 0,
440 NULL,
443 UserMode,
444 (PHANDLE)&hWinSta);
445 if (NT_SUCCESS(Status))
446 {
448 }
449 else
450 {
451 ASSERT(FALSE);
452 /* Failed to open the interactive winsta! What now? */
453 }
454
459
460 Mouse = CreateInputDevice(RIM_TYPEMOUSE, &LegacyMouseName);
461 ASSERT(Mouse);
462 Keyboard = CreateInputDevice(RIM_TYPEKEYBOARD, &LegacyKeyboardName);
464
467 UserLeave();
468
470 ghKeyboardDevice = Keyboard->Handle;
471
473 for (;;)
474 {
475 /* Reset WaitHandles array */
476 WaitObjects[0] = ShutdownEvent;
477 WaitObjects[1] = MasterTimer;
478 WaitObjects[2] = gDeviceListChangedEvent;
479
481 WaitObjects,
482 WaitAny,
485 TRUE,
486 NULL,//&WaitTimeout,
488
489 if ((Status >= STATUS_WAIT_0) &&
490 (Status < (STATUS_WAIT_0 + RTL_NUMBER_OF(WaitObjects))))
491 {
492 /* Some device has finished reading */
493 pSignaledObject = WaitObjects[Status - STATUS_WAIT_0];
494
495 if (pSignaledObject == gDeviceListChangedEvent)
496 {
498 }
499 else if (pSignaledObject == MasterTimer)
500 {
502 }
503 else if (pSignaledObject == ShutdownEvent)
504 {
505 break;
506 }
507 else ASSERT(FALSE);
508 }
509 }
510
512 while (gpInputDeviceInfo)
513 {
515 gpInputDeviceInfo = DeviceInfo->pNextDeviceInfo;
518 }
521
525
526 ERR("Raw Input Thread Exit!\n");
527}
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
static HANDLE ShutdownEvent
Definition: dcomlaunch.c:28
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#define L(x)
Definition: resources.c:13
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define ExDeleteResourceLite(res)
Definition: env_spec_w32.h:647
_Must_inspect_result_ _In_ WAIT_TYPE _In_opt_ PLARGE_INTEGER _In_opt_ PKWAIT_BLOCK WaitBlockArray
Definition: fsrtlfuncs.h:1153
@ Keyboard
Definition: i8042prt.h:115
@ Mouse
Definition: i8042prt.h:116
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:806
#define TIF_SYSTEMTHREAD
Definition: ntuser.h:268
#define LOW_REALTIME_PRIORITY
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define UserMode
Definition: asm.h:39
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
@ SynchronizationEvent
@ WaitAny
NTSTATUS NTAPI KeWaitForMultipleObjects(IN ULONG Count, IN PVOID Object[], IN WAIT_TYPE WaitType, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL, OUT PKWAIT_BLOCK WaitBlockArray OPTIONAL)
Definition: wait.c:599
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_WAIT_0
Definition: ntstatus.h:330
PWINSTATION_OBJECT InputWindowStation
Definition: winsta.c:21
BOOL FASTCALL UserSetProcessWindowStation(HWINSTA hWindowStation)
Definition: winsta.c:1614
NTSTATUS NTAPI ObOpenObjectByPointer(IN PVOID Object, IN ULONG HandleAttributes, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PHANDLE Handle)
Definition: obhandle.c:2769
NTSTATUS NTAPI PoRequestShutdownEvent(OUT PVOID *Event)
Definition: poshtdwn.c:384
struct _CLIENTINFO * pClientInfo
Definition: win32.h:95
KPRIORITY NTAPI KeSetPriorityThread(IN PKTHREAD Thread, IN KPRIORITY Priority)
Definition: thrdobj.c:1300
POBJECT_TYPE ExWindowStationObjectType
Definition: win32k.c:21
static PINPUT_DEVICE_INFO CreateInputDevice(_In_ UCHAR DeviceType, _In_ PUNICODE_STRING DeviceName)
Definition: input.c:114
PTHREADINFO ptiRawInput
Definition: input.c:29
static VOID ProcessDeviceChanges(VOID)
Definition: input.c:303
static VOID CloseInputDevice(_In_ PINPUT_DEVICE_INFO DeviceInfo)
Definition: input.c:212
PERESOURCE gpDeviceInfoListMutex
Definition: input.c:35
VOID FASTCALL ProcessTimers(VOID)
Definition: timer.c:452
VOID FASTCALL StartTheTimers(VOID)
Definition: timer.c:374
@ UserRequest
Definition: ketypes.h:473
#define NT_ASSERT
Definition: rtlfuncs.h:3334

Referenced by UserSystemThreadProc().

◆ RITReadApc()

static VOID NTAPI RITReadApc ( _In_ PVOID  ApcContext,
_In_ PIO_STATUS_BLOCK  IoStatusBlock,
_In_ ULONG  Reserved 
)
static

Definition at line 261 of file input.c.

265{
267
268 if (DeviceInfo->Handle && NT_SUCCESS(IoStatusBlock->Status))
269 {
270 if (DeviceInfo->DeviceType == RIM_TYPEKEYBOARD)
271 {
272 TRACE("KeyboardEvent: %s %04x\n",
273 (DeviceInfo->Keyboard.Data.Flags & KEY_BREAK) ? "up" : "down",
274 DeviceInfo->Keyboard.Data.MakeCode);
275
276 /* Set LastInputTick */
278
279 /* Process data */
282 UserLeave();
283 }
284 else if (DeviceInfo->DeviceType == RIM_TYPEMOUSE)
285 {
286 TRACE("MouseEvent\n");
287
288 /* Set LastInputTick */
290
291 /* Process data */
294 UserLeave();
295 }
296 }
297
299}
_In_ PIO_STATUS_BLOCK IoStatusBlock
Definition: dispmprt.h:608
_In_opt_ HANDLE _In_opt_ PIO_APC_ROUTINE _In_opt_ PVOID ApcContext
Definition: iofuncs.h:727
#define KEY_BREAK
Definition: ntddkbd.h:71
WCHAR Data[ANYSIZE_ARRAY]
static DWORD FASTCALL IntLastInputTick(BOOL bUpdate)
Definition: input.c:48
VOID NTAPI UserProcessKeyboardInput(PINPUT_DEVICE_INFO pDeviceInfo, PKEYBOARD_INPUT_DATA pKeyInput)
Definition: keyboard.c:1455
VOID NTAPI UserProcessMouseInput(PINPUT_DEVICE_INFO pDeviceInfo, PMOUSE_INPUT_DATA pMouseInputData)
Definition: mouse.c:104

Referenced by StartReadInputDevice().

◆ StartReadInputDevice()

static VOID StartReadInputDevice ( _In_ PINPUT_DEVICE_INFO  DeviceInfo)
static

Definition at line 225 of file input.c.

227{
231
232 ByteOffset.QuadPart = (LONGLONG)0;
233
234 if (DeviceInfo->DeviceType == RIM_TYPEKEYBOARD)
235 {
236 Buffer = &DeviceInfo->Keyboard.Data,
237 BufferSize = sizeof(DeviceInfo->Keyboard.Data);
238 }
239 else if (DeviceInfo->DeviceType == RIM_TYPEMOUSE)
240 {
241 Buffer = &DeviceInfo->Mouse.Data,
242 BufferSize = sizeof(DeviceInfo->Mouse.Data);
243 }
244 else
245 return;
246
247 DeviceInfo->Status = ZwReadFile(
248 DeviceInfo->Handle,
249 NULL,
252 &DeviceInfo->Iosb,
253 Buffer,
255 &ByteOffset,
256 NULL);
257}
Definition: bufpool.h:45
#define BufferSize
Definition: mmc.h:75
_In_ ULONG BufferSize
Definition: dispmprt.h:490
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:732
int64_t LONGLONG
Definition: typedefs.h:68
ULONG_PTR SIZE_T
Definition: typedefs.h:80
static VOID NTAPI RITReadApc(_In_ PVOID ApcContext, _In_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG Reserved)
Definition: input.c:261

Referenced by ProcessDeviceChanges(), and RITReadApc().

◆ UserAttachThreadInput()

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

Definition at line 656 of file input.c.

657{
658 MSG msg;
659 PATTACHINFO pai;
660 PCURICON_OBJECT CurIcon;
661
662 /* Can not be the same thread. */
663 if (ptiFrom == ptiTo) return STATUS_INVALID_PARAMETER;
664
665 /* Do not attach to system threads or between different desktops. */
666 if (ptiFrom->TIF_flags & TIF_DONTATTACHQUEUE ||
668 ptiFrom->rpdesk != ptiTo->rpdesk)
670
671 /* MSDN Note:
672 Keyboard and mouse events received by both threads are processed by the thread specified by the idAttachTo.
673 */
674
675 /* If Attach set, allocate and link. */
676 if (fAttach)
677 {
679 if (!pai) return STATUS_NO_MEMORY;
680
681 pai->paiNext = gpai;
682 pai->pti1 = ptiFrom;
683 pai->pti2 = ptiTo;
684 gpai = pai;
685 paiCount++;
686 ERR("Attach Allocated! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
687
688 if (ptiTo->MessageQueue != ptiFrom->MessageQueue)
689 {
690
691 ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
692
693 if (ptiFrom->MessageQueue == gpqForeground)
694 {
695 ERR("ptiFrom is Foreground\n");
696 ptiTo->MessageQueue->spwndActive = ptiFrom->MessageQueue->spwndActive;
697 ptiTo->MessageQueue->spwndFocus = ptiFrom->MessageQueue->spwndFocus;
698 ptiTo->MessageQueue->spwndCapture = ptiFrom->MessageQueue->spwndCapture;
699 ptiTo->MessageQueue->QF_flags ^= ((ptiTo->MessageQueue->QF_flags ^ ptiFrom->MessageQueue->QF_flags) & QF_CAPTURELOCKED);
700 RtlCopyMemory(&ptiTo->MessageQueue->CaretInfo,
701 &ptiFrom->MessageQueue->CaretInfo,
702 sizeof(ptiTo->MessageQueue->CaretInfo));
705 gptiForeground = ptiTo;
706 }
707 else
708 {
709 ERR("ptiFrom NOT Foreground\n");
710 if ( ptiTo->MessageQueue->spwndActive == 0 )
711 ptiTo->MessageQueue->spwndActive = ptiFrom->MessageQueue->spwndActive;
712 if ( ptiTo->MessageQueue->spwndFocus == 0 )
713 ptiTo->MessageQueue->spwndFocus = ptiFrom->MessageQueue->spwndFocus;
714 }
715
716 CurIcon = ptiFrom->MessageQueue->CursorObject;
717
718 MsqDestroyMessageQueue(ptiFrom);
719
720 if (CurIcon)
721 {
722 // Could be global. Keep it above the water line!
723 UserReferenceObject(CurIcon);
724 }
725
726 if (CurIcon && UserObjectInDestroy(UserHMGetHandle(CurIcon)))
727 {
728 UserDereferenceObject(CurIcon);
729 CurIcon = NULL;
730 }
731
732 ptiFrom->MessageQueue = ptiTo->MessageQueue;
733
734 // Pass cursor From if To is null. Pass test_SetCursor parent_id == current pti ID.
735 if (CurIcon && ptiTo->MessageQueue->CursorObject == NULL)
736 {
737 ERR("ptiTo receiving ptiFrom Cursor\n");
738 ptiTo->MessageQueue->CursorObject = CurIcon;
739 }
740
741 ptiFrom->MessageQueue->cThreads++;
742 ERR("ptiTo S Share count %u\n", ptiFrom->MessageQueue->cThreads);
743
745 }
746 else
747 {
748 ERR("Attach Threads are already associated!\n");
749 }
750 }
751 else /* If clear, unlink and free it. */
752 {
753 BOOL Hit = FALSE;
754 PATTACHINFO *ppai;
755
756 if (!gpai) return STATUS_INVALID_PARAMETER;
757
758 /* Search list and free if found or return false. */
759 ppai = &gpai;
760 while (*ppai != NULL)
761 {
762 if ( (*ppai)->pti2 == ptiTo && (*ppai)->pti1 == ptiFrom )
763 {
764 pai = *ppai;
765 /* Remove it from the list */
766 *ppai = (*ppai)->paiNext;
768 paiCount--;
769 Hit = TRUE;
770 break;
771 }
772 ppai = &((*ppai)->paiNext);
773 }
774
775 if (!Hit) return STATUS_INVALID_PARAMETER;
776
777 ERR("Attach Free! ptiFrom 0x%p ptiTo 0x%p paiCount %d\n",ptiFrom,ptiTo,paiCount);
778
779 if (ptiTo->MessageQueue == ptiFrom->MessageQueue)
780 {
781 PWND spwndActive = ptiTo->MessageQueue->spwndActive;
782 PWND spwndFocus = ptiTo->MessageQueue->spwndFocus;
783
784 if (gptiForeground == ptiFrom)
785 {
786 ERR("ptiTo is now pti FG.\n");
787 // MessageQueue foreground is set so switch threads.
788 gptiForeground = ptiTo;
789 }
790 ptiTo->MessageQueue->cThreads--;
791 ERR("ptiTo E Share count %u\n", ptiTo->MessageQueue->cThreads);
792 ASSERT(ptiTo->MessageQueue->cThreads >= 1);
793
795
796 ptiFrom->MessageQueue = MsqCreateMessageQueue(ptiFrom);
797
798 if (spwndActive)
799 {
800 if (spwndActive->head.pti == ptiFrom)
801 {
802 ptiFrom->MessageQueue->spwndActive = spwndActive;
803 ptiTo->MessageQueue->spwndActive = 0;
804 }
805 }
806 if (spwndFocus)
807 {
808 if (spwndFocus->head.pti == ptiFrom)
809 {
810 ptiFrom->MessageQueue->spwndFocus = spwndFocus;
811 ptiTo->MessageQueue->spwndFocus = 0;
812 }
813 }
814 ptiTo->MessageQueue->iCursorLevel -= ptiFrom->iCursorLevel;
815 }
816 else
817 {
818 ERR("Detaching Threads are not associated!\n");
819 }
820 }
821 /* Note that key state, which can be ascertained by calls to the GetKeyState
822 or GetKeyboardState function, is reset after a call to AttachThreadInput.
823 ATM which one?
824 */
825 RtlCopyMemory(ptiTo->MessageQueue->afKeyState, gafAsyncKeyState, sizeof(gafAsyncKeyState));
826
827 ptiTo->MessageQueue->msgDblClk.message = 0;
828
829 /* Generate mouse move message */
830 msg.message = WM_MOUSEMOVE;
831 msg.wParam = UserGetMouseButtonsState();
832 msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y);
833 msg.pt = gpsi->ptCursor;
835
836 return STATUS_SUCCESS;
837}
#define msg(x)
Definition: auth_time.c:54
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
PTHREADINFO gptiForeground
Definition: focus.c:15
PUSER_MESSAGE_QUEUE gpqForeground
Definition: focus.c:13
#define TIF_DONTATTACHQUEUE
Definition: ntuser.h:272
#define UserHMGetHandle(obj)
Definition: ntuser.h:233
VOID FASTCALL co_MsqInsertMouseMessage(MSG *Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook)
Definition: msgqueue.c:580
VOID FASTCALL MsqDestroyMessageQueue(_In_ PTHREADINFO pti)
Definition: msgqueue.c:2434
PUSER_MESSAGE_QUEUE FASTCALL MsqCreateMessageQueue(PTHREADINFO pti)
Definition: msgqueue.c:2407
#define QF_CAPTURELOCKED
Definition: msgqueue.h:114
#define IntReferenceMessageQueue(MsgQueue)
Definition: msgqueue.h:220
#define IntDereferenceMessageQueue(MsgQueue)
Definition: msgqueue.h:223
#define MAKELPARAM(l, h)
Definition: winuser.h:4116
#define WM_MOUSEMOVE
Definition: winuser.h:1803
INT iCursorLevel
Definition: win32.h:128
struct _USER_MESSAGE_QUEUE * MessageQueue
Definition: win32.h:90
Definition: ntuser.h:698
THRDESKHEAD head
Definition: ntuser.h:699
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
VOID FASTCALL IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue)
Definition: desktop.c:1347
INT paiCount
Definition: input.c:32
WORD FASTCALL UserGetMouseButtonsState(VOID)
Definition: mouse.c:22
BYTE gafAsyncKeyState[256 *2/8]
Definition: keyboard.c:13
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:647
BOOL FASTCALL UserObjectInDestroy(HANDLE h)
Definition: object.c:707
VOID FASTCALL UserReferenceObject(PVOID obj)
Definition: object.c:754
#define USERTAG_ATTACHINFO
Definition: tags.h:197

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

Variable Documentation

◆ gDeviceListChangedEvent

PKEVENT gDeviceListChangedEvent
static

Definition at line 38 of file input.c.

Referenced by CreateInputDevice(), and RawInputThreadMain().

◆ ghKeyboardDevice

HANDLE ghKeyboardDevice = NULL

◆ gpai

PATTACHINFO gpai = NULL

Definition at line 31 of file input.c.

Referenced by IsRemoveAttachThread(), and UserAttachThreadInput().

◆ gpDeviceInfoListMutex

PERESOURCE gpDeviceInfoListMutex = NULL

◆ gpInputDeviceInfo

◆ LastInputTick

DWORD LastInputTick = 0
static

Definition at line 37 of file input.c.

Referenced by DoTheScreenSaver(), and IntLastInputTick().

◆ MasterTimer

PKTIMER MasterTimer = NULL

Definition at line 30 of file input.c.

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

◆ paiCount

INT paiCount = 0

Definition at line 32 of file input.c.

Referenced by UserAttachThreadInput().

◆ ptiRawInput

PTHREADINFO ptiRawInput

Definition at line 29 of file input.c.

Referenced by IntSetTimer(), and RawInputThreadMain().