- Rewrite Timers, nothing is using it except a bogus system timer for raw input thread is loaded and running.

svn path=/trunk/; revision=38779
This commit is contained in:
James Tabor 2009-01-15 23:15:31 +00:00
parent a3c29b9686
commit a0d07a719b
7 changed files with 309 additions and 13 deletions

View file

@ -37,4 +37,6 @@ PKBL UserHklToKbl(HKL hKl);
#define ThreadHasInputAccess(W32Thread) \
(TRUE)
extern PTHREADINFO ptiRawInput;
#endif /* _WIN32K_INPUT_H */

View file

@ -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 */

View file

@ -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 @@ typedef struct _TIMER
#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 */

View file

@ -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 CLIENT_ID MouseThreadId;
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 @@ KeyboardThreadMain(PVOID StartContext)
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 @@ KeyboardEscape:
}
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)
{
@ -845,6 +922,18 @@ InitInputImpl(VOID)
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,
THREAD_ALL_ACCESS,
NULL,

View file

@ -360,7 +360,7 @@ IntDispatchMessage(PMSG pMsg)
{
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 @@ CheckMessages:
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);

View file

@ -1117,7 +1117,7 @@ NtUserValidateTimerCallback(
goto Exit;
}
Ret = ValidateTimerCallback(GetW32ThreadInfo(), Window, wParam, lParam);
Ret = ValidateTimerCallback(PsGetCurrentThreadWin32Thread(), Window, wParam, lParam);
Exit:
UserLeave();

View file

@ -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 @@ static ULONG HintIndex = 0;
ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&Mutex)
/* FUNCTIONS *****************************************************************/
static
PTIMER
FASTCALL
CreateTimer(VOID)
@ -144,7 +148,7 @@ FindSystemTimer(PMSG pMsg)
BOOL
FASTCALL
ValidateTimerCallback(PW32THREADINFO pti,
ValidateTimerCallback(PTHREADINFO pti,
PWINDOW_OBJECT Window,
WPARAM wParam,
LPARAM lParam)
@ -158,7 +162,7 @@ ValidateTimerCallback(PW32THREADINFO pti,
{
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 @@ ValidateTimerCallback(PW32THREADINFO pti,
// Rename it to IntSetTimer after move.
UINT_PTR FASTCALL
InternalSetTimer(HWND Wnd, UINT_PTR IDEvent, UINT Elapse, TIMERPROC TimerFunc, BOOL SystemTimer)
InternalSetTimer( PWINDOW_OBJECT Window,
UINT_PTR IDEvent,
UINT Elapse,
TIMERPROC TimerFunc,
INT Type)
{
return 0;
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 @@ SystemTimerProc(HWND hwnd,
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();
}
//
//