From 93e9630e676386b1c340946848d5b9b665f939ec Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Sat, 4 Oct 2003 22:36:37 +0000 Subject: [PATCH] implements system timers (similar to standard timers) svn path=/trunk/; revision=6240 --- reactos/iface/addsys/w32ksvc.db | 1 + reactos/include/funcs.h | 16 +- reactos/include/messages.h | 1 + reactos/include/win32k/ntuser.h | 26 +- reactos/lib/user32/controls/listbox.c | 8 +- reactos/lib/user32/misc/stubs.c | 29 +- reactos/lib/user32/misc/timer.c | 35 +- reactos/subsys/win32k/ntuser/timer.c | 468 ++++++++++++++++++--- reactos/subsys/win32k/objects/cursoricon.c | 2 +- 9 files changed, 465 insertions(+), 121 deletions(-) diff --git a/reactos/iface/addsys/w32ksvc.db b/reactos/iface/addsys/w32ksvc.db index e5f93e945bd..4764fee79c1 100644 --- a/reactos/iface/addsys/w32ksvc.db +++ b/reactos/iface/addsys/w32ksvc.db @@ -428,6 +428,7 @@ NtUserInternalGetWindowText 3 NtUserInvalidateRect 3 NtUserInvalidateRgn 3 NtUserIsClipboardFormatAvailable 1 +NtUserKillSystemTimer 2 NtUserKillTimer 2 NtUserLoadKeyboardLayoutEx 6 NtUserLockWindowStation 1 diff --git a/reactos/include/funcs.h b/reactos/include/funcs.h index 66c7d84dd1b..efd46f3488f 100644 --- a/reactos/include/funcs.h +++ b/reactos/include/funcs.h @@ -4713,11 +4713,11 @@ SetWindowStationUser( UINT STDCALL SetSystemTimer( - HWND hwnd, - UINT id, - UINT timeout, - TIMERPROC proc - ); + HWND hWnd, + UINT_PTR IDEvent, + UINT Period, + TIMERPROC TimerFunc + ); WINBOOL STDCALL @@ -4777,9 +4777,9 @@ RegisterLogonProcess( WINBOOL STDCALL KillSystemTimer( - HWND hwnd, - UINT id - ); + HWND hWnd, + UINT_PTR IDEvent + ); DWORD STDCALL diff --git a/reactos/include/messages.h b/reactos/include/messages.h index 44338e282ed..8283924fb20 100644 --- a/reactos/include/messages.h +++ b/reactos/include/messages.h @@ -1105,6 +1105,7 @@ extern "C" { #define WM_TCARD (82) #define WM_TIMECHANGE (30) #define WM_TIMER (275) +#define WM_SYSTIMER (280) #define WM_UNDO (772) #define WM_USER (1024) #define WM_USERCHANGED (84) diff --git a/reactos/include/win32k/ntuser.h b/reactos/include/win32k/ntuser.h index db17cdd2caa..f1ffbadf7cd 100644 --- a/reactos/include/win32k/ntuser.h +++ b/reactos/include/win32k/ntuser.h @@ -959,6 +959,14 @@ STDCALL NtUserIsClipboardFormatAvailable( DWORD Unknown0); +BOOL +STDCALL +NtUserKillSystemTimer +( + HWND hWnd, + UINT_PTR uIDEvent +); + BOOL STDCALL NtUserKillTimer @@ -1485,14 +1493,6 @@ NtUserSetSystemMenu( HWND hWnd, HMENU hMenu); -DWORD -STDCALL -NtUserSetSystemTimer( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3); - BOOL STDCALL NtUserSetThreadDesktop( @@ -1504,6 +1504,16 @@ NtUserSetThreadState( DWORD Unknown0, DWORD Unknown1); +UINT_PTR +STDCALL +NtUserSetSystemTimer +( + HWND hWnd, + UINT_PTR nIDEvent, + UINT uElapse, + TIMERPROC lpTimerFunc +); + UINT_PTR STDCALL NtUserSetTimer diff --git a/reactos/lib/user32/controls/listbox.c b/reactos/lib/user32/controls/listbox.c index d754545b339..fe6d03038b0 100644 --- a/reactos/lib/user32/controls/listbox.c +++ b/reactos/lib/user32/controls/listbox.c @@ -1,4 +1,4 @@ -/* $Id: listbox.c,v 1.11 2003/09/27 00:29:52 weiden Exp $ +/* $Id: listbox.c,v 1.12 2003/10/04 22:36:36 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS User32 @@ -74,12 +74,6 @@ BOOL is_old_app(HWND hwnd) #define WM_LBTRACKPOINT 0x0131 #define WS_EX_DRAGDETECT 0x00000002L #define WM_BEGINDRAG 0x022C -//#define WM_MOUSEWHEEL 0x020A -//#define WHEEL_DELTA 120 - -#define WM_SYSTIMER WM_TIMER -#define SetSystemTimer SetTimer -#define KillSystemTimer KillTimer /* End of hack section -------------------------------- */ diff --git a/reactos/lib/user32/misc/stubs.c b/reactos/lib/user32/misc/stubs.c index bee2878a110..0336e86af52 100644 --- a/reactos/lib/user32/misc/stubs.c +++ b/reactos/lib/user32/misc/stubs.c @@ -1,4 +1,4 @@ -/* $Id: stubs.c,v 1.43 2003/09/12 17:51:48 vizzini Exp $ +/* $Id: stubs.c,v 1.44 2003/10/04 22:36:36 weiden Exp $ * * COPYRIGHT: See COPYING WINBOOLthe top level directory * PROJECT: ReactOS user32.dll @@ -869,22 +869,6 @@ SetWindowStationUser ( DWORD x1, DWORD x2 ) return FALSE; } -/* - * @unimplemented - */ -UINT -STDCALL -SetSystemTimer( - HWND hwnd, - UINT id, - UINT timeout, - TIMERPROC proc - ) -{ - UNIMPLEMENTED; - return FALSE; -} - /* * @unimplemented */ @@ -978,17 +962,6 @@ RegisterLogonProcess ( HANDLE hprocess, BOOL x ) return FALSE; } -/* - * @unimplemented - */ -WINBOOL -STDCALL -KillSystemTimer ( HWND hwnd, UINT id ) -{ - UNIMPLEMENTED; - return FALSE; -} - /* * @unimplemented */ diff --git a/reactos/lib/user32/misc/timer.c b/reactos/lib/user32/misc/timer.c index aa8afa1ee3c..d00b3225847 100644 --- a/reactos/lib/user32/misc/timer.c +++ b/reactos/lib/user32/misc/timer.c @@ -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.8 2003/07/10 21:04:31 chorns Exp $ +/* $Id: timer.c,v 1.9 2003/10/04 22:36:36 weiden Exp $ * * PROJECT: ReactOS user32.dll * FILE: lib/user32/misc/dde.c @@ -35,6 +35,20 @@ /* FUNCTIONS *****************************************************************/ + +/* + * @implemented + */ +WINBOOL +STDCALL +KillSystemTimer( + HWND hWnd, + UINT_PTR IDEvent) +{ + return NtUserKillSystemTimer(hWnd, IDEvent); +} + + /* * @implemented */ @@ -44,7 +58,22 @@ KillTimer( HWND hWnd, UINT_PTR IDEvent) { - return NtUserKillTimer(hWnd, IDEvent); + return NtUserKillTimer(hWnd, IDEvent); +} + + +/* + * @implemented + */ +UINT_PTR +STDCALL +SetSystemTimer( + HWND hWnd, + UINT_PTR IDEvent, + UINT Period, + TIMERPROC TimerFunc) +{ + return NtUserSetSystemTimer(hWnd, IDEvent, Period, TimerFunc); } @@ -59,6 +88,6 @@ SetTimer( UINT Period, TIMERPROC TimerFunc) { - return NtUserSetTimer(hWnd, IDEvent, Period, TimerFunc); + return NtUserSetTimer(hWnd, IDEvent, Period, TimerFunc); } diff --git a/reactos/subsys/win32k/ntuser/timer.c b/reactos/subsys/win32k/ntuser/timer.c index c900ca3c772..73075bd0b28 100644 --- a/reactos/subsys/win32k/ntuser/timer.c +++ b/reactos/subsys/win32k/ntuser/timer.c @@ -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.10 2003/08/13 20:24:05 chorns Exp $ +/* $Id: timer.c,v 1.11 2003/10/04 22:36:37 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include @@ -48,6 +50,7 @@ static FAST_MUTEX Mutex; static LIST_ENTRY TimerListHead; +static LIST_ENTRY SysTimerListHead; static KTIMER Timer; static RTL_BITMAP HandleLessTimersBitMap; static PVOID HandleLessTimersBitMapBuffer; @@ -72,32 +75,56 @@ typedef struct _MSG_TIMER_ENTRY{ //must hold mutex while calling this BOOL FASTCALL -InsertTimerAscendingOrder(PMSG_TIMER_ENTRY NewTimer) +InsertTimerAscendingOrder(PMSG_TIMER_ENTRY NewTimer, BOOL SysTimer) { PLIST_ENTRY EnumEntry, InsertAfter; PMSG_TIMER_ENTRY MsgTimer; InsertAfter = NULL; - EnumEntry = TimerListHead.Flink; - while (EnumEntry != &TimerListHead) + if(!SysTimer) { - MsgTimer = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry); - if (NewTimer->Timeout.QuadPart > MsgTimer->Timeout.QuadPart) - { - InsertAfter = EnumEntry; - } - EnumEntry = EnumEntry->Flink; + EnumEntry = TimerListHead.Flink; + while (EnumEntry != &TimerListHead) + { + MsgTimer = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry); + if (NewTimer->Timeout.QuadPart > MsgTimer->Timeout.QuadPart) + { + InsertAfter = EnumEntry; + } + EnumEntry = EnumEntry->Flink; + } + + if (InsertAfter) + { + InsertTailList(InsertAfter, &NewTimer->ListEntry); + return FALSE; + } + //insert as first entry + InsertHeadList(&TimerListHead, &NewTimer->ListEntry); + } + else + { + EnumEntry = SysTimerListHead.Flink; + while (EnumEntry != &SysTimerListHead) + { + MsgTimer = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry); + if (NewTimer->Timeout.QuadPart > MsgTimer->Timeout.QuadPart) + { + InsertAfter = EnumEntry; + } + EnumEntry = EnumEntry->Flink; + } + + if (InsertAfter) + { + InsertTailList(InsertAfter, &NewTimer->ListEntry); + return FALSE; + } + //insert as first entry + InsertHeadList(&SysTimerListHead, &NewTimer->ListEntry); } - if (InsertAfter) - { - InsertTailList(InsertAfter, &NewTimer->ListEntry); - return FALSE; - } - - //insert as first entry - InsertHeadList(&TimerListHead, &NewTimer->ListEntry); return TRUE; } @@ -105,25 +132,46 @@ InsertTimerAscendingOrder(PMSG_TIMER_ENTRY NewTimer) //must hold mutex while calling this PMSG_TIMER_ENTRY FASTCALL -RemoveTimer(HWND hWnd, UINT_PTR IDEvent, HANDLE ThreadID) +RemoveTimer(HWND hWnd, UINT_PTR IDEvent, HANDLE ThreadID, BOOL SysTimer) { PMSG_TIMER_ENTRY MsgTimer; PLIST_ENTRY EnumEntry; - //remove timer if allready in the queue - EnumEntry = TimerListHead.Flink; - while (EnumEntry != &TimerListHead) + if(!SysTimer) { - MsgTimer = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry); - EnumEntry = EnumEntry->Flink; - - if (MsgTimer->Msg.hwnd == hWnd && - MsgTimer->Msg.wParam == (WPARAM)IDEvent && - MsgTimer->ThreadID == ThreadID) - { - RemoveEntryList(&MsgTimer->ListEntry); - return MsgTimer; - } + //remove timer if allready 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) + { + RemoveEntryList(&MsgTimer->ListEntry); + return MsgTimer; + } + } + } + else + { + //remove timer if allready in the queue + EnumEntry = SysTimerListHead.Flink; + while (EnumEntry != &SysTimerListHead) + { + MsgTimer = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry); + EnumEntry = EnumEntry->Flink; + + if (MsgTimer->Msg.hwnd == hWnd && + MsgTimer->Msg.wParam == (WPARAM)IDEvent && + MsgTimer->ThreadID == ThreadID) + { + RemoveEntryList(&MsgTimer->ListEntry); + return MsgTimer; + } + } } return NULL; @@ -142,6 +190,19 @@ RemoveTimersThread(HANDLE ThreadID) ExAcquireFastMutex(&Mutex); + EnumEntry = SysTimerListHead.Flink; + while (EnumEntry != &SysTimerListHead) + { + MsgTimer = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry); + EnumEntry = EnumEntry->Flink; + + if (MsgTimer->ThreadID == ThreadID) + { + RemoveEntryList(&MsgTimer->ListEntry); + ExFreePool(MsgTimer); + } + } + EnumEntry = TimerListHead.Flink; while (EnumEntry != &TimerListHead) { @@ -177,19 +238,13 @@ NtUserSetTimer ) { ULONG Index; - PMSG_TIMER_ENTRY MsgTimer = NULL; + PMSG_TIMER_ENTRY MsgTimer2, MsgTimer = NULL; PMSG_TIMER_ENTRY NewTimer; + PLIST_ENTRY EnumEntry; LARGE_INTEGER CurrentTime; + PWINDOW_OBJECT WindowObject; HANDLE ThreadID; - //FIXME: WINE: window must be owned by the calling thread -#if 0 - if(hWnd && !(hWnd = WIN_IsCurrentThread(hWnd)) - { - return STATUS_UNSUCCESSFUL; - } -#endif - ThreadID = PsGetCurrentThreadId(); KeQuerySystemTime(&CurrentTime); ExAcquireFastMutex(&Mutex); @@ -201,7 +256,6 @@ NtUserSetTimer if(Index == (ULONG) -1) { - /* FIXME: set the last error */ ExReleaseFastMutex(&Mutex); return 0; } @@ -213,9 +267,44 @@ NtUserSetTimer } else { + WindowObject = IntGetWindowObject(hWnd); + if(!WindowObject) + { + ExReleaseFastMutex(&Mutex); + SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE); + return 0; + } + + if(WindowObject->OwnerThread != PsGetCurrentThread()) + { + IntReleaseWindowObject(WindowObject); + ExReleaseFastMutex(&Mutex); + SetLastWin32Error(ERROR_ACCESS_DENIED); + return 0; + } + IntReleaseWindowObject(WindowObject); + /* remove timer if already in the queue */ - MsgTimer = RemoveTimer(hWnd, nIDEvent, ThreadID); + MsgTimer = RemoveTimer(hWnd, nIDEvent, ThreadID, FALSE); } + + #if 1 + + /* Win NT/2k/XP */ + if(uElapse > 0x7fffffff) + uElapse = 1; + + #else + + /* Win Server 2003 */ + if(uElapse > 0x7fffffff) + uElapse = 0x7fffffff; + + #endif + + /* Win 2k/XP */ + if(uElapse < 10) + uElapse = 10; if(MsgTimer) { @@ -230,6 +319,12 @@ NtUserSetTimer { /* FIXME: use lookaside? */ NewTimer = ExAllocatePool(PagedPool, sizeof(MSG_TIMER_ENTRY)); + if(!NewTimer) + { + ExReleaseFastMutex(&Mutex); + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } NewTimer->Msg.hwnd = hWnd; NewTimer->Msg.message = WM_TIMER; @@ -240,10 +335,23 @@ NtUserSetTimer NewTimer->ThreadID = ThreadID; } - if(InsertTimerAscendingOrder(NewTimer)) + if(InsertTimerAscendingOrder(NewTimer, FALSE)) { - /* new timer is first in queue and expires first */ - KeSetTimer(&Timer, NewTimer->Timeout, NULL); + EnumEntry = SysTimerListHead.Flink; + if(EnumEntry != &SysTimerListHead) + { + MsgTimer2 = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry); + if (NewTimer->Timeout.QuadPart <= MsgTimer2->Timeout.QuadPart) + { + /* new timer is first in queue and expires first */ + KeSetTimer(&Timer, NewTimer->Timeout, NULL); + } + } + else + { + /* new timer is first in queue and expires first */ + KeSetTimer(&Timer, NewTimer->Timeout, NULL); + } } ExReleaseFastMutex(&Mutex); @@ -261,6 +369,7 @@ NtUserKillTimer ) { PMSG_TIMER_ENTRY MsgTimer; + PWINDOW_OBJECT WindowObject; ExAcquireFastMutex(&Mutex); @@ -277,8 +386,193 @@ NtUserKillTimer RtlClearBits(&HandleLessTimersBitMap, uIDEvent - 1, 1); } + else + { + WindowObject = IntGetWindowObject(hWnd); + if(!WindowObject) + { + ExReleaseFastMutex(&Mutex); + SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE); + return FALSE; + } + if(WindowObject->OwnerThread != PsGetCurrentThread()) + { + IntReleaseWindowObject(WindowObject); + ExReleaseFastMutex(&Mutex); + SetLastWin32Error(ERROR_ACCESS_DENIED); + return FALSE; + } + IntReleaseWindowObject(WindowObject); + } - MsgTimer = RemoveTimer(hWnd, uIDEvent, PsGetCurrentThreadId()); + MsgTimer = RemoveTimer(hWnd, uIDEvent, PsGetCurrentThreadId(), FALSE); + + ExReleaseFastMutex(&Mutex); + + if(MsgTimer == NULL) + { + /* didn't find timer */ + /* FIXME: set the last error */ + return FALSE; + } + + /* FIXME: use lookaside? */ + ExFreePool(MsgTimer); + + return TRUE; +} + +UINT_PTR +STDCALL +NtUserSetSystemTimer( + HWND hWnd, + UINT_PTR nIDEvent, + UINT uElapse, + TIMERPROC lpTimerFunc +) +{ + /* As opposed to SetTimer() this one seems not to allow window-less timers! */ + PMSG_TIMER_ENTRY MsgTimer2, MsgTimer = NULL; + PMSG_TIMER_ENTRY NewTimer; + PLIST_ENTRY EnumEntry; + LARGE_INTEGER CurrentTime; + PWINDOW_OBJECT WindowObject; + HANDLE ThreadID; + + ThreadID = PsGetCurrentThreadId(); + KeQuerySystemTime(&CurrentTime); + ExAcquireFastMutex(&Mutex); + + if(hWnd == NULL) + { + ExReleaseFastMutex(&Mutex); + SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE); + return 0; + } + else + { + WindowObject = IntGetWindowObject(hWnd); + if(!WindowObject) + { + ExReleaseFastMutex(&Mutex); + SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE); + return 0; + } + + if(WindowObject->OwnerThread != PsGetCurrentThread()) + { + IntReleaseWindowObject(WindowObject); + ExReleaseFastMutex(&Mutex); + SetLastWin32Error(ERROR_ACCESS_DENIED); + return 0; + } + IntReleaseWindowObject(WindowObject); + + /* remove timer if already in the queue */ + MsgTimer = RemoveTimer(hWnd, nIDEvent, ThreadID, TRUE); + } + + #if 1 + + /* Win NT/2k/XP */ + if(uElapse > 0x7fffffff) + uElapse = 1; + + #else + + /* Win Server 2003 */ + if(uElapse > 0x7fffffff) + uElapse = 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 = ExAllocatePool(PagedPool, sizeof(MSG_TIMER_ENTRY)); + if(!NewTimer) + { + ExReleaseFastMutex(&Mutex); + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + NewTimer->Msg.hwnd = hWnd; + NewTimer->Msg.message = WM_SYSTIMER; + NewTimer->Msg.wParam = (WPARAM)nIDEvent; + NewTimer->Msg.lParam = (LPARAM)lpTimerFunc; + NewTimer->Period = uElapse; + NewTimer->Timeout.QuadPart = CurrentTime.QuadPart + (uElapse * 10000); + NewTimer->ThreadID = ThreadID; + } + + if(InsertTimerAscendingOrder(NewTimer, TRUE)) + { + EnumEntry = TimerListHead.Flink; + if(EnumEntry != &TimerListHead) + { + MsgTimer2 = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry); + if (NewTimer->Timeout.QuadPart <= MsgTimer2->Timeout.QuadPart) + { + /* new timer is first in queue and expires first */ + KeSetTimer(&Timer, NewTimer->Timeout, NULL); + } + } + else + { + /* new timer is first in queue and expires first */ + KeSetTimer(&Timer, NewTimer->Timeout, NULL); + } + } + + ExReleaseFastMutex(&Mutex); + + return 1; +} + +BOOL +STDCALL +NtUserKillSystemTimer( + HWND hWnd, + UINT_PTR uIDEvent +) +{ + /* As opposed to KillTimer() this one seems not to allow window-less timers! */ + PMSG_TIMER_ENTRY MsgTimer; + PWINDOW_OBJECT WindowObject; + + WindowObject = IntGetWindowObject(hWnd); + + /* handle-less timer? Not allowed for SystemTimers! */ + if(!WindowObject) + { + SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE); + return FALSE; + } + if(WindowObject->OwnerThread != PsGetCurrentThread()) + { + IntReleaseWindowObject(WindowObject); + SetLastWin32Error(ERROR_ACCESS_DENIED); + return FALSE; + } + IntReleaseWindowObject(WindowObject); + + ExAcquireFastMutex(&Mutex); + + MsgTimer = RemoveTimer(hWnd, uIDEvent, PsGetCurrentThreadId(), TRUE); ExReleaseFastMutex(&Mutex); @@ -295,19 +589,6 @@ NtUserKillTimer return TRUE; } -DWORD -STDCALL -NtUserSetSystemTimer( - DWORD Unknown0, - DWORD Unknown1, - DWORD Unknown2, - DWORD Unknown3) -{ - UNIMPLEMENTED - - return 0; -} - static VOID STDCALL_FUNC TimerThreadMain( @@ -317,7 +598,7 @@ TimerThreadMain( NTSTATUS Status; LARGE_INTEGER CurrentTime; PLIST_ENTRY EnumEntry; - PMSG_TIMER_ENTRY MsgTimer; + PMSG_TIMER_ENTRY MsgTimer, MsgTimer2; PETHREAD Thread; for (;;) @@ -336,8 +617,43 @@ TimerThreadMain( } ExAcquireFastMutex(&Mutex); - + KeQuerySystemTime(&CurrentTime); + + EnumEntry = SysTimerListHead.Flink; + while (EnumEntry != &SysTimerListHead) + { + MsgTimer2 = CONTAINING_RECORD(EnumEntry, MSG_TIMER_ENTRY, ListEntry); + EnumEntry = EnumEntry->Flink; + + if (CurrentTime.QuadPart >= MsgTimer2->Timeout.QuadPart) + { + RemoveEntryList(&MsgTimer2->ListEntry); + + /* + * FIXME: 1) Find a faster way of getting the thread message queue? (lookup by id is slow) + */ + + if (!NT_SUCCESS(PsLookupThreadByThreadId(MsgTimer2->ThreadID, &Thread))) + { + ExFreePool(MsgTimer2); + continue; + } + + MsqPostMessage(((PW32THREAD)Thread->Win32Thread)->MessageQueue, MsqCreateMessage(&MsgTimer2->Msg)); + + ObDereferenceObject(Thread); + + //set up next periodic timeout + MsgTimer2->Timeout.QuadPart += (MsgTimer2->Period * 10000); + InsertTimerAscendingOrder(MsgTimer2, TRUE); + + } + else + { + break; + } + } EnumEntry = TimerListHead.Flink; while (EnumEntry != &TimerListHead) @@ -365,7 +681,7 @@ TimerThreadMain( //set up next periodic timeout MsgTimer->Timeout.QuadPart += (MsgTimer->Period * 10000); - InsertTimerAscendingOrder(MsgTimer); + InsertTimerAscendingOrder(MsgTimer, FALSE); } else @@ -378,12 +694,31 @@ TimerThreadMain( if (!IsListEmpty(&TimerListHead)) { MsgTimer = CONTAINING_RECORD( TimerListHead.Flink, MSG_TIMER_ENTRY, ListEntry); - KeSetTimer(&Timer, MsgTimer->Timeout, NULL); + if(!IsListEmpty(&SysTimerListHead)) + { + MsgTimer2 = CONTAINING_RECORD( SysTimerListHead.Flink, MSG_TIMER_ENTRY, ListEntry); + if(MsgTimer->Timeout.QuadPart >= MsgTimer2->Timeout.QuadPart) + KeSetTimer(&Timer, MsgTimer->Timeout, NULL); + else + KeSetTimer(&Timer, MsgTimer2->Timeout, NULL); + } + else + { + KeSetTimer(&Timer, MsgTimer->Timeout, NULL); + } } else { - /* Reinitialize the timer, this reset the state of the timer event on which we wait */ - KeInitializeTimer(&Timer); + if(!IsListEmpty(&SysTimerListHead)) + { + MsgTimer2 = CONTAINING_RECORD( SysTimerListHead.Flink, MSG_TIMER_ENTRY, ListEntry); + KeSetTimer(&Timer, MsgTimer2->Timeout, NULL); + } + else + { + /* Reinitialize the timer, this reset the state of the timer event on which we wait */ + KeInitializeTimer(&Timer); + } } ExReleaseFastMutex(&Mutex); @@ -403,6 +738,7 @@ InitTimerImpl(VOID) BitmapBytes = ROUND_UP(NUM_HANDLE_LESS_TIMERS, sizeof(ULONG) * 8) / 8; InitializeListHead(&TimerListHead); + InitializeListHead(&SysTimerListHead); KeInitializeTimer(&Timer); ExInitializeFastMutex(&Mutex); diff --git a/reactos/subsys/win32k/objects/cursoricon.c b/reactos/subsys/win32k/objects/cursoricon.c index 7778afff593..5a5d2be8f1d 100644 --- a/reactos/subsys/win32k/objects/cursoricon.c +++ b/reactos/subsys/win32k/objects/cursoricon.c @@ -340,7 +340,7 @@ NtUserGetClipCursor( { DPRINT("Validation of window station handle (0x%X) failed\n", PROCESS_WINDOW_STATION()); - SetLastWin32Error(Status); + SetLastNtError(Status); return FALSE; }