- Merge KeyboardInput thread and MouseInputThread into Raw Input Thread (RIT)

svn path=/trunk/; revision=54159
This commit is contained in:
Rafal Harabien
2011-10-16 11:39:47 +00:00
parent 5d40c09bb6
commit 7ab2968d8e
2 changed files with 208 additions and 255 deletions
@@ -182,7 +182,7 @@ DWORD
WINAPI
CreateSystemThreads(PVOID pParam)
{
NtUserCallOneParam((DWORD_PTR)pParam, ONEPARAM_ROUTINE_CREATESYSTEMTHREADS);
NtUserCallOneParam((DWORD)pParam, ONEPARAM_ROUTINE_CREATESYSTEMTHREADS);
DPRINT1("This thread should not terminate!\n");
return 0;
}
@@ -196,7 +196,6 @@ Win32CsrInitialization(PCSRSS_API_DEFINITION *ApiDefinitions,
HANDLE ServerThread;
CLIENT_ID ClientId;
NTSTATUS Status;
UINT i;
CsrExports = *Exports;
Win32CsrApiHeap = CsrssApiHeap;
@@ -215,18 +214,15 @@ Win32CsrInitialization(PCSRSS_API_DEFINITION *ApiDefinitions,
RtlInitializeCriticalSection(&Win32CsrDefineDosDeviceCritSec);
InitializeListHead(&DosDeviceHistory);
/* Start Keyboard, Mouse and Raw Input Threads */
for (i = 0; i < 3; ++i)
/* Start Raw Input Threads */
Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, 0, 0, 0, (PTHREAD_START_ROUTINE)CreateSystemThreads, (PVOID)0, &ServerThread, &ClientId);
if (NT_SUCCESS(Status))
{
Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, 0, 0, 0, (PTHREAD_START_ROUTINE)CreateSystemThreads, (PVOID)i, &ServerThread, &ClientId);
if (NT_SUCCESS(Status))
{
NtResumeThread(ServerThread, NULL);
NtClose(ServerThread);
}
else
DPRINT1("Cannot start system thread: %u!\n", i);
NtResumeThread(ServerThread, NULL);
NtClose(ServerThread);
}
else
DPRINT1("Cannot start Raw Input Thread!\n");
return TRUE;
}
+200 -243
View File
@@ -23,12 +23,15 @@ PATTACHINFO gpai = NULL;
HANDLE ghKeyboardDevice;
static DWORD LastInputTick = 0;
static HANDLE MouseDeviceHandle;
static KEVENT InputThreadsStart;
static BOOLEAN InputThreadsRunning = FALSE;
static HANDLE ghMouseDevice;
/* FUNCTIONS *****************************************************************/
/*
* IntLastInputTick
*
* Updates or gets last input tick count
*/
static DWORD FASTCALL
IntLastInputTick(BOOL bUpdate)
{
@@ -42,6 +45,11 @@ IntLastInputTick(BOOL bUpdate)
return LastInputTick;
}
/*
* DoTheScreenSaver
*
* Check if scrensaver should be started and sends message to SAS window
*/
VOID FASTCALL
DoTheScreenSaver(VOID)
{
@@ -78,210 +86,201 @@ DoTheScreenSaver(VOID)
}
}
static VOID APIENTRY
MouseThreadMain(PVOID StartContext)
/*
* OpenInputDevice
*
* Opens input device for asynchronous access
*/
static
NTAPI NTSTATUS
OpenInputDevice(PHANDLE pHandle, PFILE_OBJECT *ppObject, CONST WCHAR *pszDeviceName)
{
UNICODE_STRING MouseDeviceName = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");
OBJECT_ATTRIBUTES MouseObjectAttributes;
IO_STATUS_BLOCK Iosb;
UNICODE_STRING DeviceName;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
MOUSE_ATTRIBUTES MouseAttr;
IO_STATUS_BLOCK Iosb;
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
LOW_REALTIME_PRIORITY + 3);
RtlInitUnicodeString(&DeviceName, pszDeviceName);
InitializeObjectAttributes(&MouseObjectAttributes,
&MouseDeviceName,
InitializeObjectAttributes(&ObjectAttributes,
&DeviceName,
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 = ZwOpenFile(&MouseDeviceHandle,
FILE_ALL_ACCESS,
&MouseObjectAttributes,
&Iosb,
0,
FILE_SYNCHRONOUS_IO_ALERT);
} while (!NT_SUCCESS(Status));
ptiMouse = PsGetCurrentThreadWin32Thread();
ptiMouse->TIF_flags |= TIF_SYSTEMTHREAD;
TRACE("Mouse Thread 0x%x \n", ptiMouse);
Status = ZwOpenFile(pHandle,
FILE_ALL_ACCESS,
&ObjectAttributes,
&Iosb,
0,
0);
if (NT_SUCCESS(Status) && ppObject)
{
Status = ObReferenceObjectByHandle(*pHandle, SYNCHRONIZE, NULL, KernelMode, (PVOID*)ppObject, NULL);
ASSERT(NT_SUCCESS(Status));
}
return Status;
}
/*
* RawInputThreadMain
*
* Reads data from input devices and supports win32 timers
*/
VOID NTAPI
RawInputThreadMain()
{
NTSTATUS MouStatus = STATUS_UNSUCCESSFUL, KbdStatus = STATUS_UNSUCCESSFUL, Status;
IO_STATUS_BLOCK MouIosb, KbdIosb;
PFILE_OBJECT pKbdDevice, pMouDevice;
LARGE_INTEGER WaitTimeout, ByteOffset;
PVOID WaitObjects[3], pSignaledObject = NULL;
ULONG cWaitObjects = 0, cMaxWaitObjects = 1;
MOUSE_INPUT_DATA MouseInput;
KEYBOARD_INPUT_DATA KeyInput;
ByteOffset.QuadPart = (LONGLONG)0;
WaitTimeout.QuadPart = (LONGLONG)(-10000000);
/*do
{
KEVENT Event;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &WaitTimeout);
} while (!NT_SUCCESS(Status));*/
ptiRawInput = PsGetCurrentThreadWin32Thread();
ptiRawInput->TIF_flags |= TIF_SYSTEMTHREAD;
TRACE("Raw Input Thread 0x%x\n", ptiRawInput);
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
LOW_REALTIME_PRIORITY + 3);
UserEnterExclusive();
StartTheTimers();
UserLeave();
for(;;)
{
/*
* Wait to start input.
*/
TRACE("Mouse Input Thread Waiting for start event\n");
Status = KeWaitForSingleObject(&InputThreadsStart,
0,
KernelMode,
TRUE,
NULL);
TRACE("Mouse Input Thread Starting...\n");
/*FIXME: Does mouse attributes need to be used for anything */
Status = ZwDeviceIoControlFile(MouseDeviceHandle,
NULL,
NULL,
NULL,
&Iosb,
IOCTL_MOUSE_QUERY_ATTRIBUTES,
&MouseAttr, sizeof(MOUSE_ATTRIBUTES),
NULL, 0);
if(!NT_SUCCESS(Status))
if (!ghMouseDevice)
{
TRACE("Failed to get mouse attributes\n");
/* Check if mouse device already exists */
Status = OpenInputDevice(&ghMouseDevice, &pMouDevice, L"\\Device\\PointerClass0" );
if (NT_SUCCESS(Status))
{
++cMaxWaitObjects;
TRACE("Mouse connected!\n");
}
}
if (!ghKeyboardDevice)
{
/* Check if keyboard device already exists */
Status = OpenInputDevice(&ghKeyboardDevice, &pKbdDevice, L"\\Device\\KeyboardClass0");
if (NT_SUCCESS(Status))
{
++cMaxWaitObjects;
TRACE("Keyboard connected!\n");
}
}
/*
* Receive and process mouse input.
*/
while(InputThreadsRunning)
/* Reset WaitHandles array */
cWaitObjects = 0;
WaitObjects[cWaitObjects++] = MasterTimer;
if (ghMouseDevice)
{
MOUSE_INPUT_DATA MouseInput;
Status = ZwReadFile(MouseDeviceHandle,
NULL,
NULL,
NULL,
&Iosb,
&MouseInput,
sizeof(MOUSE_INPUT_DATA),
NULL,
NULL);
if(Status == STATUS_ALERTED && !InputThreadsRunning)
/* Try to read from mouse if previous reading is not pending */
if (MouStatus != STATUS_PENDING)
{
break;
MouStatus = ZwReadFile(ghMouseDevice,
NULL,
NULL,
NULL,
&MouIosb,
&MouseInput,
sizeof(MOUSE_INPUT_DATA),
&ByteOffset,
NULL);
}
if(Status == STATUS_PENDING)
if (MouStatus == STATUS_PENDING)
WaitObjects[cWaitObjects++] = &pMouDevice->Event;
}
if (ghKeyboardDevice)
{
/* Try to read from keyboard if previous reading is not pending */
if (KbdStatus != STATUS_PENDING)
{
NtWaitForSingleObject(MouseDeviceHandle, FALSE, NULL);
Status = Iosb.Status;
KbdStatus = ZwReadFile(ghKeyboardDevice,
NULL,
NULL,
NULL,
&KbdIosb,
&KeyInput,
sizeof(KEYBOARD_INPUT_DATA),
&ByteOffset,
NULL);
}
if(!NT_SUCCESS(Status))
if (KbdStatus == STATUS_PENDING)
WaitObjects[cWaitObjects++] = &pKbdDevice->Event;
}
/* If all objects are pending, wait for them */
if (cWaitObjects == cMaxWaitObjects)
{
Status = KeWaitForMultipleObjects(cWaitObjects,
WaitObjects,
WaitAny,
UserRequest,
KernelMode,
TRUE,
NULL,//&WaitTimeout,
NULL);
if (Status >= STATUS_WAIT_0 && Status < STATUS_WAIT_0 + cWaitObjects)
{
ERR("Win32K: Failed to read from mouse.\n");
return; //(Status);
/* Some device has finished reading */
pSignaledObject = WaitObjects[Status - STATUS_WAIT_0];
/* Check if it is mouse or keyboard and update status */
if (pSignaledObject == &pMouDevice->Event)
MouStatus = MouIosb.Status;
else if (pSignaledObject == &pKbdDevice->Event)
KbdStatus = KbdIosb.Status;
else if (pSignaledObject == MasterTimer)
{
/* FIXME: where it should go? */
ProcessTimers();
}
else ASSERT(FALSE);
}
}
/* Have we successed reading from mouse? */
if (NT_SUCCESS(MouStatus) && MouStatus != STATUS_PENDING)
{
TRACE("MouseEvent\n");
/* Set LastInputTick */
IntLastInputTick(TRUE);
/* Process data */
UserEnterExclusive();
UserProcessMouseInput(&MouseInput, Iosb.Information / sizeof(MOUSE_INPUT_DATA));
UserProcessMouseInput(&MouseInput, MouIosb.Information / sizeof(MOUSE_INPUT_DATA));
UserLeave();
}
TRACE("Mouse Input Thread Stopped...\n");
}
}
else if (MouStatus != STATUS_PENDING)
ERR("Failed to read from mouse: %x.\n", MouStatus);
VOID NTAPI
KeyboardThreadMain(PVOID StartContext)
{
UNICODE_STRING KeyboardDeviceName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass0");
OBJECT_ATTRIBUTES KeyboardObjectAttributes;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
InitializeObjectAttributes(&KeyboardObjectAttributes,
&KeyboardDeviceName,
0,
NULL,
NULL);
do
{
LARGE_INTEGER DueTime;
KEVENT Event;
DueTime.QuadPart = (LONGLONG)(-100000000);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &DueTime);
Status = ZwOpenFile(&ghKeyboardDevice,
FILE_READ_ACCESS,//FILE_ALL_ACCESS,
&KeyboardObjectAttributes,
&Iosb,
0,
FILE_SYNCHRONOUS_IO_ALERT);
} while (!NT_SUCCESS(Status));
UserInitKeyboard(ghKeyboardDevice);
ptiKeyboard = PsGetCurrentThreadWin32Thread();
ptiKeyboard->TIF_flags |= TIF_SYSTEMTHREAD;
TRACE("Keyboard Thread 0x%x \n", ptiKeyboard);
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
LOW_REALTIME_PRIORITY + 3);
for (;;)
{
/*
* Wait to start input.
*/
TRACE("Keyboard Input Thread Waiting for start event\n");
Status = KeWaitForSingleObject(&InputThreadsStart,
0,
KernelMode,
TRUE,
NULL);
TRACE("Keyboard Input Thread Starting...\n");
/*
* Receive and process keyboard input.
*/
while (InputThreadsRunning)
/* Have we successed reading from keyboard? */
if (NT_SUCCESS(KbdStatus) && KbdStatus != STATUS_PENDING)
{
KEYBOARD_INPUT_DATA KeyInput;
TRACE("KeyInput @ %08x\n", &KeyInput);
Status = ZwReadFile (ghKeyboardDevice,
NULL,
NULL,
NULL,
&Iosb,
&KeyInput,
sizeof(KEYBOARD_INPUT_DATA),
NULL,
NULL);
if (Status == STATUS_ALERTED && !InputThreadsRunning)
{
break;
}
if (Status == STATUS_PENDING)
{
NtWaitForSingleObject(ghKeyboardDevice, FALSE, NULL);
Status = Iosb.Status;
}
if (!NT_SUCCESS(Status))
{
ERR("Win32K: Failed to read from keyboard.\n");
return; //(Status);
}
TRACE("KeyRaw: %s %04x\n",
TRACE("KeyboardEvent: %s %04x\n",
(KeyInput.Flags & KEY_BREAK) ? "up" : "down",
KeyInput.MakeCode );
if (Status == STATUS_ALERTED && !InputThreadsRunning)
break;
if (!NT_SUCCESS(Status))
{
ERR("Win32K: Failed to read from keyboard.\n");
return; //(Status);
}
KeyInput.MakeCode);
/* Set LastInputTick */
IntLastInputTick(TRUE);
@@ -291,68 +290,18 @@ KeyboardThreadMain(PVOID StartContext)
UserProcessKeyboardInput(&KeyInput);
UserLeave();
}
TRACE("KeyboardInput Thread Stopped...\n");
}
}
static PVOID Objects[2];
/*
Raw Input Thread.
Since this relies on InputThreadsStart, just fake it.
*/
static VOID APIENTRY
RawInputThreadMain(PVOID StartContext)
{
NTSTATUS Status;
LARGE_INTEGER DueTime;
DueTime.QuadPart = (LONGLONG)(-10000000);
do
{
KEVENT Event;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &DueTime);
} while (!NT_SUCCESS(Status));
Objects[0] = &InputThreadsStart;
Objects[1] = MasterTimer;
ptiRawInput = PsGetCurrentThreadWin32Thread();
ptiRawInput->TIF_flags |= TIF_SYSTEMTHREAD;
TRACE("Raw Input Thread 0x%x \n", ptiRawInput);
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
LOW_REALTIME_PRIORITY + 3);
UserEnterExclusive();
StartTheTimers();
UserLeave();
//
// ATM, we just have one job to handle, merge the other two later.
//
for(;;)
{
TRACE("Raw Input Thread Waiting for start event\n");
Status = KeWaitForMultipleObjects( 2,
Objects,
WaitAll, //WaitAny,
WrUserRequest,
KernelMode,
TRUE,
NULL,
NULL);
TRACE("Raw Input Thread Starting...\n");
ProcessTimers();
else if (KbdStatus != STATUS_PENDING)
ERR("Failed to read from keyboard: %x.\n", KbdStatus);
}
ERR("Raw Input Thread Exit!\n");
}
/*
* CreateSystemThreads
*
* Called form dedicated thread in CSRSS. RIT is started in context of this
* thread because it needs valid Win32 process with TEB initialized
*/
DWORD NTAPI
CreateSystemThreads(UINT Type)
{
@@ -360,9 +309,7 @@ CreateSystemThreads(UINT Type)
switch (Type)
{
case 0: KeyboardThreadMain(NULL); break;
case 1: MouseThreadMain(NULL); break;
case 2: RawInputThreadMain(NULL); break;
case 0: RawInputThreadMain(); break;
default: ERR("Wrong type: %x\n", Type);
}
@@ -371,38 +318,43 @@ CreateSystemThreads(UINT Type)
return 0;
}
/*
* InitInputImpl
*
* Inits input implementation
*/
INIT_FUNCTION
NTSTATUS
NTAPI
InitInputImpl(VOID)
{
KeInitializeEvent(&InputThreadsStart, NotificationEvent, FALSE);
MasterTimer = ExAllocatePoolWithTag(NonPagedPool, sizeof(KTIMER), USERTAG_SYSTEM);
if (!MasterTimer)
{
ERR("Win32K: Failed making Raw Input thread a win32 thread.\n");
ERR("Failed to allocate memory\n");
ASSERT(FALSE);
return STATUS_UNSUCCESSFUL;
}
KeInitializeTimer(MasterTimer);
/* Initialize the default keyboard layout */
if(!UserInitDefaultKeyboardLayout())
if (!UserInitDefaultKeyboardLayout())
{
ERR("Failed to initialize default keyboard layout!\n");
}
InputThreadsRunning = TRUE;
KeSetEvent(&InputThreadsStart, IO_NO_INCREMENT, FALSE);
return STATUS_SUCCESS;
}
/*
* CleanupInputImp
*
* Cleans input implementation
*/
NTSTATUS FASTCALL
CleanupInputImp(VOID)
{
return(STATUS_SUCCESS);
return STATUS_SUCCESS;
}
BOOL FASTCALL
@@ -517,6 +469,11 @@ UserAttachThreadInput(PTHREADINFO pti, PTHREADINFO ptiTo, BOOL fAttach)
return TRUE;
}
/*
* NtUserSendInput
*
* Generates input events from software
*/
UINT
APIENTRY
NtUserSendInput(