- Do not do callbacks to user mode while holding a lock
- Fix when WH_MOUSE_LL and WH_JOURNALRECORD are called
See issue #4926 for more details.

svn path=/trunk/; revision=47058
This commit is contained in:
Giannis Adamopoulos 2010-04-29 07:48:43 +00:00
parent 3ec3baec08
commit 0ec839d544
4 changed files with 140 additions and 112 deletions

View file

@ -248,6 +248,16 @@ VOID APIENTRY MsqRemoveWindowMessagesFromQueue(PVOID pWindow); /* F*(&$ headers,
(message) == WM_NCRBUTTON##code || \ (message) == WM_NCRBUTTON##code || \
(message) == WM_NCXBUTTON##code ) (message) == WM_NCXBUTTON##code )
#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
#define WM_NCMOUSELAST (WM_NCMOUSEFIRST+(WM_MOUSELAST-WM_MOUSEFIRST))
#define IS_MOUSE_MESSAGE(message) \
((message >= WM_NCMOUSEFIRST && message <= WM_NCMOUSELAST) || \
(message >= WM_MOUSEFIRST && message <= WM_MOUSELAST))
#define IS_KBD_MESSAGE(message) \
(message == WM_KEYDOWN || message == WM_KEYUP)
HANDLE FASTCALL HANDLE FASTCALL
IntMsqSetWakeMask(DWORD WakeMask); IntMsqSetWakeMask(DWORD WakeMask);

View file

@ -204,6 +204,16 @@ MouseThreadMain(PVOID StartContext)
NTSTATUS Status; NTSTATUS Status;
MOUSE_ATTRIBUTES MouseAttr; MOUSE_ATTRIBUTES MouseAttr;
Status = Win32kInitWin32Thread(PsGetCurrentThread());
if (!NT_SUCCESS(Status))
{
DPRINT1("Win32K: Failed making keyboard thread a win32 thread.\n");
return; //(Status);
}
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
LOW_REALTIME_PRIORITY + 3);
InitializeObjectAttributes(&MouseObjectAttributes, InitializeObjectAttributes(&MouseObjectAttributes,
&MouseDeviceName, &MouseDeviceName,
0, 0,

View file

@ -645,6 +645,74 @@ co_IntTranslateMouseMessage(
return FALSE; return FALSE;
} }
BOOL ProcessMouseMessage(MSG* Msg, USHORT HitTest, UINT RemoveMsg)
{
MOUSEHOOKSTRUCT MHook;
EVENTMSG Event;
Event.message = Msg->message;
Event.time = Msg->time;
Event.hwnd = Msg->hwnd;
Event.paramL = Msg->pt.x;
Event.paramH = Msg->pt.y;
co_HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&Event);
MHook.pt = Msg->pt;
MHook.hwnd = Msg->hwnd;
MHook.wHitTestCode = HitTest;
MHook.dwExtraInfo = 0;
if (co_HOOK_CallHooks( WH_MOUSE,
RemoveMsg ? HC_ACTION : HC_NOREMOVE,
Msg->message,
(LPARAM)&MHook ))
{
if (ISITHOOKED(WH_CBT))
{
MHook.pt = Msg->pt;
MHook.hwnd = Msg->hwnd;
MHook.wHitTestCode = HitTest;
MHook.dwExtraInfo = 0;
co_HOOK_CallHooks( WH_CBT,
HCBT_CLICKSKIPPED,
Msg->message,
(LPARAM)&MHook);
}
return FALSE;
}
return TRUE;
}
BOOL ProcessKeyboardMessage(MSG* Msg, UINT RemoveMsg)
{
EVENTMSG Event;
Event.message = Msg->message;
Event.hwnd = Msg->hwnd;
Event.time = Msg->time;
Event.paramL = (Msg->wParam & 0xFF) | (HIWORD(Msg->lParam) << 8);
Event.paramH = Msg->lParam & 0x7FFF;
if (HIWORD(Msg->lParam) & 0x0100) Event.paramH |= 0x8000;
co_HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&Event);
if (co_HOOK_CallHooks( WH_KEYBOARD,
RemoveMsg ? HC_ACTION : HC_NOREMOVE,
LOWORD(Msg->wParam),
Msg->lParam))
{
if (ISITHOOKED(WH_CBT))
{
/* skip this message */
co_HOOK_CallHooks( WH_CBT,
HCBT_KEYSKIPPED,
LOWORD(Msg->wParam),
Msg->lParam );
}
return FALSE;
}
return TRUE;
}
/* /*
* Internal version of PeekMessage() doing all the work * Internal version of PeekMessage() doing all the work
*/ */
@ -662,7 +730,6 @@ co_IntPeekMessage( PUSER_MESSAGE Msg,
BOOL Present, RemoveMessages; BOOL Present, RemoveMessages;
USER_REFERENCE_ENTRY Ref; USER_REFERENCE_ENTRY Ref;
USHORT HitTest; USHORT HitTest;
MOUSEHOOKSTRUCT MHook;
/* The queues and order in which they are checked are documented in the MSDN /* The queues and order in which they are checked are documented in the MSDN
article on GetMessage() */ article on GetMessage() */
@ -867,52 +934,20 @@ MessageFound:
} }
MsgExit: MsgExit:
if ( ISITHOOKED(WH_MOUSE) && if ( ISITHOOKED(WH_MOUSE) && IS_MOUSE_MESSAGE(Msg->Msg.message))
Msg->Msg.message >= WM_MOUSEFIRST &&
Msg->Msg.message <= WM_MOUSELAST )
{ {
MHook.pt = Msg->Msg.pt; if(!ProcessMouseMessage(&Msg->Msg, HitTest, RemoveMsg))
MHook.hwnd = Msg->Msg.hwnd; {
MHook.wHitTestCode = HitTest; return FALSE;
MHook.dwExtraInfo = 0; }
if (co_HOOK_CallHooks( WH_MOUSE, }
RemoveMsg ? HC_ACTION : HC_NOREMOVE,
Msg->Msg.message,
(LPARAM)&MHook ))
{
if (ISITHOOKED(WH_CBT))
{
MHook.pt = Msg->Msg.pt;
MHook.hwnd = Msg->Msg.hwnd;
MHook.wHitTestCode = HitTest;
MHook.dwExtraInfo = 0;
co_HOOK_CallHooks( WH_CBT,
HCBT_CLICKSKIPPED,
Msg->Msg.message,
(LPARAM)&MHook);
}
return FALSE;
}
}
if ( ISITHOOKED(WH_KEYBOARD) && if ( ISITHOOKED(WH_KEYBOARD) && IS_KBD_MESSAGE(Msg->Msg.message))
(Msg->Msg.message == WM_KEYDOWN || Msg->Msg.message == WM_KEYUP) )
{ {
if (co_HOOK_CallHooks( WH_KEYBOARD, if(!ProcessKeyboardMessage(&Msg->Msg, RemoveMsg))
RemoveMsg ? HC_ACTION : HC_NOREMOVE, {
LOWORD(Msg->Msg.wParam), return FALSE;
Msg->Msg.lParam)) }
{
if (ISITHOOKED(WH_CBT))
{
/* skip this message */
co_HOOK_CallHooks( WH_CBT,
HCBT_KEYSKIPPED,
LOWORD(Msg->Msg.wParam),
Msg->Msg.lParam );
}
return FALSE;
}
} }
// The WH_GETMESSAGE hook enables an application to monitor messages about to // The WH_GETMESSAGE hook enables an application to monitor messages about to
// be returned by the GetMessage or PeekMessage function. // be returned by the GetMessage or PeekMessage function.

