📄 message.c
字号:
WPARAM wParam;
PSYSTEM_CURSORINFO CurInfo;
if(!IntGetWindowStationObject(InputWindowStation))
{
break;
}
CurInfo = IntGetSysCursorInfo(InputWindowStation);
wParam = (WPARAM)(CurInfo->ButtonsDown);
ObDereferenceObject(InputWindowStation);
co_IntSendMessage(Msg->hwnd, WM_MOUSEMOVE, wParam, Msg->lParam);
co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(HTCLIENT, Msg->message));
break;
}
case WM_NCLBUTTONDOWN:
case WM_NCMBUTTONDOWN:
case WM_NCRBUTTONDOWN:
case WM_NCXBUTTONDOWN:
case WM_NCLBUTTONDBLCLK:
case WM_NCMBUTTONDBLCLK:
case WM_NCRBUTTONDBLCLK:
case WM_NCXBUTTONDBLCLK:
{
co_IntSendMessage(Msg->hwnd, WM_NCMOUSEMOVE, (WPARAM)Msg->wParam, Msg->lParam);
co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(Msg->wParam, Msg->message));
break;
}
}
}
BOOL FASTCALL
co_IntActivateWindowMouse(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg, PWINDOW_OBJECT MsgWindow,
USHORT *HitTest)
{
ULONG Result;
PWINDOW_OBJECT Parent;
ASSERT_REFS_CO(MsgWindow);
if(*HitTest == (USHORT)HTTRANSPARENT)
{
/* eat the message, search again! */
return TRUE;
}
Parent = IntGetParent(MsgWindow);//fixme: deref retval?
/* fixme: abort if no parent ? */
Result = co_IntSendMessage(MsgWindow->hSelf,
WM_MOUSEACTIVATE,
(WPARAM) (Parent ? Parent->hSelf : NULL),
(LPARAM)MAKELONG(*HitTest, Msg->message)
);
switch (Result)
{
case MA_NOACTIVATEANDEAT:
return TRUE;
case MA_NOACTIVATE:
break;
case MA_ACTIVATEANDEAT:
co_IntMouseActivateWindow(MsgWindow);
return TRUE;
default:
/* MA_ACTIVATE */
co_IntMouseActivateWindow(MsgWindow);
break;
}
return FALSE;
}
BOOL FASTCALL
co_IntTranslateMouseMessage(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg, USHORT *HitTest, BOOL Remove)
{
PWINDOW_OBJECT Window;
USER_REFERENCE_ENTRY Ref, DesktopRef;
if(!(Window = UserGetWindowObject(Msg->hwnd)))
{
/* let's just eat the message?! */
return TRUE;
}
UserRefObjectCo(Window, &Ref);
if(ThreadQueue == Window->MessageQueue &&
ThreadQueue->CaptureWindow != Window->hSelf)
{
/* only send WM_NCHITTEST messages if we're not capturing the window! */
*HitTest = co_IntSendMessage(Window->hSelf, WM_NCHITTEST, 0,
MAKELONG(Msg->pt.x, Msg->pt.y));
if(*HitTest == (USHORT)HTTRANSPARENT)
{
PWINDOW_OBJECT DesktopWindow;
HWND hDesktop = IntGetDesktopWindow();
if((DesktopWindow = UserGetWindowObject(hDesktop)))
{
PWINDOW_OBJECT Wnd;
UserRefObjectCo(DesktopWindow, &DesktopRef);
co_WinPosWindowFromPoint(DesktopWindow, Window->MessageQueue, &Msg->pt, &Wnd);
if(Wnd)
{
if(Wnd != Window)
{
/* post the message to the other window */
Msg->hwnd = Wnd->hSelf;
if(!(Wnd->Status & WINDOWSTATUS_DESTROYING))
{
MsqPostMessage(Wnd->MessageQueue, Msg, FALSE,
Msg->message == WM_MOUSEMOVE ? QS_MOUSEMOVE :
QS_MOUSEBUTTON);
}
/* eat the message */
UserDerefObject(Wnd);
UserDerefObjectCo(DesktopWindow);
UserDerefObjectCo(Window);
return TRUE;
}
UserDerefObject(Wnd);
}
UserDerefObjectCo(DesktopWindow);
}
}
}
else
{
*HitTest = HTCLIENT;
}
if(IS_BTN_MESSAGE(Msg->message, DOWN))
{
/* generate double click messages, if necessary */
if ((((*HitTest) != HTCLIENT) ||
(Window->Class->Style & CS_DBLCLKS)) &&
MsqIsDblClk(Msg, Remove))
{
Msg->message += WM_LBUTTONDBLCLK - WM_LBUTTONDOWN;
}
}
if(Msg->message != WM_MOUSEWHEEL)
{
if ((*HitTest) != HTCLIENT)
{
Msg->message += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
if((Msg->message == WM_NCRBUTTONUP) &&
(((*HitTest) == HTCAPTION) || ((*HitTest) == HTSYSMENU)))
{
Msg->message = WM_CONTEXTMENU;
Msg->wParam = (WPARAM)Window->hSelf;
}
else
{
Msg->wParam = *HitTest;
}
Msg->lParam = MAKELONG(Msg->pt.x, Msg->pt.y);
}
else if(ThreadQueue->MoveSize == NULL &&
ThreadQueue->MenuOwner == NULL)
{
/* NOTE: Msg->pt should remain in screen coordinates. -- FiN */
Msg->lParam = MAKELONG(
Msg->pt.x - (WORD)Window->ClientRect.left,
Msg->pt.y - (WORD)Window->ClientRect.top);
}
}
UserDerefObjectCo(Window);
return FALSE;
}
/*
* Internal version of PeekMessage() doing all the work
*/
BOOL FASTCALL
co_IntPeekMessage(PUSER_MESSAGE Msg,
HWND hWnd,
UINT MsgFilterMin,
UINT MsgFilterMax,
UINT RemoveMsg)
{
LARGE_INTEGER LargeTickCount;
PUSER_MESSAGE_QUEUE ThreadQueue;
PUSER_MESSAGE Message;
BOOL Present, RemoveMessages;
USER_REFERENCE_ENTRY Ref;
USHORT HitTest;
/* The queues and order in which they are checked are documented in the MSDN
article on GetMessage() */
ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetCurrentThreadWin32Thread()->MessageQueue;
/* Inspect RemoveMsg flags */
/* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
RemoveMessages = RemoveMsg & PM_REMOVE;
CheckMessages:
Present = FALSE;
KeQueryTickCount(&LargeTickCount);
ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
/* Dispatch sent messages here. */
while (co_MsqDispatchOneSentMessage(ThreadQueue))
;
/* Now look for a quit message. */
if (ThreadQueue->QuitPosted)
{
/* According to the PSDK, WM_QUIT messages are always returned, regardless
of the filter specified */
Msg->Msg.hwnd = NULL;
Msg->Msg.message = WM_QUIT;
Msg->Msg.wParam = ThreadQueue->QuitExitCode;
Msg->Msg.lParam = 0;
Msg->FreeLParam = FALSE;
if (RemoveMessages)
{
ThreadQueue->QuitPosted = FALSE;
}
return TRUE;
}
/* Now check for normal messages. */
Present = co_MsqFindMessage(ThreadQueue,
FALSE,
RemoveMessages,
hWnd,
MsgFilterMin,
MsgFilterMax,
&Message);
if (Present)
{
RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
if (RemoveMessages)
{
MsqDestroyMessage(Message);
}
goto MessageFound;
}
/* Check for hardware events. */
Present = co_MsqFindMessage(ThreadQueue,
TRUE,
RemoveMessages,
hWnd,
MsgFilterMin,
MsgFilterMax,
&Message);
if (Present)
{
RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
if (RemoveMessages)
{
MsqDestroyMessage(Message);
}
goto MessageFound;
}
/* Check for sent messages again. */
while (co_MsqDispatchOneSentMessage(ThreadQueue))
;
/* Check for paint messages. */
if (IntGetPaintMessage(hWnd, MsgFilterMin, MsgFilterMax, PsGetCurrentThreadWin32Thread(), &Msg->Msg, RemoveMessages))
{
Msg->FreeLParam = FALSE;
return TRUE;
}
/* Check for WM_(SYS)TIMER messages */
Present = MsqGetTimerMessage(ThreadQueue, hWnd, MsgFilterMin, MsgFilterMax,
&Msg->Msg, RemoveMessages);
if (Present)
{
Msg->FreeLParam = FALSE;
goto MessageFound;
}
if(Present)
{
MessageFound:
if(RemoveMessages)
{
PWINDOW_OBJECT MsgWindow = NULL;
if(Msg->Msg.hwnd && (MsgWindow = UserGetWindowObject(Msg->Msg.hwnd)) &&
Msg->Msg.message >= WM_MOUSEFIRST && Msg->Msg.message <= WM_MOUSELAST)
{
USHORT HitTest;
UserRefObjectCo(MsgWindow, &Ref);
if(co_IntTranslateMouseMessage(ThreadQueue, &Msg->Msg, &HitTest, TRUE))
/* FIXME - check message filter again, if the message doesn't match anymore,
search again */
{
UserDerefObjectCo(MsgWindow);
/* eat the message, search again */
goto CheckMessages;
}
if(ThreadQueue->CaptureWindow == NULL)
{
co_IntSendHitTestMessages(ThreadQueue, &Msg->Msg);
if((Msg->Msg.message != WM_MOUSEMOVE && Msg->Msg.message != WM_NCMOUSEMOVE) &&
IS_BTN_MESSAGE(Msg->Msg.message, DOWN) &&
co_IntActivateWindowMouse(ThreadQueue, &Msg->Msg, MsgWindow, &HitTest))
{
UserDerefObjectCo(MsgWindow);
/* eat the message, search again */
goto CheckMessages;
}
}
UserDerefObjectCo(MsgWindow);
}
else
{
co_IntSendHitTestMessages(ThreadQueue, &Msg->Msg);
}
// if(MsgWindow)
// {
// UserDerefObject(MsgWindow);
// }
return TRUE;
}
if((Msg->Msg.hwnd && Msg->Msg.message >= WM_MOUSEFIRST && Msg->Msg.message <= WM_MOUSELAST) &&
co_IntTranslateMouseMessage(ThreadQueue, &Msg->Msg, &HitTest, FALSE))
/* FIXME - check message filter again, if the message doesn't match anymore,
search again */
{
/* eat the message, search again */
goto CheckMessages;
}
return TRUE;
}
return Present;
}
BOOL STDCALL
NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
HWND hWnd,
UINT MsgFilterMin,
UINT MsgFilterMax,
UINT RemoveMsg)
{
NTSTATUS Status;
BOOL Present;
NTUSERGETMESSAGEINFO Info;
PWINDOW_OBJECT Window;
PMSGMEMORY MsgMemoryEntry;
PVOID UserMem;
UINT Size;
USER_MESSAGE Msg;
DECLARE_RETURN(BOOL);
DPRINT("Enter NtUserPeekMessage\n");
UserEnterExclusive();
/* Validate input */
if (hWnd && hWnd != INVALID_HANDLE_VALUE)
{
if (!(Window = UserGetWindowObject(hWnd)))
{
RETURN(-1);
}
}
if (MsgFilterMax < MsgFilterMin)
{
MsgFilterMin = 0;
MsgFilterMax = 0;
}
Present = co_IntPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg);
if (Present)
{
Info.Msg = Msg.Msg;
/* See if this message type is present in the table */
MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
if (NULL == MsgMemoryEntry)
{
/* Not present, no copying needed */
Info.LParamSize = 0;
}
else
{
/* Determine required size */
Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam,
Info.Msg.lParam);
/* Allocate required amount of user-mode memory */
Info.LParamSize = Size;
UserMem = NULL;
Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem, 0,
&Info.LParamSize, MEM_COMMIT, PAGE_READWRITE);
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( (BOOL) -1);
}
/* Transfer lParam data to user-mode mem */
Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Size);
if (! NT_SUCCESS(Status))
{
ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &UserMem,
&Info.LParamSize, MEM_DECOMMIT);
SetLastNtError(Status);
RETURN( (BOOL) -1);
}
Info.Msg.lParam = (LPARAM) UserMem;
}
if (RemoveMsg && Msg.FreeLParam && 0 != Msg.Msg.lParam)
{
ExFreePool((void *) Msg.Msg.lParam);
}
Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO));
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( (BOOL) -1);
}
}
RETURN( Present);
CLEANUP:
DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
static BOOL FASTCALL
co_IntWaitMessage(HWND Wnd,
UINT MsgFilterMin,
UINT MsgFilterMax)
{
PUSER_MESSAGE_QUEUE ThreadQueue;
NTSTATUS Status;
USER_MESSAGE Msg;
ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetCurrentThreadWin32Thread()->MessageQueue;
do
{
if (co_IntPeekMessage(&Msg, Wnd, MsgFilterMin, MsgFilterMax, PM_NOREMOVE))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -