📄 input.c
字号:
/*
* ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: input.c 27952 2007-07-28 17:16:51Z weiden $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Window classes
* FILE: subsys/win32k/ntuser/class.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISION HISTORY:
* 06-06-2001 CSH Created
*/
/* INCLUDES ******************************************************************/
#include <w32k.h>
#include <ntddkbd.h>
#define NDEBUG
#include <debug.h>
extern BYTE gQueueKeyStateTable[];
/* GLOBALS *******************************************************************/
static HANDLE MouseDeviceHandle;
static HANDLE MouseThreadHandle;
static CLIENT_ID MouseThreadId;
static HANDLE KeyboardThreadHandle;
static CLIENT_ID KeyboardThreadId;
static HANDLE KeyboardDeviceHandle;
static KEVENT InputThreadsStart;
static BOOLEAN InputThreadsRunning = FALSE;
/* FUNCTIONS *****************************************************************/
ULONG FASTCALL
IntSystemParametersInfo(UINT uiAction, UINT uiParam,PVOID pvParam, UINT fWinIni);
DWORD IntLastInputTick(BOOL LastInputTickSetGet);
#define ClearMouseInput(mi) \
mi.dx = 0; \
mi.dy = 0; \
mi.mouseData = 0; \
mi.dwFlags = 0;
#define SendMouseEvent(mi) \
if(mi.dx != 0 || mi.dy != 0) \
mi.dwFlags |= MOUSEEVENTF_MOVE; \
if(mi.dwFlags) \
IntMouseInput(&mi); \
ClearMouseInput(mi);
DWORD IntLastInputTick(BOOL LastInputTickSetGet)
{
static DWORD LastInputTick = 0;
if (LastInputTickSetGet == TRUE)
{
LARGE_INTEGER TickCount;
KeQueryTickCount(&TickCount);
LastInputTick = TickCount.u.LowPart * (KeQueryTimeIncrement() / 10000);
}
return LastInputTick;
}
BOOL
STDCALL
NtUserGetLastInputInfo(PLASTINPUTINFO plii)
{
BOOL ret = TRUE;
UserEnterShared();
_SEH_TRY
{
if (ProbeForReadUint(&plii->cbSize) != sizeof(LASTINPUTINFO))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
ret = FALSE;
_SEH_LEAVE;
}
ProbeForWrite(plii, sizeof(LASTINPUTINFO), sizeof(DWORD));
plii->dwTime = IntLastInputTick(FALSE);
}
_SEH_HANDLE
{
SetLastNtError(_SEH_GetExceptionCode());
ret = FALSE;
}
_SEH_END;
UserLeave();
return ret;
}
VOID FASTCALL
ProcessMouseInputData(PMOUSE_INPUT_DATA Data, ULONG InputCount)
{
PMOUSE_INPUT_DATA mid;
MOUSEINPUT mi;
ULONG i;
ClearMouseInput(mi);
mi.time = 0;
mi.dwExtraInfo = 0;
for(i = 0; i < InputCount; i++)
{
mid = (Data + i);
mi.dx += mid->LastX;
mi.dy += mid->LastY;
if(mid->ButtonFlags)
{
if(mid->ButtonFlags & MOUSE_LEFT_BUTTON_DOWN)
{
mi.dwFlags |= MOUSEEVENTF_LEFTDOWN;
SendMouseEvent(mi);
}
if(mid->ButtonFlags & MOUSE_LEFT_BUTTON_UP)
{
mi.dwFlags |= MOUSEEVENTF_LEFTUP;
SendMouseEvent(mi);
}
if(mid->ButtonFlags & MOUSE_MIDDLE_BUTTON_DOWN)
{
mi.dwFlags |= MOUSEEVENTF_MIDDLEDOWN;
SendMouseEvent(mi);
}
if(mid->ButtonFlags & MOUSE_MIDDLE_BUTTON_UP)
{
mi.dwFlags |= MOUSEEVENTF_MIDDLEUP;
SendMouseEvent(mi);
}
if(mid->ButtonFlags & MOUSE_RIGHT_BUTTON_DOWN)
{
mi.dwFlags |= MOUSEEVENTF_RIGHTDOWN;
SendMouseEvent(mi);
}
if(mid->ButtonFlags & MOUSE_RIGHT_BUTTON_UP)
{
mi.dwFlags |= MOUSEEVENTF_RIGHTUP;
SendMouseEvent(mi);
}
if(mid->ButtonFlags & MOUSE_BUTTON_4_DOWN)
{
mi.mouseData |= XBUTTON1;
mi.dwFlags |= MOUSEEVENTF_XDOWN;
SendMouseEvent(mi);
}
if(mid->ButtonFlags & MOUSE_BUTTON_4_UP)
{
mi.mouseData |= XBUTTON1;
mi.dwFlags |= MOUSEEVENTF_XUP;
SendMouseEvent(mi);
}
if(mid->ButtonFlags & MOUSE_BUTTON_5_DOWN)
{
mi.mouseData |= XBUTTON2;
mi.dwFlags |= MOUSEEVENTF_XDOWN;
SendMouseEvent(mi);
}
if(mid->ButtonFlags & MOUSE_BUTTON_5_UP)
{
mi.mouseData |= XBUTTON2;
mi.dwFlags |= MOUSEEVENTF_XUP;
SendMouseEvent(mi);
}
if(mid->ButtonFlags & MOUSE_WHEEL)
{
mi.mouseData = mid->ButtonData;
mi.dwFlags |= MOUSEEVENTF_WHEEL;
SendMouseEvent(mi);
}
}
}
SendMouseEvent(mi);
}
VOID STDCALL
MouseThreadMain(PVOID StartContext)
{
UNICODE_STRING MouseDeviceName = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");
OBJECT_ATTRIBUTES MouseObjectAttributes;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
InitializeObjectAttributes(&MouseObjectAttributes,
&MouseDeviceName,
0,
NULL,
NULL);
do
{
LARGE_INTEGER DueTime;
KEVENT Event;
DueTime.QuadPart = (LONGLONG)(-10000000);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &DueTime);
Status = NtOpenFile(&MouseDeviceHandle,
FILE_ALL_ACCESS,
&MouseObjectAttributes,
&Iosb,
0,
FILE_SYNCHRONOUS_IO_ALERT);
} while (!NT_SUCCESS(Status));
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
LOW_REALTIME_PRIORITY + 3);
for(;;)
{
/*
* Wait to start input.
*/
DPRINT("Mouse Input Thread Waiting for start event\n");
Status = KeWaitForSingleObject(&InputThreadsStart,
0,
KernelMode,
TRUE,
NULL);
DPRINT("Mouse Input Thread Starting...\n");
/*
* Receive and process mouse input.
*/
while(InputThreadsRunning)
{
MOUSE_INPUT_DATA MouseInput;
Status = NtReadFile(MouseDeviceHandle,
NULL,
NULL,
NULL,
&Iosb,
&MouseInput,
sizeof(MOUSE_INPUT_DATA),
NULL,
NULL);
if(Status == STATUS_ALERTED && !InputThreadsRunning)
{
break;
}
if(Status == STATUS_PENDING)
{
NtWaitForSingleObject(MouseDeviceHandle, FALSE, NULL);
Status = Iosb.Status;
}
if(!NT_SUCCESS(Status))
{
DPRINT1("Win32K: Failed to read from mouse.\n");
return; //(Status);
}
DPRINT("MouseEvent\n");
IntLastInputTick(TRUE);
UserEnterExclusive();
ProcessMouseInputData(&MouseInput, Iosb.Information / sizeof(MOUSE_INPUT_DATA));
UserLeave();
}
DPRINT("Mouse Input Thread Stopped...\n");
}
}
/* Returns a value that indicates if the key is a modifier key, and
* which one.
*/
static UINT STDCALL
IntKeyboardGetModifiers(KEYBOARD_INPUT_DATA *InputData)
{
if (InputData->Flags & KEY_E1)
return 0;
if (!(InputData->Flags & KEY_E0))
{
switch (InputData->MakeCode)
{
case 0x2a: /* left shift */
case 0x36: /* right shift */
return MOD_SHIFT;
case 0x1d: /* left control */
return MOD_CONTROL;
case 0x38: /* left alt */
return MOD_ALT;
default:
return 0;
}
}
else
{
switch (InputData->MakeCode)
{
case 0x1d: /* right control */
return MOD_CONTROL;
case 0x38: /* right alt */
return MOD_ALT;
case 0x5b: /* left gui (windows) */
case 0x5c: /* right gui (windows) */
return MOD_WIN;
default:
return 0;
}
}
}
/* Asks the keyboard driver to send a small table that shows which
* lights should connect with which scancodes
*/
static NTSTATUS STDCALL
IntKeyboardGetIndicatorTrans(HANDLE KeyboardDeviceHandle,
PKEYBOARD_INDICATOR_TRANSLATION *IndicatorTrans)
{
NTSTATUS Status;
DWORD Size = 0;
IO_STATUS_BLOCK Block;
PKEYBOARD_INDICATOR_TRANSLATION Ret;
Size = sizeof(KEYBOARD_INDICATOR_TRANSLATION);
Ret = ExAllocatePoolWithTag(PagedPool,
Size,
TAG_KEYBOARD);
while (Ret)
{
Status = NtDeviceIoControlFile(KeyboardDeviceHandle,
NULL,
NULL,
NULL,
&Block,
IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION,
NULL, 0,
Ret, Size);
if (Status != STATUS_BUFFER_TOO_SMALL)
break;
ExFreePool(Ret);
Size += sizeof(KEYBOARD_INDICATOR_TRANSLATION);
Ret = ExAllocatePoolWithTag(PagedPool,
Size,
TAG_KEYBOARD);
}
if (!Ret)
return STATUS_INSUFFICIENT_RESOURCES;
if (Status != STATUS_SUCCESS)
{
ExFreePool(Ret);
return Status;
}
*IndicatorTrans = Ret;
return Status;
}
/* Sends the keyboard commands to turn on/off the lights.
*/
static NTSTATUS STDCALL
IntKeyboardUpdateLeds(HANDLE KeyboardDeviceHandle,
PKEYBOARD_INPUT_DATA KeyInput,
PKEYBOARD_INDICATOR_TRANSLATION IndicatorTrans)
{
NTSTATUS Status;
UINT Count;
static KEYBOARD_INDICATOR_PARAMETERS Indicators;
IO_STATUS_BLOCK Block;
if (!IndicatorTrans)
return STATUS_NOT_SUPPORTED;
if (KeyInput->Flags & (KEY_E0 | KEY_E1 | KEY_BREAK))
return STATUS_SUCCESS;
for (Count = 0; Count < IndicatorTrans->NumberOfIndicatorKeys; Count++)
{
if (KeyInput->MakeCode == IndicatorTrans->IndicatorList[Count].MakeCode)
{
Indicators.LedFlags ^=
IndicatorTrans->IndicatorList[Count].IndicatorFlags;
/* Update the lights on the hardware */
Status = NtDeviceIoControlFile(KeyboardDeviceHandle,
NULL,
NULL,
NULL,
&Block,
IOCTL_KEYBOARD_SET_INDICATORS,
&Indicators, sizeof(Indicators),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -