Author: rharabien Date: Sun Oct 16 11:39:47 2011 New Revision: 54159
URL: http://svn.reactos.org/svn/reactos?rev=54159&view=rev Log: [WIN32K] - Merge KeyboardInput thread and MouseInputThread into Raw Input Thread (RIT)
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/dllmain.c trunk/reactos/subsystems/win32/win32k/ntuser/input.c
Modified: trunk/reactos/subsystems/win32/csrss/win32csr/dllmain.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/win3... ============================================================================== --- trunk/reactos/subsystems/win32/csrss/win32csr/dllmain.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/csrss/win32csr/dllmain.c [iso-8859-1] Sun Oct 16 11:39:47 2011 @@ -182,7 +182,7 @@ 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 @@ HANDLE ServerThread; CLIENT_ID ClientId; NTSTATUS Status; - UINT i;
CsrExports = *Exports; Win32CsrApiHeap = CsrssApiHeap; @@ -215,18 +214,15 @@ RtlInitializeCriticalSection(&Win32CsrDefineDosDeviceCritSec); InitializeListHead(&DosDeviceHistory);
- /* Start Keyboard, Mouse and Raw Input Threads */ - for (i = 0; i < 3; ++i) - { - 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); - } + /* Start Raw Input Threads */ + Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, 0, 0, 0, (PTHREAD_START_ROUTINE)CreateSystemThreads, (PVOID)0, &ServerThread, &ClientId); + if (NT_SUCCESS(Status)) + { + NtResumeThread(ServerThread, NULL); + NtClose(ServerThread); + } + else + DPRINT1("Cannot start Raw Input Thread!\n");
return TRUE; }
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/input.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/input.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/input.c [iso-8859-1] Sun Oct 16 11:39:47 2011 @@ -23,12 +23,15 @@ 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 @@ return LastInputTick; }
+/* + * DoTheScreenSaver + * + * Check if scrensaver should be started and sends message to SAS window + */ VOID FASTCALL DoTheScreenSaver(VOID) { @@ -78,210 +86,201 @@ } }
-static VOID APIENTRY -MouseThreadMain(PVOID StartContext) -{ - UNICODE_STRING MouseDeviceName = RTL_CONSTANT_STRING(L"\Device\PointerClass0"); - OBJECT_ATTRIBUTES MouseObjectAttributes; +/* + * OpenInputDevice + * + * Opens input device for asynchronous access + */ +static +NTAPI NTSTATUS +OpenInputDevice(PHANDLE pHandle, PFILE_OBJECT *ppObject, CONST WCHAR *pszDeviceName) +{ + UNICODE_STRING DeviceName; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; IO_STATUS_BLOCK Iosb; - NTSTATUS Status; - MOUSE_ATTRIBUTES MouseAttr; - - KeSetPriorityThread(&PsGetCurrentThread()->Tcb, - LOW_REALTIME_PRIORITY + 3); - - InitializeObjectAttributes(&MouseObjectAttributes, - &MouseDeviceName, + + RtlInitUnicodeString(&DeviceName, pszDeviceName); + + InitializeObjectAttributes(&ObjectAttributes, + &DeviceName, 0, NULL, NULL); - do - { - LARGE_INTEGER DueTime; + + 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; - 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 = 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, + if (!ghMouseDevice) + { + /* 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"); + } + } + + /* Reset WaitHandles array */ + cWaitObjects = 0; + WaitObjects[cWaitObjects++] = MasterTimer; + + if (ghMouseDevice) + { + /* Try to read from mouse if previous reading is not pending */ + if (MouStatus != STATUS_PENDING) + { + MouStatus = ZwReadFile(ghMouseDevice, NULL, NULL, NULL, - &Iosb, - IOCTL_MOUSE_QUERY_ATTRIBUTES, - &MouseAttr, sizeof(MOUSE_ATTRIBUTES), - NULL, 0); - if(!NT_SUCCESS(Status)) - { - TRACE("Failed to get mouse attributes\n"); - } - - /* - * Receive and process mouse input. - */ - while(InputThreadsRunning) - { - MOUSE_INPUT_DATA MouseInput; - Status = ZwReadFile(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)) - { - ERR("Win32K: Failed to read from mouse.\n"); - return; //(Status); - } + &MouIosb, + &MouseInput, + sizeof(MOUSE_INPUT_DATA), + &ByteOffset, + NULL); + } + + 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) + { + KbdStatus = ZwReadFile(ghKeyboardDevice, + NULL, + NULL, + NULL, + &KbdIosb, + &KeyInput, + sizeof(KEYBOARD_INPUT_DATA), + &ByteOffset, + NULL); + + } + 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) + { + /* 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"); - } -} - -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) - { - 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", + else if (MouStatus != STATUS_PENDING) + ERR("Failed to read from mouse: %x.\n", MouStatus); + + /* Have we successed reading from keyboard? */ + if (NT_SUCCESS(KbdStatus) && KbdStatus != STATUS_PENDING) + { + 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 @@ 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 @@
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 @@ 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 @@ return TRUE; }
+/* + * NtUserSendInput + * + * Generates input events from software + */ UINT APIENTRY NtUserSendInput(