8 modified files
reactos/subsys/win32k/include
diff -u -r1.44 -r1.45
--- msgqueue.h 25 Dec 2004 22:59:10 -0000 1.44
+++ msgqueue.h 29 Dec 2004 19:55:01 -0000 1.45
@@ -40,6 +40,16 @@
LIST_ENTRY ListEntry;
} USER_SENT_MESSAGE_NOTIFY, *PUSER_SENT_MESSAGE_NOTIFY;
+typedef struct _TIMER_ENTRY{
+ LIST_ENTRY ListEntry;
+ LARGE_INTEGER ExpiryTime;
+ HWND Wnd;
+ UINT_PTR IDEvent;
+ UINT Period;
+ TIMERPROC TimerFunc;
+ UINT Msg;
+} TIMER_ENTRY, *PTIMER_ENTRY;
+
typedef struct _USER_MESSAGE_QUEUE
{
/* Reference counter, only access this variable with interlocked functions! */
@@ -55,6 +65,8 @@
LIST_ENTRY NotifyMessagesListHead;
/* Queue for hardware messages for the queue. */
LIST_ENTRY HardwareMessagesListHead;
+ /* List of timers, sorted on expiry time (earliest first) */
+ LIST_ENTRY TimerListHead;
/* Lock for the hardware message list. */
KMUTEX HardwareLock;
/* Lock for the queue. */
@@ -144,13 +156,12 @@
PUSER_MESSAGE_QUEUE FASTCALL
MsqGetHardwareMessageQueue(VOID);
NTSTATUS FASTCALL
-MsqWaitForNewMessage(PUSER_MESSAGE_QUEUE MessageQueue);
-NTSTATUS FASTCALL
MsqInitializeImpl(VOID);
BOOLEAN FASTCALL
MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue);
NTSTATUS FASTCALL
-MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue);
+MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue, HWND WndFilter,
+ UINT MsgFilterMin, UINT MsgFilterMax);
VOID FASTCALL
MsqSendNotifyMessage(PUSER_MESSAGE_QUEUE MessageQueue,
PUSER_SENT_MESSAGE_NOTIFY NotifyMessage);
@@ -248,6 +259,24 @@
BOOL FASTCALL
IntMsqClearWakeMask(VOID);
+BOOLEAN FASTCALL
+MsqSetTimer(PUSER_MESSAGE_QUEUE MessageQueue, HWND Wnd,
+ UINT_PTR IDEvent, UINT Period, TIMERPROC TimerFunc,
+ UINT Msg);
+BOOLEAN FASTCALL
+MsqKillTimer(PUSER_MESSAGE_QUEUE MessageQueue, HWND Wnd,
+ UINT_PTR IDEvent, UINT Msg);
+BOOLEAN FASTCALL
+MsqGetTimerMessage(PUSER_MESSAGE_QUEUE MessageQueue,
+ HWND WndFilter, UINT MsgFilterMin, UINT MsgFilterMax,
+ MSG *Msg, BOOLEAN Restart);
+BOOLEAN FASTCALL
+MsqGetFirstTimerExpiry(PUSER_MESSAGE_QUEUE MessageQueue,
+ HWND WndFilter, UINT MsgFilterMin, UINT MsgFilterMax,
+ PLARGE_INTEGER FirstTimerExpiry);
+VOID FASTCALL
+MsqRemoveTimersWindow(PUSER_MESSAGE_QUEUE MessageQueue, HWND Wnd);
+
#endif /* _WIN32K_MSGQUEUE_H */
/* EOF */
reactos/subsys/win32k/include
diff -u -r1.7 -r1.8
--- timer.h 4 Aug 2004 22:31:17 -0000 1.7
+++ timer.h 29 Dec 2004 19:55:01 -0000 1.8
@@ -1,18 +1,8 @@
#ifndef _WIN32K_TIMER_H
#define _WIN32K_TIMER_H
-typedef struct _MSG_TIMER_ENTRY{
- LIST_ENTRY ListEntry;
- LARGE_INTEGER Timeout;
- HANDLE ThreadID;
- UINT Period;
- MSG Msg;
-} MSG_TIMER_ENTRY, *PMSG_TIMER_ENTRY;
-
NTSTATUS FASTCALL InitTimerImpl(VOID);
-VOID FASTCALL RemoveTimersThread(HANDLE ThreadID);
-VOID FASTCALL RemoveTimersWindow(HWND hWnd);
-PMSG_TIMER_ENTRY FASTCALL IntRemoveTimer(HWND hWnd, UINT_PTR IDEvent, HANDLE ThreadID, BOOL SysTimer);
-UINT_PTR FASTCALL IntSetTimer(HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc, BOOL SystemTimer);
+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);
#endif /* _WIN32K_TIMER_H */
reactos/subsys/win32k/main
diff -u -r1.85 -r1.86
--- dllmain.c 24 Dec 2004 17:45:58 -0000 1.85
+++ dllmain.c 29 Dec 2004 19:55:01 -0000 1.86
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: dllmain.c,v 1.85 2004/12/24 17:45:58 weiden Exp $
+/* $Id: dllmain.c,v 1.86 2004/12/29 19:55:01 gvg Exp $
*
* Entry Point for win32k.sys
*/
@@ -184,7 +184,6 @@
Win32Thread->IsExiting = TRUE;
HOOK_DestroyThreadHooks(Thread);
- RemoveTimersThread(Win32Thread->MessageQueue);
UnregisterThreadHotKeys(Thread);
DestroyThreadWindows(Thread);
IntBlockInput(Win32Thread, FALSE);
reactos/subsys/win32k/ntuser
diff -u -r1.16 -r1.17
--- caret.c 25 Dec 2004 22:59:10 -0000 1.16
+++ caret.c 29 Dec 2004 19:55:01 -0000 1.17
@@ -1,4 +1,4 @@
-/* $Id: caret.c,v 1.16 2004/12/25 22:59:10 navaraf Exp $
+/* $Id: caret.c,v 1.17 2004/12/29 19:55:01 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -240,7 +240,7 @@
return FALSE;
}
- IntRemoveTimer(hWnd, IDCARETTIMER, PsGetCurrentThreadId(), TRUE);
+ IntKillTimer(hWnd, IDCARETTIMER, TRUE);
ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
@@ -325,7 +325,7 @@
if(ThreadQueue->CaretInfo->Visible)
{
- IntRemoveTimer(hWnd, IDCARETTIMER, PsGetCurrentThreadId(), TRUE);
+ IntKillTimer(hWnd, IDCARETTIMER, TRUE);
IntHideCaret(ThreadQueue->CaretInfo);
ThreadQueue->CaretInfo->Visible = 0;
reactos/subsys/win32k/ntuser
diff -u -r1.78 -r1.79
--- message.c 25 Dec 2004 22:59:10 -0000 1.78
+++ message.c 29 Dec 2004 19:55:01 -0000 1.79
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: message.c,v 1.78 2004/12/25 22:59:10 navaraf Exp $
+/* $Id: message.c,v 1.79 2004/12/29 19:55:01 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -690,7 +690,14 @@
return TRUE;
}
- /* FIXME - get WM_(SYS)TIMER messages */
+ /* Check for WM_(SYS)TIMER messages */
+ Present = MsqGetTimerMessage(ThreadQueue, Wnd, MsgFilterMin, MsgFilterMax,
+ &Msg->Msg, RemoveMessages);
+ if (Present)
+ {
+ Msg->FreeLParam = FALSE;
+ goto MessageFound;
+ }
if(Present)
{
@@ -845,8 +852,8 @@
static BOOL FASTCALL
IntWaitMessage(HWND Wnd,
- UINT MsgFilterMin,
- UINT MsgFilterMax)
+ UINT MsgFilterMin,
+ UINT MsgFilterMax)
{
PUSER_MESSAGE_QUEUE ThreadQueue;
NTSTATUS Status;
@@ -862,9 +869,9 @@
}
/* Nothing found. Wait for new messages. */
- Status = MsqWaitForNewMessages(ThreadQueue);
+ Status = MsqWaitForNewMessages(ThreadQueue, Wnd, MsgFilterMin, MsgFilterMax);
}
- while (STATUS_WAIT_0 <= Status && Status <= STATUS_WAIT_63);
+ while ((STATUS_WAIT_0 <= Status && Status <= STATUS_WAIT_63) || STATUS_TIMEOUT == Status);
SetLastNtError(Status);
reactos/subsys/win32k/ntuser
diff -u -r1.111 -r1.112
--- msgqueue.c 25 Dec 2004 22:59:10 -0000 1.111
+++ msgqueue.c 29 Dec 2004 19:55:01 -0000 1.112
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: msgqueue.c,v 1.111 2004/12/25 22:59:10 navaraf Exp $
+/* $Id: msgqueue.c,v 1.112 2004/12/29 19:55:01 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -53,6 +53,7 @@
static KEVENT HardwareMessageEvent;
static PAGED_LOOKASIDE_LIST MessageLookasideList;
+static PAGED_LOOKASIDE_LIST TimerLookasideList;
#define IntLockSystemMessageQueue(OldIrql) \
KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql)
@@ -145,6 +146,13 @@
sizeof(USER_MESSAGE),
0,
256);
+ ExInitializePagedLookasideList(&TimerLookasideList,
+ NULL,
+ NULL,
+ 0,
+ sizeof(TIMER_ENTRY),
+ 0,
+ 64);
return(STATUS_SUCCESS);
}
@@ -1195,16 +1203,29 @@
}
NTSTATUS FASTCALL
-MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue)
+MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue, HWND WndFilter,
+ UINT MsgFilterMin, UINT MsgFilterMax)
{
PVOID WaitObjects[2] = {MessageQueue->NewMessages, &HardwareMessageEvent};
+ LARGE_INTEGER TimerExpiry;
+ PLARGE_INTEGER Timeout;
+
+ if (MsqGetFirstTimerExpiry(MessageQueue, WndFilter, MsgFilterMin, MsgFilterMax, &TimerExpiry))
+ {
+ Timeout = &TimerExpiry;
+ }
+ else
+ {
+ Timeout = NULL;
+ }
+
return(KeWaitForMultipleObjects(2,
WaitObjects,
WaitAny,
Executive,
UserMode,
FALSE,
- NULL,
+ Timeout,
NULL));
}
@@ -1228,6 +1249,7 @@
InitializeListHead(&MessageQueue->PostedMessagesListHead);
InitializeListHead(&MessageQueue->SentMessagesListHead);
InitializeListHead(&MessageQueue->HardwareMessagesListHead);
+ InitializeListHead(&MessageQueue->TimerListHead);
InitializeListHead(&MessageQueue->DispatchingMessagesHead);
InitializeListHead(&MessageQueue->LocalDispatchingMessagesHead);
KeInitializeMutex(&MessageQueue->HardwareLock, 0);
@@ -1267,6 +1289,7 @@
{
PLIST_ENTRY CurrentEntry;
PUSER_MESSAGE CurrentMessage;
+ PTIMER_ENTRY CurrentTimer;
PUSER_SENT_MESSAGE CurrentSentMessage;
IntLockMessageQueue(MessageQueue);
@@ -1311,6 +1334,14 @@
ExFreePool(CurrentSentMessage);
}
+ /* cleanup timers */
+ while (! IsListEmpty(&MessageQueue->TimerListHead))
+ {
+ CurrentEntry = RemoveHeadList(&MessageQueue->TimerListHead);
+ CurrentTimer = CONTAINING_RECORD(CurrentEntry, TIMER_ENTRY, ListEntry);
+ ExFreeToPagedLookasideList(&TimerLookasideList, CurrentTimer);
+ }
+
/* notify senders of dispatching messages. This needs to be cleaned up if e.g.
ExitThread() was called in a SendMessage() umode callback */
while (!IsListEmpty(&MessageQueue->LocalDispatchingMessagesHead))
@@ -1476,4 +1507,300 @@
return NULL;
}
+#ifndef NDEBUG
+static VOID FASTCALL
+DumpTimerList(PUSER_MESSAGE_QUEUE MessageQueue)
+{
+ PLIST_ENTRY Current;
+ PTIMER_ENTRY Timer;
+
+ Current = MessageQueue->TimerListHead.Flink;
+ if (Current == &MessageQueue->TimerListHead)
+ {
+ DPRINT("timer list is empty for queue %p\n", MessageQueue);
+ }
+ while (Current != &MessageQueue->TimerListHead)
+ {
+ Timer = CONTAINING_RECORD(Current, TIMER_ENTRY, ListEntry);
+ DPRINT("queue %p timer %p expiry %I64d wnd %x id %p period %u timerproc %p msg %u\n",
+ MessageQueue, Timer, Timer->ExpiryTime.QuadPart, Timer->Wnd, Timer->IDEvent,
+ Timer->Period, Timer->TimerFunc, Timer->Msg);
+ Current = Current->Flink;
+ }
+}
+#endif /* ! defined(NDEBUG) */
+
+/* Must have the message queue locked while calling this */
+static VOID FASTCALL
+InsertTimer(PUSER_MESSAGE_QUEUE MessageQueue, PTIMER_ENTRY NewTimer)
+{
+ PLIST_ENTRY Current;
+
+ Current = MessageQueue->TimerListHead.Flink;
+ while (Current != &MessageQueue->TimerListHead)
+ {
+ if (NewTimer->ExpiryTime.QuadPart <
+ CONTAINING_RECORD(Current, TIMER_ENTRY, ListEntry)->ExpiryTime.QuadPart)
+ {
+ break;
+ }
+ Current = Current->Flink;
+ }
+
+ InsertTailList(Current, &NewTimer->ListEntry);
+}
+
+/* Must have the message queue locked while calling this */
+static PTIMER_ENTRY FASTCALL
+RemoveTimer(PUSER_MESSAGE_QUEUE MessageQueue, HWND Wnd, UINT_PTR IDEvent, UINT Msg)
+{
+ PTIMER_ENTRY Timer;
+ PLIST_ENTRY EnumEntry;
+
+ /* Remove timer if already in the queue */
+ EnumEntry = MessageQueue->TimerListHead.Flink;
+ while (EnumEntry != &MessageQueue->TimerListHead)
+ {
+ Timer = CONTAINING_RECORD(EnumEntry, TIMER_ENTRY, ListEntry);
+ EnumEntry = EnumEntry->Flink;
+
+ if (Timer->Wnd == Wnd &&
+ Timer->IDEvent == IDEvent &&
+ Timer->Msg == Msg)
+ {
+ RemoveEntryList(&Timer->ListEntry);
+ return Timer;
+ }
+ }
+
+ return NULL;
+}
+
+BOOLEAN FASTCALL
+MsqSetTimer(PUSER_MESSAGE_QUEUE MessageQueue, HWND Wnd,
+ UINT_PTR IDEvent, UINT Period, TIMERPROC TimerFunc,
+ UINT Msg)
+{
+ PTIMER_ENTRY Timer;
+ LARGE_INTEGER CurrentTime;
+
+ DPRINT("MsqSetTimer queue %p wnd %x id %p period %u timerproc %p msg %d\n",
+ MessageQueue, Wnd, IDEvent, Period, TimerFunc, Msg);
+
+ IntLockMessageQueue(MessageQueue);
+ Timer = RemoveTimer(MessageQueue, Wnd, IDEvent, Msg);
+ if (NULL == Timer)
+ {
+ Timer = ExAllocateFromPagedLookasideList(&TimerLookasideList);
+ if (NULL == Timer)
+ {
+ IntUnLockMessageQueue(MessageQueue);
+ DPRINT1("Failed to allocate timer entry\n");
+ return FALSE;
+ }
+ DPRINT("Allocated new timer entry %p\n", Timer);
+ Timer->Wnd = Wnd;
+ Timer->IDEvent = IDEvent;
+ Timer->Msg = Msg;
+ }
+ else
+ {
+ DPRINT("Updating existing timer entry %p\n", Timer);
+ }
+
+ KeQuerySystemTime(&CurrentTime);
+ Timer->ExpiryTime.QuadPart = CurrentTime.QuadPart +
+ (ULONGLONG) Period * (ULONGLONG) 10000;
+ Timer->Period = Period;
+ Timer->TimerFunc = TimerFunc;
+ DPRINT("Insert timer now %I64d expiry %I64d\n", CurrentTime.QuadPart,
+ Timer->ExpiryTime.QuadPart);
+
+ InsertTimer(MessageQueue, Timer);
+
+#ifndef NDEBUG
+ DumpTimerList(MessageQueue);
+#endif /* ! defined(NDEBUG) */
+
+ IntUnLockMessageQueue(MessageQueue);
+
+ return TRUE;
+}
+
+BOOLEAN FASTCALL
+MsqKillTimer(PUSER_MESSAGE_QUEUE MessageQueue, HWND Wnd,
+ UINT_PTR IDEvent, UINT Msg)
+{
+ PTIMER_ENTRY Timer;
+
+ DPRINT("MsqKillTimer queue %p wnd %x id %p msg %d\n",
+ MessageQueue, Wnd, IDEvent, Msg);
+
+ IntLockMessageQueue(MessageQueue);
+ Timer = RemoveTimer(MessageQueue, Wnd, IDEvent, Msg);
+
+ if (NULL == Timer)
+ {
+ DPRINT("Failed to remove timer from list, not found\n");
+ }
+ else
+ {
+ ExFreeToPagedLookasideList(&TimerLookasideList, Timer);
+ }
+
+#ifndef NDEBUG
+ DumpTimerList(MessageQueue);
+#endif /* ! defined(NDEBUG) */
+
+ IntUnLockMessageQueue(MessageQueue);
+
+ return NULL != Timer;
+}
+
+BOOLEAN FASTCALL
+MsqGetTimerMessage(PUSER_MESSAGE_QUEUE MessageQueue,
+ HWND WndFilter, UINT MsgFilterMin, UINT MsgFilterMax,
+ MSG *Msg, BOOLEAN Restart)
+{
+ PTIMER_ENTRY Timer;
+ LARGE_INTEGER CurrentTime;
+ PLIST_ENTRY EnumEntry;
+ BOOLEAN GotMessage;
+
+ DPRINT("MsqGetTimerMessage queue %p msg %p restart %s\n",
+ MessageQueue, Msg, Restart ? "TRUE" : "FALSE");
+
+ IntLockMessageQueue(MessageQueue);
+ KeQuerySystemTime(&CurrentTime);
+ DPRINT("Current time %I64d\n", CurrentTime.QuadPart);
+ EnumEntry = MessageQueue->TimerListHead.Flink;
+ GotMessage = FALSE;
+ while (EnumEntry != &MessageQueue->TimerListHead)
+ {
+ Timer = CONTAINING_RECORD(MessageQueue->TimerListHead.Flink,
+ TIMER_ENTRY, ListEntry);
+ DPRINT("Checking timer %p wnd %x expiry %I64d\n", Timer, Timer->wnd,
+ Timer->ExpiryTime.QuadPart);
+ EnumEntry = EnumEntry->Flink;
+ if ((NULL == WndFilter || Timer->Wnd == WndFilter) &&
+ ((MsgFilterMin == 0 && MsgFilterMax == 0) ||
+ (MsgFilterMin <= Timer->Msg &&
+ Timer->Msg <= MsgFilterMax)))
+ {
+ if (Timer->ExpiryTime.QuadPart <= CurrentTime.QuadPart)
+ {
+ DPRINT("Timer is expired\n");
+ GotMessage = TRUE;
+ break;
+ }
+ else
+ {
+ DPRINT("No need to check later timers\n");
+ break;
+ }
+ }
+ else
+ {
+ DPRINT("timer %p (wnd %x msg %d) failed filter wnd %x msgmin %d msgmax %d\n",
+ Timer, Timer->Wnd, Timer->Msg, WndFilter, MsgFilterMin, MsgFilterMax);
+ }
+ }
+
+ if (! GotMessage)
+ {
+ DPRINT("No timer pending\n");
+ IntUnLockMessageQueue(MessageQueue);
+ return FALSE;
+ }
+
+ Msg->hwnd = Timer->Wnd;
+ Msg->message = Timer->Msg;
+ Msg->wParam = (WPARAM) Timer->IDEvent;
+ Msg->lParam = (LPARAM) Timer->TimerFunc;
+
+ if (Restart)
+ {
+ RemoveEntryList(&Timer->ListEntry);
+ Timer->ExpiryTime.QuadPart = CurrentTime.QuadPart +
+ (ULONGLONG) Timer->Period * (ULONGLONG) 10000;
+ DPRINT("Restarting timer %p expires %I64d\n", Timer, Timer->ExpiryTime.QuadPart);
+ InsertTimer(MessageQueue, Timer);
+
+#ifndef NDEBUG
+ DumpTimerList(MessageQueue);
+#endif /* ! defined(NDEBUG) */
+ }
+
+ IntUnLockMessageQueue(MessageQueue);
+
+ DPRINT("Created message wnd %x msg %d wParam %u lParam %u\n", Msg->hwnd, Msg->message,
+ Msg->wParam, Msg->lParam);
+
+ return TRUE;
+}
+
+VOID FASTCALL
+MsqRemoveTimersWindow(PUSER_MESSAGE_QUEUE MessageQueue, HWND Wnd)
+{
+ PTIMER_ENTRY Timer;
+ PLIST_ENTRY EnumEntry;
+
+ DPRINT("MsqRemoveTimersWindow queue %p wnd %x\n", MessageQueue, Wnd);
+
+ IntLockMessageQueue(MessageQueue);
+ EnumEntry = MessageQueue->TimerListHead.Flink;
+ while (EnumEntry != &MessageQueue->TimerListHead)
+ {
+ Timer = CONTAINING_RECORD(EnumEntry, TIMER_ENTRY, ListEntry);
+ EnumEntry = EnumEntry->Flink;
+ if (Timer->Wnd == Wnd)
+ {
+ DPRINT("Removing timer %p because its window is going away\n", Timer);
+ RemoveEntryList(&Timer->ListEntry);
+ ExFreeToPagedLookasideList(&TimerLookasideList, Timer);
+ }
+ }
+
+#ifndef NDEBUG
+ DumpTimerList(MessageQueue);
+#endif /* ! defined(NDEBUG) */
+
+ IntUnLockMessageQueue(MessageQueue);
+}
+
+BOOLEAN FASTCALL
+MsqGetFirstTimerExpiry(PUSER_MESSAGE_QUEUE MessageQueue,
+ HWND WndFilter, UINT MsgFilterMin, UINT MsgFilterMax,
+ PLARGE_INTEGER FirstTimerExpiry)
+{
+ PTIMER_ENTRY Timer;
+ PLIST_ENTRY EnumEntry;
+
+ DPRINT("MsqGetFirstTimerExpiry queue %p wndfilter %x msgfiltermin %d msgfiltermax %d expiry %p\n",
+ MessageQueue, WndFilter, MsgFilterMin, MsgFilterMax, FirstTimerExpiry);
+
+ IntLockMessageQueue(MessageQueue);
+ EnumEntry = MessageQueue->TimerListHead.Flink;
+ while (EnumEntry != &MessageQueue->TimerListHead)
+ {
+ Timer = CONTAINING_RECORD(MessageQueue->TimerListHead.Flink,
+ TIMER_ENTRY, ListEntry);
+ EnumEntry = EnumEntry->Flink;
+ if ((NULL == WndFilter || Timer->Wnd == WndFilter) &&
+ ((MsgFilterMin == 0 && MsgFilterMax == 0) ||
+ (MsgFilterMin <= Timer->Msg &&
+ Timer->Msg <= MsgFilterMax)))
+ {
+ *FirstTimerExpiry = Timer->ExpiryTime;
+ DPRINT("First timer expires %I64d\n", Timer->ExpiryTime);
+ IntUnLockMessageQueue(MessageQueue);
+ return TRUE;
+ }
+ }
+
+ IntUnLockMessageQueue(MessageQueue);
+
+ return FALSE;
+}
+
/* EOF */
reactos/subsys/win32k/ntuser
diff -u -r1.37 -r1.38
--- timer.c 25 Dec 2004 22:59:10 -0000 1.37
+++ timer.c 29 Dec 2004 19:55:01 -0000 1.38
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: timer.c,v 1.37 2004/12/25 22:59:10 navaraf Exp $
+/* $Id: timer.c,v 1.38 2004/12/29 19:55:01 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -32,446 +32,165 @@
#include <w32k.h>
-#define NDEBUG
+#undef NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
-//windows 2000 has room for 32768 window-less timers
+/* Windows 2000 has room for 32768 window-less timers */
#define NUM_WINDOW_LESS_TIMERS 1024
static FAST_MUTEX Mutex;
-static LIST_ENTRY TimerListHead;
-static KTIMER Timer;
static RTL_BITMAP WindowLessTimersBitMap;
static PVOID WindowLessTimersBitMapBuffer;
static ULONG HintIndex = 0;
-static HANDLE MsgTimerThreadHandle;
-static CLIENT_ID MsgTimerThreadId;
-#define IntLockTimerList() \
+#define IntLockWindowlessTimerBitmap() \
ExAcquireFastMutex(&Mutex)
-#define IntUnLockTimerList() \
+#define IntUnlockWindowlessTimerBitmap() \
ExReleaseFastMutex(&Mutex)
/* FUNCTIONS *****************************************************************/
-//return true if the new timer became the first entry
-//must hold mutex while calling this
-BOOL FASTCALL
-IntInsertTimerAscendingOrder(PMSG_TIMER_ENTRY NewTimer)
-{
- PLIST_ENTRY current;
-
- current = TimerListHead.Flink;
- while (current != &TimerListHead)
- {
- if (CONTAINING_RECORD(current, MSG_TIMER_ENTRY, ListEntry)->Timeout.QuadPart >=\
- NewTimer->Timeout.QuadPart)
- {
- break;
- }
- current = current->Flink;
- }
-
- InsertTailList(current, &NewTimer->ListEntry);
-
- return TimerListHead.Flink == &NewTimer->ListEntry;
-}
-
-
-//must hold mutex while calling this
-PMSG_TIMER_ENTRY FASTCALL
-IntRemoveTimer(HWND hWnd, UINT_PTR IDEvent, HANDLE ThreadID, BOOL SysTimer)
+UINT_PTR FASTCALL
+IntSetTimer(HWND Wnd, UINT_PTR IDEvent, UINT Elapse, TIMERPROC TimerFunc, BOOL SystemTimer)
{
- PMSG_TIMER_ENTRY MsgTimer;
- PLIST_ENTRY EnumEntry;
-
- //remove timer if already in the queue
- EnumEntry = TimerListHead.Flink;
- while (EnumEntry != &TimerListHead)
- {
- MsgTimer = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry);
- EnumEntry = EnumEntry->Flink;
-
- if (MsgTimer->Msg.hwnd == hWnd &&
- MsgTimer->Msg.wParam == (WPARAM)IDEvent &&
- MsgTimer->ThreadID == ThreadID &&
- (MsgTimer->Msg.message == WM_SYSTIMER) == SysTimer)
- {
- RemoveEntryList(&MsgTimer->ListEntry);
- return MsgTimer;
- }
- }
-
- return NULL;
-}
-
+ PWINDOW_OBJECT WindowObject;
+ UINT_PTR Ret = 0;
-/*
- * NOTE: It doesn't kill the timer. It just removes them from the list.
- */
-VOID FASTCALL
-RemoveTimersThread(HANDLE ThreadID)
-{
- PMSG_TIMER_ENTRY MsgTimer;
- PLIST_ENTRY EnumEntry;
-
- IntLockTimerList();
+ DPRINT("IntSetTimer wnd %x id %p elapse %u timerproc %p systemtimer %s\n",
+ Wnd, IDEvent, Elapse, TimerFunc, SystemTimer ? "TRUE" : "FALSE");
- EnumEntry = TimerListHead.Flink;
- while (EnumEntry != &TimerListHead)
- {
- MsgTimer = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry);
- EnumEntry = EnumEntry->Flink;
-
- if (MsgTimer->ThreadID == ThreadID)
+ if ((Wnd == NULL) && ! SystemTimer)
{
- if (MsgTimer->Msg.hwnd == NULL)
- {
- RtlClearBits(&WindowLessTimersBitMap, ((UINT_PTR)MsgTimer->Msg.wParam) - 1, 1);
- }
-
- RemoveEntryList(&MsgTimer->ListEntry);
- ExFreePool(MsgTimer);
- }
- }
-
- IntUnLockTimerList();
-}
-
-
-/*
- * NOTE: It doesn't kill the timer. It just removes them from the list.
- */
-VOID FASTCALL
-RemoveTimersWindow(HWND Wnd)
-{
- PMSG_TIMER_ENTRY MsgTimer;
- PLIST_ENTRY EnumEntry;
-
- IntLockTimerList();
-
- EnumEntry = TimerListHead.Flink;
- while (EnumEntry != &TimerListHead)
- {
- MsgTimer = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry);
- EnumEntry = EnumEntry->Flink;
+ DPRINT("Window-less timer\n");
+ /* find a free, window-less timer id */
+ IntLockWindowlessTimerBitmap();
+ IDEvent = RtlFindClearBitsAndSet(&WindowLessTimersBitMap, 1, HintIndex);
- if (MsgTimer->Msg.hwnd == Wnd)
- {
- RemoveEntryList(&MsgTimer->ListEntry);
- ExFreePool(MsgTimer);
- }
- }
-
- IntUnLockTimerList();
-}
-
-
-UINT_PTR FASTCALL
-IntSetTimer(HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc, BOOL SystemTimer)
-{
- PMSG_TIMER_ENTRY MsgTimer = NULL;
- PMSG_TIMER_ENTRY NewTimer;
- LARGE_INTEGER CurrentTime;
- PWINDOW_OBJECT WindowObject;
- HANDLE ThreadID;
- UINT_PTR Ret = 0;
-
- ThreadID = PsGetCurrentThreadId();
- KeQuerySystemTime(&CurrentTime);
- IntLockTimerList();
-
- if((hWnd == NULL) && !SystemTimer)
- {
- /* find a free, window-less timer id */
- nIDEvent = 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;
+ }
- if(nIDEvent == (UINT_PTR) -1)
- {
- IntUnLockTimerList();
- return 0;
+ HintIndex = ++IDEvent;
+ IntUnlockWindowlessTimerBitmap();
+ Ret = IDEvent;
}
-
- HintIndex = ++nIDEvent;
- }
else
- {
- WindowObject = IntGetWindowObject(hWnd);
- if(!WindowObject)
{
- IntUnLockTimerList();
- SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
- return 0;
- }
+ WindowObject = IntGetWindowObject(Wnd);
+ if (! WindowObject)
+ {
+ DPRINT1("Invalid window handle\n");
+ SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
+ return 0;
+ }
- if(WindowObject->OwnerThread != PsGetCurrentThread())
- {
- IntUnLockTimerList();
+ if (WindowObject->OwnerThread != PsGetCurrentThread())
+ {
+ IntReleaseWindowObject(WindowObject);
+ DPRINT1("Trying to set timer for window in another thread (shatter attack?)\n");
+ SetLastWin32Error(ERROR_ACCESS_DENIED);
+ return 0;
+ }
IntReleaseWindowObject(WindowObject);
- SetLastWin32Error(ERROR_ACCESS_DENIED);
- return 0;
+ Ret = 1;
}
- IntReleaseWindowObject(WindowObject);
-
- /* remove timer if already in the queue */
- MsgTimer = IntRemoveTimer(hWnd, nIDEvent, ThreadID, SystemTimer);
- }
#if 1
/* Win NT/2k/XP */
- if(uElapse > 0x7fffffff)
- uElapse = 1;
+ if (Elapse > 0x7fffffff)
+ {
+ DPRINT("Adjusting uElapse\n");
+ Elapse = 1;
+ }
#else
/* Win Server 2003 */
- if(uElapse > 0x7fffffff)
- uElapse = 0x7fffffff;
+ if (Elapse > 0x7fffffff)
+ {
+ DPRINT("Adjusting uElapse\n");
+ Elapse = 0x7fffffff;
+ }
#endif
/* Win 2k/XP */
- if(uElapse < 10)
- uElapse = 10;
-
- if(MsgTimer)
- {
- /* modify existing (removed) timer */
- NewTimer = MsgTimer;
-
- NewTimer->Period = uElapse;
- NewTimer->Timeout.QuadPart = CurrentTime.QuadPart + (uElapse * 10000);
- NewTimer->Msg.lParam = (LPARAM)lpTimerFunc;
- }
- else
- {
- /* FIXME: use lookaside? */
- NewTimer = ExAllocatePoolWithTag(PagedPool, sizeof(MSG_TIMER_ENTRY), TAG_TIMER);
- if(!NewTimer)
+ if (Elapse < 10)
+ {
+ DPRINT("Adjusting uElapse\n");
+ Elapse = 10;
+ }
+
+ if (! MsqSetTimer(PsGetWin32Thread()->MessageQueue, Wnd,
+ IDEvent, Elapse, TimerFunc,
+ SystemTimer ? WM_SYSTIMER : WM_TIMER))
{
- IntUnLockTimerList();
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ DPRINT1("Failed to set timer in message queue\n");
+ SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
return 0;
}
-
- NewTimer->Msg.hwnd = hWnd;
- NewTimer->Msg.message = (SystemTimer ? WM_SYSTIMER : WM_TIMER);
- NewTimer->Msg.wParam = (WPARAM)nIDEvent;
- NewTimer->Msg.lParam = (LPARAM)lpTimerFunc;
- NewTimer->Period = uElapse;
- NewTimer->Timeout.QuadPart = CurrentTime.QuadPart + (uElapse * 10000);
- NewTimer->ThreadID = ThreadID;
- }
-
- Ret = nIDEvent; // FIXME - return lpTimerProc if it's not a system timer
-
- if(IntInsertTimerAscendingOrder(NewTimer))
- {
- /* new timer is first in queue and expires first */
- KeSetTimer(&Timer, NewTimer->Timeout, NULL);
- }
- IntUnLockTimerList();
return Ret;
}
BOOL FASTCALL
-IntKillTimer(HWND hWnd, UINT_PTR uIDEvent, BOOL SystemTimer)
+IntKillTimer(HWND Wnd, UINT_PTR IDEvent, BOOL SystemTimer)
{
- PMSG_TIMER_ENTRY MsgTimer;
- PWINDOW_OBJECT WindowObject;
-
- IntLockTimerList();
-
- /* window-less timer? */
- if((hWnd == NULL) && !SystemTimer)
- {
- if(!RtlAreBitsSet(&WindowLessTimersBitMap, uIDEvent - 1, 1))
- {
- IntUnLockTimerList();
- /* bit was not set */
- /* FIXME: set the last error */
- return FALSE;
- }
- RtlClearBits(&WindowLessTimersBitMap, uIDEvent - 1, 1);
- }
- else
- {
- WindowObject = IntGetWindowObject(hWnd);
- if(!WindowObject)
- {
- IntUnLockTimerList();
- SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
- return FALSE;
- }
- if(WindowObject->OwnerThread != PsGetCurrentThread())
+ DPRINT("IntKillTimer wnd %x id %p systemtimer %s\n",
+ Wnd, IDEvent, SystemTimer ? "TRUE" : "FALSE");
+
+ if (! MsqKillTimer(PsGetWin32Thread()->MessageQueue, Wnd,
+ IDEvent, SystemTimer ? WM_SYSTIMER : WM_TIMER))
{
- IntUnLockTimerList();
- IntReleaseWindowObject(WindowObject);
- SetLastWin32Error(ERROR_ACCESS_DENIED);
+ DPRINT1("Unable to locate timer in message queue\n");
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
- IntReleaseWindowObject(WindowObject);
- }
- MsgTimer = IntRemoveTimer(hWnd, uIDEvent, PsGetCurrentThreadId(), SystemTimer);
-
- IntUnLockTimerList();
-
- if(MsgTimer == NULL)
- {
- /* didn't find timer */
- /* FIXME: set the last error */
- return FALSE;
- }
-
- /* FIXME: use lookaside? */
- ExFreePool(MsgTimer);
-
- return TRUE;
-}
-
-static VOID STDCALL
-TimerThreadMain(PVOID StartContext)
-{
- NTSTATUS Status;
- LARGE_INTEGER CurrentTime;
- PLIST_ENTRY EnumEntry;
- PMSG_TIMER_ENTRY MsgTimer;
- PETHREAD Thread;
- PETHREAD *ThreadsToDereference;
- ULONG ThreadsToDereferenceCount, ThreadsToDereferencePos, i;
-
- for(;;)
- {
- Status = KeWaitForSingleObject(&Timer,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Error waiting in TimerThreadMain\n");
- KEBUGCHECK(0);
- }
-
- ThreadsToDereferenceCount = ThreadsToDereferencePos = 0;
-
- IntLockTimerList();
-
- KeQuerySystemTime(&CurrentTime);
-
- for (EnumEntry = TimerListHead.Flink;
- EnumEntry != &TimerListHead;
- EnumEntry = EnumEntry->Flink)
+ /* window-less timer? */
+ if ((Wnd == NULL) && ! SystemTimer)
{
- MsgTimer = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry);
- if (CurrentTime.QuadPart >= MsgTimer->Timeout.QuadPart)
- ++ThreadsToDereferenceCount;
- else
- break;
- }
-
-
- ThreadsToDereference = (PETHREAD *)ExAllocatePoolWithTag(
- NonPagedPool, ThreadsToDereferenceCount * sizeof(PETHREAD), TAG_TIMERTD);
+ /* Release the id */
+ IntLockWindowlessTimerBitmap();
- EnumEntry = TimerListHead.Flink;
- while (EnumEntry != &TimerListHead)
- {
- MsgTimer = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry);
-
- if (CurrentTime.QuadPart >= MsgTimer->Timeout.QuadPart)
- {
- EnumEntry = EnumEntry->Flink;
-
- RemoveEntryList(&MsgTimer->ListEntry);
-
- /*
- * FIXME: 1) Find a faster way of getting the thread message queue? (lookup by id is slow)
- */
-
- if (!NT_SUCCESS(PsLookupThreadByThreadId(MsgTimer->ThreadID, &Thread)))
- {
- ExFreePool(MsgTimer);
- continue;
- }
-
- MsqPostMessage(Thread->Tcb.Win32Thread->MessageQueue, &MsgTimer->Msg,
- FALSE, QS_TIMER);
-
- ThreadsToDereference[ThreadsToDereferencePos] = Thread;
- ++ThreadsToDereferencePos;
-
- //set up next periodic timeout
- //FIXME: is this calculation really necesary (and correct)? -Gunnar
- do
- {
- MsgTimer->Timeout.QuadPart += (MsgTimer->Period * 10000);
- }
- while (MsgTimer->Timeout.QuadPart <= CurrentTime.QuadPart);
- IntInsertTimerAscendingOrder(MsgTimer);
- }
- else
- {
- break;
- }
+ ASSERT(RtlAreBitsSet(&WindowLessTimersBitMap, IDEvent - 1, 1));
+ RtlClearBits(&WindowLessTimersBitMap, IDEvent - 1, 1);
+ IntUnlockWindowlessTimerBitmap();
}
-
-
- //set up next timeout from first entry (if any)
- if (!IsListEmpty(&TimerListHead))
- {
- MsgTimer = CONTAINING_RECORD( TimerListHead.Flink, MSG_TIMER_ENTRY, ListEntry);
- KeSetTimer(&Timer, MsgTimer->Timeout, NULL);
- }
-
- IntUnLockTimerList();
-
- for (i = 0; i < ThreadsToDereferencePos; i++)
- ObDereferenceObject(ThreadsToDereference[i]);
-
- ExFreePool(ThreadsToDereference);
- }
+
+ return TRUE;
}
NTSTATUS FASTCALL
InitTimerImpl(VOID)
{
- NTSTATUS Status;
ULONG BitmapBytes;
- BitmapBytes = ROUND_UP(NUM_WINDOW_LESS_TIMERS, sizeof(ULONG) * 8) / 8;
-
- InitializeListHead(&TimerListHead);
- KeInitializeTimerEx(&Timer, SynchronizationTimer);
ExInitializeFastMutex(&Mutex);
+ BitmapBytes = ROUND_UP(NUM_WINDOW_LESS_TIMERS, sizeof(ULONG) * 8) / 8;
WindowLessTimersBitMapBuffer = ExAllocatePoolWithTag(PagedPool, BitmapBytes, TAG_TIMERBMP);
RtlInitializeBitMap(&WindowLessTimersBitMap,
WindowLessTimersBitMapBuffer,
BitmapBytes * 8);
- //yes we need this, since ExAllocatePool isn't supposed to zero out allocated memory
+ /* yes we need this, since ExAllocatePool isn't supposed to zero out allocated memory */
RtlClearAllBits(&WindowLessTimersBitMap);
-
- Status = PsCreateSystemThread(&MsgTimerThreadHandle,
- THREAD_ALL_ACCESS,
- NULL,
- NULL,
- &MsgTimerThreadId,
- TimerThreadMain,
- NULL);
- return Status;
+
+ return STATUS_SUCCESS;
}
reactos/subsys/win32k/ntuser
diff -u -r1.258 -r1.259
--- window.c 25 Dec 2004 20:30:50 -0000 1.258
+++ window.c 29 Dec 2004 19:55:01 -0000 1.259
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: window.c,v 1.258 2004/12/25 20:30:50 navaraf Exp $
+/* $Id: window.c,v 1.259 2004/12/29 19:55:01 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -268,7 +268,7 @@
ASSERT(Window);
- RemoveTimersWindow(Window->Self);
+ MsqRemoveTimersWindow(ThreadData->MessageQueue, Window->Self);
IntLockThreadWindows(Window->OwnerThread->Tcb.Win32Thread);
if(Window->Status & WINDOWSTATUS_DESTROYING)
CVSspam 0.2.8