Author: jimtabor Date: Thu Jan 15 17:15:31 2009 New Revision: 38779
URL: http://svn.reactos.org/svn/reactos?rev=38779&view=rev Log: - Rewrite Timers, nothing is using it except a bogus system timer for raw input thread is loaded and running.
Modified: trunk/reactos/subsystems/win32/win32k/include/input.h trunk/reactos/subsystems/win32/win32k/include/tags.h trunk/reactos/subsystems/win32/win32k/include/timer.h trunk/reactos/subsystems/win32/win32k/ntuser/input.c trunk/reactos/subsystems/win32/win32k/ntuser/message.c trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c trunk/reactos/subsystems/win32/win32k/ntuser/timer.c
Modified: trunk/reactos/subsystems/win32/win32k/include/input.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/input.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/input.h [iso-8859-1] Thu Jan 15 17:15:31 2009 @@ -37,4 +37,6 @@ #define ThreadHasInputAccess(W32Thread) \ (TRUE)
+extern PTHREADINFO ptiRawInput; + #endif /* _WIN32K_INPUT_H */
Modified: trunk/reactos/subsystems/win32/win32k/include/tags.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/tags.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/tags.h [iso-8859-1] Thu Jan 15 17:15:31 2009 @@ -26,6 +26,7 @@ #define TAG_CALLBACK TAG('C', 'B', 'C', 'K') /* callback memory */ #define TAG_WINSTA TAG('W', 'S', 'T', 'A') /* window station */ #define TAG_PDCE TAG('U', 's', 'd', 'c') /* dce */ +#define TAG_INPUT TAG('U', 's', 's', 'y') /* Input */
/* gdi objects from the handle table */ #define TAG_DC TAG('G', 'l', 'a', '1') /* dc */
Modified: trunk/reactos/subsystems/win32/win32k/include/timer.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/timer.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/timer.h [iso-8859-1] Thu Jan 15 17:15:31 2009 @@ -4,7 +4,7 @@ typedef struct _TIMER { LIST_ENTRY ptmrList; - PW32THREADINFO pti; + PTHREADINFO pti; PWINDOW_OBJECT pWnd; // hWnd UINT_PTR nID; // Specifies a nonzero timer identifier. INT cmsCountdown; // uElapse @@ -22,13 +22,19 @@ #define TMRF_INIT 0x0008 #define TMRF_ONESHOT 0x0010 #define TMRF_WAITING 0x0020 +#define TMRF_TIFROMWND 0x0040 + +extern PKTIMER MasterTimer;
NTSTATUS FASTCALL InitTimerImpl(VOID); BOOL FASTCALL IntKillTimer(HWND Wnd, UINT_PTR IDEvent, BOOL SystemTimer); UINT_PTR FASTCALL IntSetTimer(HWND Wnd, UINT_PTR IDEvent, UINT Elapse, TIMERPROC TimerFunc, BOOL SystemTimer); PTIMER FASTCALL FindSystemTimer(PMSG); -BOOL FASTCALL ValidateTimerCallback(PW32THREADINFO,PWINDOW_OBJECT,WPARAM,LPARAM); +BOOL FASTCALL ValidateTimerCallback(PTHREADINFO,PWINDOW_OBJECT,WPARAM,LPARAM); VOID CALLBACK SystemTimerProc(HWND,UINT,UINT_PTR,DWORD); -UINT_PTR FASTCALL SetSystemTimer(HWND,UINT_PTR,UINT,TIMERPROC); +UINT_PTR FASTCALL SetSystemTimer(PWINDOW_OBJECT,UINT_PTR,UINT,TIMERPROC); +BOOL FASTCALL PostTimerMessages(HWND); +VOID FASTCALL ProcessTimers(VOID); +VOID FASTCALL StartTheTimers(VOID);
#endif /* _WIN32K_TIMER_H */
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] Thu Jan 15 17:15:31 2009 @@ -36,9 +36,12 @@ #include <debug.h>
extern BYTE gQueueKeyStateTable[]; +extern NTSTATUS Win32kInitWin32Thread(PETHREAD Thread);
/* GLOBALS *******************************************************************/
+PTHREADINFO ptiRawInput; +PKTIMER MasterTimer;
static HANDLE MouseDeviceHandle; static HANDLE MouseThreadHandle; @@ -46,6 +49,8 @@ static HANDLE KeyboardThreadHandle; static CLIENT_ID KeyboardThreadId; static HANDLE KeyboardDeviceHandle; +static HANDLE RawInputThreadHandle; +static CLIENT_ID RawInputThreadId; static KEVENT InputThreadsStart; static BOOLEAN InputThreadsRunning = FALSE;
@@ -468,7 +473,6 @@ MSG msg; PUSER_MESSAGE_QUEUE FocusQueue; struct _ETHREAD *FocusThread; - extern NTSTATUS Win32kInitWin32Thread(PETHREAD Thread);
PKEYBOARD_INDICATOR_TRANSLATION IndicatorTrans = NULL; UINT ModifierState = 0; @@ -832,6 +836,79 @@ }
+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; + + MasterTimer = ExAllocatePoolWithTag(NonPagedPool, sizeof(KTIMER), TAG_INPUT); + if (!MasterTimer) + { + DPRINT1("Win32K: Failed making Raw Input thread a win32 thread.\n"); + return; + } + KeInitializeTimer(MasterTimer); + Objects[1] = MasterTimer; + + // This thread requires win32k! + Status = Win32kInitWin32Thread(PsGetCurrentThread()); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Win32K: Failed making Raw Input thread a win32 thread.\n"); + return; //(Status); + } + + ptiRawInput = PsGetCurrentThreadWin32Thread(); + DPRINT1("\nRaw 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(;;) + { + DPRINT( "Raw Input Thread Waiting for start event\n" ); + + Status = KeWaitForMultipleObjects( 2, + Objects, + WaitAll, //WaitAny, + WrUserRequest, + KernelMode, + TRUE, + NULL, + NULL); + DPRINT( "Raw Input Thread Starting...\n" ); + + ProcessTimers(); + } + DPRINT1("Raw Input Thread Exit!\n"); +} + NTSTATUS FASTCALL InitInputImpl(VOID) { @@ -843,6 +920,18 @@ if(!UserInitDefaultKeyboardLayout()) { DPRINT1("Failed to initialize default keyboard layout!\n"); + } + + Status = PsCreateSystemThread(&RawInputThreadHandle, + THREAD_ALL_ACCESS, + NULL, + NULL, + &RawInputThreadId, + RawInputThreadMain, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Win32K: Failed to create raw thread.\n"); }
Status = PsCreateSystemThread(&KeyboardThreadHandle,
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/message.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] Thu Jan 15 17:15:31 2009 @@ -360,7 +360,7 @@ { if (pMsg->message == WM_TIMER) { - if (ValidateTimerCallback(GetW32ThreadInfo(),Window,pMsg->wParam,pMsg->lParam)) + if (ValidateTimerCallback(PsGetCurrentThreadWin32Thread(),Window,pMsg->wParam,pMsg->lParam)) { return co_IntCallWindowProc((WNDPROC)pMsg->lParam, TRUE, @@ -829,6 +829,11 @@ goto MsgExit; }
+ if (ThreadQueue->WakeMask & QS_TIMER) + if (PostTimerMessages(hWnd)) // If there are timers ready, + goto CheckMessages; // go back and process them. + + // LOL! Polling Timer Queue? How much time is spent doing this? /* Check for WM_(SYS)TIMER messages */ Present = MsqGetTimerMessage(ThreadQueue, hWnd, MsgFilterMin, MsgFilterMax, &Msg->Msg, RemoveMessages);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/ntstubs.c [iso-8859-1] Thu Jan 15 17:15:31 2009 @@ -1117,7 +1117,7 @@ goto Exit; }
- Ret = ValidateTimerCallback(GetW32ThreadInfo(), Window, wParam, lParam); + Ret = ValidateTimerCallback(PsGetCurrentThreadWin32Thread(), Window, wParam, lParam);
Exit: UserLeave();
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/timer.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/timer.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/timer.c [iso-8859-1] Thu Jan 15 17:15:31 2009 @@ -37,6 +37,9 @@ /* GLOBALS *******************************************************************/
static PTIMER FirstpTmr = NULL; +static LONG TimeLast = 0; + +#define MAX_ELAPSE_TIME 0x7FFFFFFF
/* Windows 2000 has room for 32768 window-less timers */ #define NUM_WINDOW_LESS_TIMERS 1024 @@ -54,6 +57,7 @@ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&Mutex)
/* FUNCTIONS *****************************************************************/ +static PTIMER FASTCALL CreateTimer(VOID) @@ -144,7 +148,7 @@
BOOL FASTCALL -ValidateTimerCallback(PW32THREADINFO pti, +ValidateTimerCallback(PTHREADINFO pti, PWINDOW_OBJECT Window, WPARAM wParam, LPARAM lParam) @@ -158,7 +162,7 @@ { if ( (lParam == (LPARAM)pTmr->pfn) && (pTmr->flags & (TMRF_SYSTEM|TMRF_RIT)) && - (pTmr->pti->pi == pti->pi) ) + (pTmr->pti->ThreadInfo->kpi == pti->ThreadInfo->kpi) ) break;
pTmr = (PTIMER)pTmr->ptmrList.Flink; @@ -172,13 +176,73 @@
// Rename it to IntSetTimer after move. UINT_PTR FASTCALL -InternalSetTimer(HWND Wnd, UINT_PTR IDEvent, UINT Elapse, TIMERPROC TimerFunc, BOOL SystemTimer) -{ - return 0; +InternalSetTimer( PWINDOW_OBJECT Window, + UINT_PTR IDEvent, + UINT Elapse, + TIMERPROC TimerFunc, + INT Type) +{ + PTIMER pTmr; + LARGE_INTEGER DueTime; + DueTime.QuadPart = (LONGLONG)(-10000000); + +#if 0 + /* Windows NT/2k/XP behaviour */ + if (Elapse > MAX_ELAPSE_TIME) + { + DPRINT("Adjusting uElapse\n"); + Elapse = 1; + } +#else + /* Windows XP SP2 and Windows Server 2003 behaviour */ + if (Elapse > MAX_ELAPSE_TIME) + { + DPRINT("Adjusting uElapse\n"); + Elapse = MAX_ELAPSE_TIME; + } +#endif + + /* Windows 2k/XP and Windows Server 2003 SP1 behaviour */ + if (Elapse < 10) + { + DPRINT("Adjusting uElapse\n"); + Elapse = 10; + } + + pTmr = FindTimer(Window, IDEvent, Type, FALSE); + if (!pTmr) + { + pTmr = CreateTimer(); + if (!pTmr) return 0; + + if (Window && (Type & TMRF_TIFROMWND)) + pTmr->pti = Window->OwnerThread->Tcb.Win32Thread; + else + { + if (Type & TMRF_RIT) + pTmr->pti = ptiRawInput; + else + pTmr->pti = PsGetCurrentThreadWin32Thread(); + } + pTmr->pWnd = Window; + pTmr->cmsCountdown = Elapse; + pTmr->cmsRate = Elapse; + pTmr->flags = Type|TMRF_INIT; // Set timer to Init mode. + pTmr->pfn = TimerFunc; + pTmr->nID = IDEvent; + + InsertTailList(&FirstpTmr->ptmrList, &pTmr->ptmrList); + } + + // Start the timer thread! + KeSetTimer(MasterTimer, DueTime, NULL); + + if (!pTmr->nID) return 1; + return pTmr->nID; }
// -// Process system timers. +// Process win32k system timers. // VOID CALLBACK @@ -187,18 +251,147 @@ UINT_PTR idEvent, DWORD dwTime) { + DPRINT( "Timer Running!\n" ); +} + +VOID +FASTCALL +StartTheTimers(VOID) +{ + // Need to start gdi syncro timers then start timer with Hang App proc + // that calles Idle process so the screen savers will know to run...... + InternalSetTimer(NULL, 0, 1000, SystemTimerProc, TMRF_RIT); }
UINT_PTR FASTCALL -SetSystemTimer( HWND hWnd, +SetSystemTimer( PWINDOW_OBJECT Window, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc) { - return 0; -} - + if (Window && Window->OwnerThread->ThreadsProcess != PsGetCurrentProcess()) + { + SetLastWin32Error(ERROR_ACCESS_DENIED); + return 0; + } + return InternalSetTimer( Window, nIDEvent, uElapse, lpTimerFunc, TMRF_SYSTEM); +} + +BOOL +FASTCALL +PostTimerMessages(HWND hWnd) +{ + PUSER_MESSAGE_QUEUE ThreadQueue; + MSG Msg; + PTHREADINFO pti; + PWINDOW_OBJECT pWnd = NULL; + BOOL Hit = FALSE; + PTIMER pTmr = FirstpTmr; + + if (!pTmr) return FALSE; + + if (hWnd) + { + pWnd = UserGetWindowObject(hWnd); + if (!pWnd || !pWnd->Wnd) return FALSE; + } + + pti = PsGetCurrentThreadWin32Thread(); + ThreadQueue = pti->MessageQueue; + + KeEnterCriticalRegion(); + do + { + if ( (pTmr->flags & TMRF_READY) && + (pTmr->pti == pti) && + (pTmr->pWnd == pWnd)) + { + Msg.hwnd = hWnd; + Msg.message = (pTmr->flags & TMRF_SYSTEM) ? WM_SYSTIMER : WM_TIMER; + Msg.wParam = (WPARAM) pTmr->nID; + Msg.lParam = (LPARAM) pTmr->pfn; + MsqPostMessage(ThreadQueue, &Msg, FALSE, QS_POSTMESSAGE); + + pTmr->flags &= ~TMRF_READY; + ThreadQueue->WakeMask = ~QS_TIMER; + Hit = TRUE; + } + + pTmr = (PTIMER)pTmr->ptmrList.Flink; + } while (pTmr != FirstpTmr); + KeLeaveCriticalRegion(); + + return Hit; +} + +VOID +FASTCALL +ProcessTimers(VOID) +{ + LARGE_INTEGER TickCount, DueTime; + LONG Time; + PTIMER pTmr = FirstpTmr; + + if (!pTmr) return; + + UserEnterExclusive(); + + KeQueryTickCount(&TickCount); + Time = MsqCalculateMessageTime(&TickCount); + + DueTime.QuadPart = (LONGLONG)(-10000000); + + do + { + if (pTmr->flags & TMRF_WAITING) + { + pTmr = (PTIMER)pTmr->ptmrList.Flink; + continue; + } + + if (pTmr->flags & TMRF_INIT) + pTmr->flags &= ~TMRF_INIT; // Skip this run. + else + { + if (pTmr->cmsCountdown < 0) + { + if (!(pTmr->flags & TMRF_READY)) + { + if (pTmr->flags & TMRF_ONESHOT) + pTmr->flags |= TMRF_WAITING; + + if (pTmr->flags & TMRF_RIT) + { + // Hard coded call here, inside raw input thread. + pTmr->pfn(NULL, WM_SYSTIMER, pTmr->nID, (LPARAM)pTmr); + } + else + { + pTmr->flags |= TMRF_READY; // Set timer ready to be ran. + // Set thread message queue for this timer. + if (pTmr->pti->MessageQueue) + { // Wakeup thread + pTmr->pti->MessageQueue->WakeMask |= QS_TIMER; + KeSetEvent(pTmr->pti->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE); + } + } + } + pTmr->cmsCountdown = pTmr->cmsRate; + } + else + pTmr->cmsCountdown -= Time - TimeLast; + } + pTmr = (PTIMER)pTmr->ptmrList.Flink; + } while (pTmr != FirstpTmr); + + // Restart the timer thread! + KeSetTimer(MasterTimer, DueTime, NULL); + + TimeLast = Time; + + UserLeave(); +}
// //