Author: jimtabor
Date: Sun Nov 14 00:27:38 2010
New Revision: 49579
URL:
http://svn.reactos.org/svn/reactos?rev=49579&view=rev
Log:
[Win32k]
- Fixed WaitForInputIdle, finally!, passed all the wine tests for it.
- Moved Get/Peek message to the new all in one support routine.
- Foreground hook hits one out of five, this needs more research.
- Attempted to workout synchronizing issues with low level and regular hooks.
Modified:
trunk/reactos/subsystems/win32/win32k/main/dllmain.c
trunk/reactos/subsystems/win32/win32k/ntuser/message.c
trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c
Modified: trunk/reactos/subsystems/win32/win32k/main/dllmain.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ma…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/main/dllmain.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/main/dllmain.c [iso-8859-1] Sun Nov 14 00:27:38
2010
@@ -103,6 +103,8 @@
ExInitializeFastMutex(&Win32Process->DriverObjListLock);
Win32Process->KeyboardLayout = W32kGetDefaultKeyLayout();
+ EngCreateEvent((PEVENT *)&Win32Process->InputIdleEvent);
+ KeInitializeEvent(Win32Process->InputIdleEvent, NotificationEvent, FALSE);
if(Process->Peb != NULL)
{
@@ -118,6 +120,13 @@
else
{
DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n",
Process->UniqueProcessId, KeGetCurrentIrql());
+ Win32Process->W32PF_flags |= W32PF_TERMINATED;
+ if (Win32Process->InputIdleEvent)
+ {
+ EngFreeMem((PVOID)Win32Process->InputIdleEvent);
+ Win32Process->InputIdleEvent = NULL;
+ }
+
IntCleanupMenus(Process, Win32Process);
IntCleanupCurIcons(Process, Win32Process);
CleanupMonitorImpl();
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] Sun Nov 14
00:27:38 2010
@@ -14,6 +14,8 @@
#define NDEBUG
#include <debug.h>
+
+BOOLEAN NTAPI PsGetProcessExitProcessCalled(PEPROCESS Process);
#define PM_BADMSGFLAGS ~((QS_RAWINPUT <<
16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
@@ -323,6 +325,52 @@
return STATUS_INVALID_PARAMETER;
}
+//
+// Wakeup any thread/process waiting on idle input.
+//
+VOID FASTCALL
+IdlePing(VOID)
+{
+ PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
+ PUSER_MESSAGE_QUEUE ForegroundQueue;
+ PTHREADINFO pti, ptiForeground = NULL;
+
+ ForegroundQueue = IntGetFocusMessageQueue();
+
+ if (ForegroundQueue)
+ ptiForeground = ForegroundQueue->Thread->Tcb.Win32Thread;
+
+ pti = PsGetCurrentThreadWin32Thread();
+
+ if ( pti && pti->pDeskInfo && pti == ptiForeground )
+ {
+ if ( pti->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) ||
+ pti->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) )
+ {
+ co_HOOK_CallHooks(WH_FOREGROUNDIDLE,HC_ACTION,0,0);
+ }
+ }
+
+ DPRINT("IdlePing ppi 0x%x\n",ppi);
+ if ( ppi && ppi->InputIdleEvent )
+ {
+ DPRINT("InputIdleEvent\n");
+ KeSetEvent( ppi->InputIdleEvent, IO_NO_INCREMENT, FALSE);
+ }
+}
+
+VOID FASTCALL
+IdlePong(VOID)
+{
+ PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
+
+ DPRINT("IdlePong ppi 0x%x\n",ppi);
+ if ( ppi && ppi->InputIdleEvent )
+ {
+ KeClearEvent(ppi->InputIdleEvent);
+ }
+}
+
static VOID FASTCALL
IntCallWndProc( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
@@ -856,6 +904,8 @@
RemoveMessages = RemoveMsg & PM_REMOVE;
+ IdlePong();
+
do
{
KeQueryTickCount(&LargeTickCount);
@@ -944,10 +994,6 @@
}
while (TRUE);
- // The WH_GETMESSAGE hook enables an application to monitor messages about to
- // be returned by the GetMessage or PeekMessage function.
-
- co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE,
(LPARAM)&Msg->Msg);
return TRUE;
}
@@ -1068,6 +1114,7 @@
{
return TRUE;
}
+
/* Nothing found. Wait for new messages. */
Status = co_MsqWaitForNewMessages( ThreadQueue,
Window,
@@ -1094,9 +1141,9 @@
UINT RemoveMsg,
BOOL bGMSG )
{
- BOOL Present;
PWND Window;
USER_MESSAGE Msg;
+ BOOL Present = FALSE;
if ( hWnd == HWND_TOPMOST || hWnd == HWND_BROADCAST )
hWnd = HWND_BOTTOM;
@@ -1122,6 +1169,8 @@
MsgFilterMin = 0;
MsgFilterMax = 0;
}
+
+ RtlZeroMemory(&Msg, sizeof(USER_MESSAGE));
do
{
@@ -1132,33 +1181,40 @@
RemoveMsg );
if (Present)
{
- RtlCopyMemory( pMsg, &Msg.Msg, sizeof(MSG));
-
- if (bGMSG)
- return (WM_QUIT != pMsg->message);
- else
- return TRUE;
- }
-
- if ( bGMSG && !co_IntWaitMessage(Window, MsgFilterMin, MsgFilterMax) )
- {
- return -1;
+ RtlCopyMemory( pMsg, &Msg.Msg, sizeof(MSG));
+
+ // The WH_GETMESSAGE hook enables an application to monitor messages about to
+ // be returned by the GetMessage or PeekMessage function.
+
+ co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE,
(LPARAM)pMsg);
+
+ if ( bGMSG )
+ return (WM_QUIT != pMsg->message);
+ }
+
+ if ( bGMSG )
+ {
+ if ( !co_IntWaitMessage(Window, MsgFilterMin, MsgFilterMax) )
+ return -1;
}
else
{
- if (!(RemoveMsg & PM_NOYIELD))
- {
- // Yield this thread!
- UserLeave();
- ZwYieldExecution();
- UserEnterExclusive();
- // Fall through to fail.
- }
+ if (!(RemoveMsg & PM_NOYIELD))
+ {
+ IdlePing();
+ // Yield this thread!
+ UserLeave();
+ ZwYieldExecution();
+ UserEnterExclusive();
+ // Fall through to exit.
+ IdlePong();
+ }
+ break;
}
}
while( bGMSG && !Present );
- return FALSE;
+ return Present;
}
BOOL FASTCALL
@@ -2049,49 +2105,30 @@
* retrieved.
*/
{
- BOOL GotMessage;
NTUSERGETMESSAGEINFO Info;
NTSTATUS Status;
/* FIXME: if initialization is removed, gcc complains that this may be used before
initialization. Please review */
- PWND Window = NULL;
PMSGMEMORY MsgMemoryEntry;
PVOID UserMem;
ULONG Size;
- USER_MESSAGE Msg;
-
- DPRINT("Enter NtUserGetMessage\n");
+ MSG Msg;
+ BOOL GotMessage;
+
+ if ( (MsgFilterMin|MsgFilterMax) & ~WM_MAXIMUM )
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
UserEnterExclusive();
- /* Validate input */
- if (hWnd && !(Window = UserGetWindowObject(hWnd)))
- {
- UserLeave();
- return -1;
- }
-
- // if (Window) UserRefObjectCo(Window, &Ref);
-
- if (MsgFilterMax < MsgFilterMin)
- {
- MsgFilterMin = 0;
- MsgFilterMax = 0;
- }
-
- do
- {
- GotMessage = co_IntPeekMessage(&Msg, Window, MsgFilterMin, MsgFilterMax,
PM_REMOVE);
-
- if (!GotMessage && !co_IntWaitMessage(Window, MsgFilterMin,
MsgFilterMax))
- {
- UserLeave();
- return -1;
- }
- }
- while (! GotMessage);
+ RtlZeroMemory(&Msg, sizeof(MSG));
+
+ GotMessage = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax,
PM_REMOVE, TRUE);
UserLeave();
- Info.Msg = Msg.Msg;
+ Info.Msg = Msg; //.Msg;
/* See if this message type is present in the table */
MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
@@ -2103,7 +2140,7 @@
if (NULL == MsgMemoryEntry)
{
/* Not present, no copying needed */
- Info.LParamSize = 0;
+ UnsafeInfo->LParamSize = 0;
}
else
{
@@ -2127,8 +2164,8 @@
ProbeForWrite(UserMem, Size, 1);
RtlCopyMemory(UserMem, (PVOID)Info.Msg.lParam, Size);
- Info.LParamSize = Size;
- Info.Msg.lParam = (LPARAM) UserMem;
+ UnsafeInfo->LParamSize = Size;
+ UnsafeInfo->Msg.lParam = (LPARAM) UserMem;
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -2144,7 +2181,7 @@
}
_SEH2_END;
- return (Info.Msg.message != WM_QUIT );
+ return GotMessage;
}
@@ -2163,9 +2200,9 @@
return FALSE;
}
+ UserEnterExclusive();
+
RtlZeroMemory(&Msg, sizeof(MSG));
-
- UserEnterExclusive();
Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE,
TRUE);
@@ -2197,46 +2234,30 @@
UINT RemoveMsg)
{
NTSTATUS Status;
- BOOL Ret;
NTUSERGETMESSAGEINFO Info;
- PWND Window;
PMSGMEMORY MsgMemoryEntry;
PVOID UserMem = NULL;
ULONG Size;
- USER_MESSAGE Msg;
+ MSG Msg;
+ BOOL Ret;
+
+ if ( RemoveMsg & PM_BADMSGFLAGS )
+ {
+ SetLastWin32Error(ERROR_INVALID_FLAGS);
+ return FALSE;
+ }
UserEnterExclusive();
- if (hWnd == (HWND)-1 || hWnd == (HWND)0x0000FFFF || hWnd == (HWND)0xFFFFFFFF)
- hWnd = (HWND)1;
-
- /* Validate input */
- if (hWnd && hWnd != (HWND)1)
- {
- if (!(Window = UserGetWindowObject(hWnd)))
- {
- UserLeave();
- return -1;
- }
- }
- else
- {
- Window = (PWND)hWnd;
- }
-
- if (MsgFilterMax < MsgFilterMin)
- {
- MsgFilterMin = 0;
- MsgFilterMax = 0;
- }
-
- Ret = co_IntPeekMessage(&Msg, Window, MsgFilterMin, MsgFilterMax, RemoveMsg);
+ RtlZeroMemory(&Msg, sizeof(MSG));
+
+ Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg,
FALSE);
UserLeave();
if (Ret)
{
- Info.Msg = Msg.Msg;
+ Info.Msg = Msg;
/* See if this message type is present in the table */
MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
@@ -2248,7 +2269,7 @@
if (NULL == MsgMemoryEntry)
{
/* Not present, no copying needed */
- Info.LParamSize = 0;
+ UnsafeInfo->LParamSize = 0;
}
else
{
@@ -2272,8 +2293,8 @@
ProbeForWrite(UserMem, Size, 1);
RtlCopyMemory(UserMem, (PVOID)Info.Msg.lParam, Size);
- Info.LParamSize = Size;
- Info.Msg.lParam = (LPARAM) UserMem;
+ UnsafeInfo->LParamSize = Size;
+ UnsafeInfo->Msg.lParam = (LPARAM) UserMem;
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -2308,9 +2329,9 @@
return FALSE;
}
+ UserEnterExclusive();
+
RtlZeroMemory(&Msg, sizeof(MSG));
-
- UserEnterExclusive();
Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg,
FALSE);
@@ -2665,10 +2686,10 @@
{
PEPROCESS Process;
PPROCESSINFO W32Process;
+ PTHREADINFO pti;
NTSTATUS Status;
- HANDLE Handles[2];
+ HANDLE Handles[3];
LARGE_INTEGER Timeout;
- ULONGLONG StartTime, Run, Elapsed = 0;
UserEnterExclusive();
@@ -2686,8 +2707,13 @@
return WAIT_FAILED;
}
+ pti = PsGetCurrentThreadWin32Thread();
+
W32Process = (PPROCESSINFO)Process->Win32Process;
- if (!W32Process)
+
+ if ( PsGetProcessExitProcessCalled(Process) ||
+ !W32Process ||
+ pti->ppi == W32Process)
{
ObDereferenceObject(Process);
UserLeave();
@@ -2695,10 +2721,9 @@
return WAIT_FAILED;
}
- EngCreateEvent((PEVENT *)&W32Process->InputIdleEvent);
-
Handles[0] = Process;
Handles[1] = W32Process->InputIdleEvent;
+ Handles[2] = pti->MessageQueue->NewMessages; // pEventQueueServer;
IntMsqSetWakeMask returns hEventQueueClient
if (!Handles[1])
{
@@ -2707,16 +2732,15 @@
return STATUS_SUCCESS; /* no event to wait on */
}
- StartTime = EngGetTickCount();
-
- Run = dwMilliseconds;
-
+ if (dwMilliseconds != INFINITE)
+ Timeout.QuadPart = (LONGLONG) dwMilliseconds * (LONGLONG) -10000;
+
+ DPRINT("WFII: ppi 0x%x\n",W32Process);
DPRINT("WFII: waiting for %p\n", Handles[1] );
do
{
- Timeout.QuadPart = Run - Elapsed;
UserLeave();
- Status = KeWaitForMultipleObjects( 2,
+ Status = KeWaitForMultipleObjects( 3,
Handles,
WaitAny,
UserRequest,
@@ -2736,21 +2760,19 @@
switch (Status)
{
case STATUS_WAIT_0:
- Status = WAIT_FAILED;
goto WaitExit;
case STATUS_WAIT_2:
{
- USER_MESSAGE Msg;
- co_IntPeekMessage( &Msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE );
- break;
- }
-
- case STATUS_USER_APC:
- case STATUS_ALERTED:
+ USER_MESSAGE Msg;
+ co_IntPeekMessage( &Msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE );
+ DPRINT1("WFII: WAIT 2\n");
+ }
+ break;
+
case STATUS_TIMEOUT:
DPRINT1("WFII: timeout\n");
- Status = STATUS_TIMEOUT;
+ case WAIT_FAILED:
goto WaitExit;
default:
@@ -2758,24 +2780,10 @@
Status = STATUS_SUCCESS;
goto WaitExit;
}
-
- if (dwMilliseconds != INFINITE)
- {
- Elapsed = EngGetTickCount() - StartTime;
-
- if (Elapsed > Run)
- Status = STATUS_TIMEOUT;
- break;
- }
- }
- while (1);
+ }
+ while (TRUE);
WaitExit:
- if (W32Process->InputIdleEvent)
- {
- EngFreeMem((PVOID)W32Process->InputIdleEvent);
- W32Process->InputIdleEvent = NULL;
- }
ObDereferenceObject(Process);
UserLeave();
return Status;
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/msgqueue.c [iso-8859-1] Sun Nov 14
00:27:38 2010
@@ -62,32 +62,6 @@
/* FUNCTIONS *****************************************************************/
-//
-// Wakeup any thread/process waiting on idle input.
-//
-static VOID FASTCALL
-IdlePing(VOID)
-{
- HWND hWnd;
- PWND Window;
- PPROCESSINFO W32d = PsGetCurrentProcessWin32Process();
-
- hWnd = UserGetForegroundWindow();
-
- Window = UserGetWindowObject(hWnd);
-
- if (Window && Window->head.pti)
- {
- if (Window->head.pti->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE))
- {
- co_HOOK_CallHooks(WH_FOREGROUNDIDLE,HC_ACTION,0,0);
- }
- }
-
- if (W32d && W32d->InputIdleEvent)
- KePulseEvent( W32d->InputIdleEvent, EVENT_INCREMENT, TRUE);
-}
-
HANDLE FASTCALL
IntMsqSetWakeMask(DWORD WakeMask)
{
@@ -578,8 +552,6 @@
WaitObjects[0] = &HardwareMessageQueueLock;
do
{
- IdlePing();
-
UserLeaveCo();
WaitStatus = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, UserRequest,
@@ -1185,8 +1157,6 @@
if(Block)
{
- IdlePing();
-
UserLeaveCo();
/* don't process messages sent to the thread */
@@ -1248,8 +1218,6 @@
WaitObjects[1] = ThreadQueue->NewMessages;
do
{
- IdlePing();
-
UserLeaveCo();
WaitStatus = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, UserRequest,
@@ -1406,8 +1374,6 @@
{
PVOID WaitObjects[2] = {MessageQueue->NewMessages, &HardwareMessageEvent};
NTSTATUS ret;
-
- IdlePing(); // Going to wait so send Idle ping.
UserLeaveCo();