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/in…
==============================================================================
--- 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/ma…
==============================================================================
--- 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/nt…
==============================================================================
--- 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/nt…
==============================================================================
--- 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/nt…
==============================================================================
--- 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_);