Congrats, good stuff Michael :) -----Original Message----- From: ros-diffs-boun...@reactos.org [mailto:ros-diffs-boun...@reactos.org] On Behalf Of mjmar...@svn.reactos.org Sent: 15 May 2010 20:41 To: ros-di...@reactos.org Subject: [ros-diffs] [mjmartin] 47226: [win32k] - Change the first parameter type from HWND to PWINDOW_OBJECT for IntKillTimer as it makes more sense. Activate IntSetTimer, already done by James. - Add flag TMRF_DELETEPENDING. Destroy timers when this flag is set
Author: mjmartin Date: Sat May 15 21:40:33 2010 New Revision: 47226 URL: http://svn.reactos.org/svn/reactos?rev=47226&view=rev Log: [win32k] - Change the first parameter type from HWND to PWINDOW_OBJECT for IntKillTimer as it makes more sense. Activate IntSetTimer, already done by James. - Add flag TMRF_DELETEPENDING. Destroy timers when this flag is set in ProcessTimers to allow any timers that have expired to have the WM_SYSTIMER/WM_TIMER messages posted to message queue before being destroyed. - Fix error in FindTimer, it was always returning a Timer and it needed to return NULL if the specified timer did not exist. - Fix error in PostTimerMessages, need to handle cases where the Window object is NULL which occurs when requesting messages for any window belonging to the thread. - In co_IntPeekMessage, simply call PostTimerMessages to have WM_SYSTIMER/WM_TIMER messages posted for expired timers. Remove call to old timer message handling. - TODO: Code using the old timer implementation needs removed. - Fixes bugs #2393, #3634, #2835. Commit dedicated to JT and Mr. Roboto. Modified: trunk/reactos/subsystems/win32/win32k/include/timer.h trunk/reactos/subsystems/win32/win32k/main/dllmain.c trunk/reactos/subsystems/win32/win32k/ntuser/caret.c trunk/reactos/subsystems/win32/win32k/ntuser/message.c trunk/reactos/subsystems/win32/win32k/ntuser/timer.c Modified: trunk/reactos/subsystems/win32/win32k/include/timer.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/include/timer.h?rev=47226&r1=47225&r2=47226&view=diff ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/timer.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/timer.h [iso-8859-1] Sat May 15 21:40:33 2010 @@ -23,12 +23,14 @@ #define TMRF_ONESHOT 0x0010 #define TMRF_WAITING 0x0020 #define TMRF_TIFROMWND 0x0040 +#define TMRF_DELETEPENDING 0x8000 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); +BOOL FASTCALL DestroyTimersForThread(PTHREADINFO pti); +BOOL FASTCALL IntKillTimer(PWINDOW_OBJECT Window, UINT_PTR IDEvent, BOOL SystemTimer); +UINT_PTR FASTCALL IntSetTimer(PWINDOW_OBJECT Window, UINT_PTR IDEvent, UINT Elapse, TIMERPROC TimerFunc, INT Type); PTIMER FASTCALL FindSystemTimer(PMSG); BOOL FASTCALL ValidateTimerCallback(PTHREADINFO,PWINDOW_OBJECT,WPARAM,LPARAM); VOID CALLBACK SystemTimerProc(HWND,UINT,UINT_PTR,DWORD); Modified: trunk/reactos/subsystems/win32/win32k/main/dllmain.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/main/dllmain.c?rev=47226&r1=47225&r2=47226&view=diff ============================================================================== --- trunk/reactos/subsystems/win32/win32k/main/dllmain.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/main/dllmain.c [iso-8859-1] Sat May 15 21:40:33 2010 @@ -290,6 +290,8 @@ Win32Thread->TIF_flags |= TIF_INCLEANUP; DceFreeThreadDCE(Win32Thread); HOOK_DestroyThreadHooks(Thread); + /* Cleanup timers */ + DestroyTimersForThread(Win32Thread); UnregisterThreadHotKeys(Thread); /* what if this co_ func crash in umode? what will clean us up then? */ co_DestroyThreadWindows(Thread); Modified: trunk/reactos/subsystems/win32/win32k/ntuser/caret.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/caret.c?rev=47226&r1=47225&r2=47226&view=diff ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/caret.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/caret.c [iso-8859-1] Sat May 15 21:40:33 2010 @@ -189,7 +189,7 @@ ThreadQueue->CaretInfo->Pos.x = X; ThreadQueue->CaretInfo->Pos.y = Y; co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0); - IntSetTimer(ThreadQueue->CaretInfo->hWnd, IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TRUE); + IntSetTimer(UserGetWindowObject(ThreadQueue->CaretInfo->hWnd), IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TMRF_SYSTEM); } return TRUE; } @@ -302,7 +302,7 @@ { co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0); } - IntSetTimer(ThreadQueue->CaretInfo->hWnd, IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TRUE); + IntSetTimer(UserGetWindowObject(ThreadQueue->CaretInfo->hWnd), IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TMRF_SYSTEM); } return TRUE; Modified: trunk/reactos/subsystems/win32/win32k/ntuser/message.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/message.c?rev=47226&r1=47225&r2=47226&view=diff ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] Sat May 15 21:40:33 2010 @@ -880,23 +880,8 @@ goto MsgExit; } - if (ThreadQueue->WakeMask & QS_TIMER) - if (PostTimerMessages(Window)) // 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, - Window, - MsgFilterMin, - MsgFilterMax, - &Msg->Msg, - RemoveMessages); - if (Present) - { - Msg->FreeLParam = FALSE; - goto MessageFound; - } + if (PostTimerMessages(Window)) + goto CheckMessages; if(Present) { Modified: trunk/reactos/subsystems/win32/win32k/ntuser/timer.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/timer.c?rev=47226&r1=47225&r2=47226&view=diff ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/timer.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/timer.c [iso-8859-1] Sat May 15 21:40:33 2010 @@ -57,7 +57,7 @@ { Ret = UserCreateObject(gHandleTable, NULL, &Handle, otTimer, sizeof(TIMER)); if (Ret) InsertTailList(&FirstpTmr->ptmrList, &Ret->ptmrList); - } + } return Ret; } @@ -68,8 +68,8 @@ { if (pTmr) { - RemoveEntryList(&pTmr->ptmrList); - UserDeleteObject( UserHMGetHandle(pTmr), otTimer); + /* Set the flag, it will be removed when ready */ + pTmr->flags |= TMRF_DELETEPENDING; return TRUE; } return FALSE; @@ -83,7 +83,7 @@ BOOL Distroy) { PLIST_ENTRY pLE; - PTIMER pTmr = FirstpTmr; + PTIMER pTmr = FirstpTmr, RetTmr = NULL; KeEnterCriticalRegion(); do { @@ -96,8 +96,8 @@ if (Distroy) { RemoveTimer(pTmr); - pTmr = (PTIMER)1; // We are here to remove the timer. } + RetTmr = pTmr; break; } @@ -106,7 +106,7 @@ } while (pTmr != FirstpTmr); KeLeaveCriticalRegion(); - return pTmr; + return RetTmr; } PTIMER @@ -162,15 +162,15 @@ return TRUE; } -// Rename it to IntSetTimer after move. UINT_PTR FASTCALL -InternalSetTimer( PWINDOW_OBJECT Window, +IntSetTimer( PWINDOW_OBJECT Window, UINT_PTR IDEvent, UINT Elapse, TIMERPROC TimerFunc, INT Type) { PTIMER pTmr; + UINT Ret= IDEvent; LARGE_INTEGER DueTime; DueTime.QuadPart = (LONGLONG)(-10000000); @@ -195,6 +195,24 @@ { DPRINT("Adjusting uElapse\n"); Elapse = 10; + } + + if ((Window == NULL) && (!(Type & TMRF_SYSTEM))) + { + IntLockWindowlessTimerBitmap(); + IDEvent = RtlFindClearBitsAndSet(&WindowLessTimersBitMap, 1, HintIndex); + + if (IDEvent == (UINT_PTR) -1) + { + IntUnlockWindowlessTimerBitmap(); + DPRINT1("Unable to find a free window-less timer id\n"); + SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES); + return 0; + } + + HintIndex = ++IDEvent; + IntUnlockWindowlessTimerBitmap(); + Ret = IDEvent; } pTmr = FindTimer(Window, IDEvent, Type, FALSE); @@ -215,18 +233,23 @@ 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); + pTmr->flags = Type|TMRF_INIT; // Set timer to Init mode. + } + + pTmr->cmsCountdown = Elapse; + pTmr->cmsRate = Elapse; + if (pTmr->flags & TMRF_DELETEPENDING) + { + pTmr->flags &= ~TMRF_DELETEPENDING; } // Start the timer thread! - KeSetTimer(MasterTimer, DueTime, NULL); - - if (!pTmr->nID) return 1; - return pTmr->nID; + if (pTmr == FirstpTmr) + KeSetTimer(MasterTimer, DueTime, NULL); + + return Ret; } // @@ -248,7 +271,7 @@ { // 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); + IntSetTimer(NULL, 0, 1000, SystemTimerProc, TMRF_RIT); } UINT_PTR @@ -256,14 +279,14 @@ SystemTimerSet( PWINDOW_OBJECT Window, UINT_PTR nIDEvent, UINT uElapse, - TIMERPROC lpTimerFunc) + TIMERPROC lpTimerFunc) { if (Window && Window->pti->pEThread->ThreadsProcess != PsGetCurrentProcess()) { SetLastWin32Error(ERROR_ACCESS_DENIED); return 0; } - return InternalSetTimer( Window, nIDEvent, uElapse, lpTimerFunc, TMRF_SYSTEM); + return IntSetTimer( Window, nIDEvent, uElapse, lpTimerFunc, TMRF_SYSTEM); } BOOL @@ -279,28 +302,23 @@ if (!pTmr) return FALSE; - if (Window && ((ULONG_PTR)Window != 1)) - { - if (!Window->Wnd) return FALSE; - } - pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; KeEnterCriticalRegion(); + do { if ( (pTmr->flags & TMRF_READY) && (pTmr->pti == pti) && - (pTmr->pWnd == Window)) + ((pTmr->pWnd == Window) || (Window == NULL) ) ) { - ASSERT((ULONG_PTR)Window != 1); - Msg.hwnd = Window->hSelf; + Msg.hwnd = (pTmr->pWnd) ? pTmr->pWnd->hSelf : 0; 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); - + + MsqPostMessage(ThreadQueue, &Msg, FALSE, QS_TIMER); pTmr->flags &= ~TMRF_READY; ThreadQueue->WakeMask = ~QS_TIMER; Hit = TRUE; @@ -309,6 +327,7 @@ pLE = pTmr->ptmrList.Flink; pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList); } while (pTmr != FirstpTmr); + KeLeaveCriticalRegion(); return Hit; @@ -330,7 +349,7 @@ KeQueryTickCount(&TickCount); Time = MsqCalculateMessageTime(&TickCount); - DueTime.QuadPart = (LONGLONG)(-10000000); + DueTime.QuadPart = (LONGLONG)(-1000000); do { @@ -341,8 +360,10 @@ continue; } - if (pTmr->flags & TMRF_INIT) + if (pTmr->flags & TMRF_INIT) + { pTmr->flags &= ~TMRF_INIT; // Skip this run. + } else { if (pTmr->cmsCountdown < 0) @@ -363,16 +384,35 @@ // 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); + if (pTmr->pti->MessageQueue->WakeMask & QS_POSTMESSAGE) + KeSetEvent(pTmr->pti->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE); } } } - pTmr->cmsCountdown = pTmr->cmsRate; + if (pTmr->flags & TMRF_DELETEPENDING) + { + DPRINT("Removing Timer %x from List\n", pTmr); + + /* FIXME: Fix this!!!! */ +/* + if (!pTmr->pWnd) + { + DPRINT1("Clearing Bits for WindowLess Timer\n"); + IntLockWindowlessTimerBitmap(); + RtlSetBits(&WindowLessTimersBitMap, pTmr->nID, 1); + IntUnlockWindowlessTimerBitmap(); + } +*/ + RemoveEntryList(&pTmr->ptmrList); + UserDeleteObject( UserHMGetHandle(pTmr), otTimer); + } + else + pTmr->cmsCountdown = pTmr->cmsRate; } else pTmr->cmsCountdown -= Time - TimeLast; } + pLE = pTmr->ptmrList.Flink; pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList); } while (pTmr != FirstpTmr); @@ -391,7 +431,7 @@ // // UINT_PTR FASTCALL -IntSetTimer(HWND Wnd, UINT_PTR IDEvent, UINT Elapse, TIMERPROC TimerFunc, BOOL SystemTimer) +InternalSetTimer(HWND Wnd, UINT_PTR IDEvent, UINT Elapse, TIMERPROC TimerFunc, BOOL SystemTimer) { PWINDOW_OBJECT Window; UINT_PTR Ret = 0; @@ -477,17 +517,66 @@ return 0; } - +if (Ret == 0) ASSERT(FALSE); return Ret; } - BOOL FASTCALL -IntKillTimer(HWND Wnd, UINT_PTR IDEvent, BOOL SystemTimer) +DestroyTimersForThread(PTHREADINFO pti) +{ + PLIST_ENTRY pLE; + PTIMER pTmr = FirstpTmr; + BOOL TimersRemoved = FALSE; + + if (FirstpTmr == NULL) + return FALSE; + + KeEnterCriticalRegion(); + + do + { + if ((pTmr) && (pTmr->pti == pti)) + { + pTmr->flags &= ~TMRF_READY; + pTmr->flags |= TMRF_DELETEPENDING; + TimersRemoved = TRUE; + } + pLE = pTmr->ptmrList.Flink; + pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList); + } while (pTmr != FirstpTmr); + + KeLeaveCriticalRegion(); + + return TimersRemoved; +} + + +BOOL FASTCALL +IntKillTimer(PWINDOW_OBJECT Window, UINT_PTR IDEvent, BOOL SystemTimer) +{ + PTIMER pTmr = NULL; + DPRINT("IntKillTimer Window %x id %p systemtimer %s\n", + Window, IDEvent, SystemTimer ? "TRUE" : "FALSE"); + + if (IDEvent == 0) + return FALSE; + + pTmr = FindTimer(Window, IDEvent, SystemTimer ? TMRF_SYSTEM : 0, TRUE); + return pTmr ? TRUE : FALSE; +} + + +// +// +// Old Kill Timer +// +// +BOOL FASTCALL +InternalKillTimer(HWND Wnd, UINT_PTR IDEvent, BOOL SystemTimer) { PTHREADINFO pti; PWINDOW_OBJECT Window = NULL; - + DPRINT("IntKillTimer wnd %x id %p systemtimer %s\n", Wnd, IDEvent, SystemTimer ? "TRUE" : "FALSE"); @@ -495,7 +584,7 @@ if (Wnd) { Window = UserGetWindowObject(Wnd); - + if (! MsqKillTimer(pti->MessageQueue, Wnd, IDEvent, SystemTimer ? WM_SYSTIMER : WM_TIMER)) { @@ -574,7 +663,7 @@ DPRINT("Enter NtUserSetTimer\n"); UserEnterExclusive(); - RETURN(IntSetTimer(hWnd, nIDEvent, uElapse, lpTimerFunc, FALSE)); + RETURN(IntSetTimer(UserGetWindowObject(hWnd), nIDEvent, uElapse, lpTimerFunc, 0)); CLEANUP: DPRINT("Leave NtUserSetTimer, ret=%i\n", _ret_); @@ -591,12 +680,15 @@ UINT_PTR uIDEvent ) { + PWINDOW_OBJECT Window; DECLARE_RETURN(BOOL); DPRINT("Enter NtUserKillTimer\n"); UserEnterExclusive(); - RETURN(IntKillTimer(hWnd, uIDEvent, FALSE)); + Window = UserGetWindowObject(hWnd); + + RETURN(IntKillTimer(Window, uIDEvent, FALSE)); CLEANUP: DPRINT("Leave NtUserKillTimer, ret=%i\n", _ret_); @@ -620,7 +712,7 @@ UserEnterExclusive(); // This is wrong, lpTimerFunc is NULL! - RETURN(IntSetTimer(hWnd, nIDEvent, uElapse, lpTimerFunc, TRUE)); + RETURN(IntSetTimer(UserGetWindowObject(hWnd), nIDEvent, uElapse, lpTimerFunc, TMRF_SYSTEM)); CLEANUP: DPRINT("Leave NtUserSetSystemTimer, ret=%i\n", _ret_); _______________________________________________ Ros-dev mailing list Ros-dev@reactos.org http://www.reactos.org/mailman/listinfo/ros-dev