mirror of
https://github.com/reactos/reactos.git
synced 2025-06-06 01:40:36 +00:00
- 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:
parent
a3c29b9686
commit
a0d07a719b
7 changed files with 309 additions and 13 deletions
|
@ -37,4 +37,6 @@ PKBL UserHklToKbl(HKL hKl);
|
|||
#define ThreadHasInputAccess(W32Thread) \
|
||||
(TRUE)
|
||||
|
||||
extern PTHREADINFO ptiRawInput;
|
||||
|
||||
#endif /* _WIN32K_INPUT_H */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1117,7 +1117,7 @@ NtUserValidateTimerCallback(
|
|||
goto Exit;
|
||||
}
|
||||
|
||||
Ret = ValidateTimerCallback(GetW32ThreadInfo(), Window, wParam, lParam);
|
||||
Ret = ValidateTimerCallback(PsGetCurrentThreadWin32Thread(), Window, wParam, lParam);
|
||||
|
||||
Exit:
|
||||
UserLeave();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue