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/in…
==============================================================================
--- 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/in…
==============================================================================
--- 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/in…
==============================================================================
--- 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/nt…
==============================================================================
--- 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/nt…
==============================================================================
--- 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/nt…
==============================================================================
--- 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/nt…
==============================================================================
--- 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();
+}
//
//