View file

@ -174,8 +174,41 @@ MsqInsertSystemMessage(MSG* Msg)
LARGE_INTEGER LargeTickCount; LARGE_INTEGER LargeTickCount;
KIRQL OldIrql; KIRQL OldIrql;
ULONG Prev; ULONG Prev;
EVENTMSG Event; MSLLHOOKSTRUCT MouseHookData;
KeQueryTickCount(&LargeTickCount);
Msg->time = MsqCalculateMessageTime(&LargeTickCount);
MouseHookData.pt.x = LOWORD(Msg->lParam);
MouseHookData.pt.y = HIWORD(Msg->lParam);
switch(Msg->message)
{
case WM_MOUSEWHEEL:
MouseHookData.mouseData = MAKELONG(0, GET_WHEEL_DELTA_WPARAM(Msg->wParam));
break;
case WM_XBUTTONDOWN:
case WM_XBUTTONUP:
case WM_XBUTTONDBLCLK:
case WM_NCXBUTTONDOWN:
case WM_NCXBUTTONUP:
case WM_NCXBUTTONDBLCLK:
MouseHookData.mouseData = MAKELONG(0, HIWORD(Msg->wParam));
break;
default:
MouseHookData.mouseData = 0;
break;
}
MouseHookData.flags = 0;
MouseHookData.time = Msg->time;
MouseHookData.dwExtraInfo = 0;
if( co_HOOK_CallHooks(WH_MOUSE_LL, HC_ACTION, Msg->message, (LPARAM) &MouseHookData))
return;
/*
* If we got WM_MOUSEMOVE and there are already messages in the
* system message queue, check if the last message is mouse move
* and if it is then just overwrite it.
*/
IntLockSystemMessageQueue(OldIrql); IntLockSystemMessageQueue(OldIrql);
/* /*
@ -189,22 +222,6 @@ MsqInsertSystemMessage(MSG* Msg)
return; return;
} }
KeQueryTickCount(&LargeTickCount);
Msg->time = MsqCalculateMessageTime(&LargeTickCount);
Event.message = Msg->message;
Event.time = Msg->time;
Event.hwnd = Msg->hwnd;
Event.paramL = Msg->pt.x;
Event.paramH = Msg->pt.y;
co_HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&Event);
/*
* If we got WM_MOUSEMOVE and there are already messages in the
* system message queue, check if the last message is mouse move
* and if it is then just overwrite it.
*/
if (Msg->message == WM_MOUSEMOVE && SystemMessageQueueCount) if (Msg->message == WM_MOUSEMOVE && SystemMessageQueueCount)
{ {
if (SystemMessageQueueTail == 0) if (SystemMessageQueueTail == 0)
@ -623,7 +640,6 @@ co_MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, PWINDOW_OBJECT Windo
{ {
PUSER_MESSAGE UserMsg; PUSER_MESSAGE UserMsg;
MSG Msg; MSG Msg;
BOOL ProcessMessage;
ASSERT(SystemMessageQueueHead < SYSTEM_MESSAGE_QUEUE_SIZE); ASSERT(SystemMessageQueueHead < SYSTEM_MESSAGE_QUEUE_SIZE);
Msg = SystemMessageQueue[SystemMessageQueueHead]; Msg = SystemMessageQueue[SystemMessageQueueHead];
@ -631,48 +647,14 @@ co_MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, PWINDOW_OBJECT Windo
(SystemMessageQueueHead + 1) % SYSTEM_MESSAGE_QUEUE_SIZE; (SystemMessageQueueHead + 1) % SYSTEM_MESSAGE_QUEUE_SIZE;
SystemMessageQueueCount--; SystemMessageQueueCount--;
IntUnLockSystemMessageQueue(OldIrql); IntUnLockSystemMessageQueue(OldIrql);
if (WM_MOUSEFIRST <= Msg.message && Msg.message <= WM_MOUSELAST)
{
MSLLHOOKSTRUCT MouseHookData;
MouseHookData.pt.x = LOWORD(Msg.lParam); UserMsg = ExAllocateFromPagedLookasideList(&MessageLookasideList);
MouseHookData.pt.y = HIWORD(Msg.lParam); /* What to do if out of memory? For now we just panic a bit in debug */
switch(Msg.message) ASSERT(UserMsg);
{ UserMsg->FreeLParam = FALSE;
case WM_MOUSEWHEEL: UserMsg->Msg = Msg;
MouseHookData.mouseData = MAKELONG(0, GET_WHEEL_DELTA_WPARAM(Msg.wParam)); InsertTailList(&HardwareMessageQueueHead, &UserMsg->ListEntry);
break;
case WM_XBUTTONDOWN:
case WM_XBUTTONUP:
case WM_XBUTTONDBLCLK:
case WM_NCXBUTTONDOWN:
case WM_NCXBUTTONUP:
case WM_NCXBUTTONDBLCLK:
MouseHookData.mouseData = MAKELONG(0, HIWORD(Msg.wParam));
break;
default:
MouseHookData.mouseData = 0;
break;
}
MouseHookData.flags = 0;
MouseHookData.time = Msg.time;
MouseHookData.dwExtraInfo = 0;
ProcessMessage = (0 == co_HOOK_CallHooks(WH_MOUSE_LL, HC_ACTION,
Msg.message, (LPARAM) &MouseHookData));
}
else
{
ProcessMessage = TRUE;
}
if (ProcessMessage)
{
UserMsg = ExAllocateFromPagedLookasideList(&MessageLookasideList);
/* What to do if out of memory? For now we just panic a bit in debug */
ASSERT(UserMsg);
UserMsg->FreeLParam = FALSE;
UserMsg->Msg = Msg;
InsertTailList(&HardwareMessageQueueHead, &UserMsg->ListEntry);
}
IntLockSystemMessageQueue(OldIrql); IntLockSystemMessageQueue(OldIrql);
} }
HardwareMessageQueueStamp++; HardwareMessageQueueStamp++;
@ -767,7 +749,6 @@ co_MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
MSG Msg; MSG Msg;
LARGE_INTEGER LargeTickCount; LARGE_INTEGER LargeTickCount;
KBDLLHOOKSTRUCT KbdHookData; KBDLLHOOKSTRUCT KbdHookData;
EVENTMSG Event;
BOOLEAN Entered = FALSE; BOOLEAN Entered = FALSE;
DPRINT("MsqPostKeyboardMessage(uMsg 0x%x, wParam 0x%x, lParam 0x%x)\n", DPRINT("MsqPostKeyboardMessage(uMsg 0x%x, wParam 0x%x, lParam 0x%x)\n",
@ -795,14 +776,6 @@ co_MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
KeQueryTickCount(&LargeTickCount); KeQueryTickCount(&LargeTickCount);
Msg.time = MsqCalculateMessageTime(&LargeTickCount); Msg.time = MsqCalculateMessageTime(&LargeTickCount);
Event.message = Msg.message;
Event.hwnd = Msg.hwnd;
Event.time = Msg.time;
Event.paramL = (Msg.wParam & 0xFF) | (HIWORD(Msg.lParam) << 8);
Event.paramH = Msg.lParam & 0x7FFF;
if (HIWORD(Msg.lParam) & 0x0100) Event.paramH |= 0x8000;
co_HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&Event);
/* We can't get the Msg.pt point here since we don't know thread /* We can't get the Msg.pt point here since we don't know thread
(and thus the window station) the message will end up in yet. */ (and thus the window station) the message will end up in yet. */