msgqueue.c
来自「一个类似windows」· C语言 代码 · 共 1,894 行 · 第 1/5 页
C
1,894 行
UserDerefObject(Window);
return(FALSE);
}
/* From here on, we're in the same message queue as the caller! */
*ScreenPoint = Message->Msg.pt;
if((hWnd != NULL && Window->hSelf != hWnd) ||
((FilterLow != 0 || FilterLow != 0) && (Msg < FilterLow || Msg > FilterHigh)))
{
/* Reject the message because it doesn't match the filter */
if(FromGlobalQueue)
{
/* Lock the message queue so no other thread can mess with it.
Our own message queue is not locked while fetching from the global
queue, so we have to make sure nothing interferes! */
IntLockHardwareMessageQueue(Window->MessageQueue);
/* if we're from the global queue, we need to add our message to our
private queue so we don't loose it! */
InsertTailList(&Window->MessageQueue->HardwareMessagesListHead,
&Message->ListEntry);
}
if (Message->Msg.message == WM_MOUSEMOVE)
{
if(Window->MessageQueue->MouseMoveMsg &&
(Window->MessageQueue->MouseMoveMsg != Message))
{
/* delete the old message */
RemoveEntryList(&Window->MessageQueue->MouseMoveMsg->ListEntry);
ExFreePool(Window->MessageQueue->MouseMoveMsg);
}
/* always save a pointer to this WM_MOUSEMOVE message here because we're
sure that the message is in the private queue */
Window->MessageQueue->MouseMoveMsg = Message;
}
if(FromGlobalQueue)
{
IntUnLockHardwareMessageQueue(Window->MessageQueue);
}
UserDerefObject(Window);
*Freed = FALSE;
return(FALSE);
}
/* FIXME - only assign if removing? */
Message->Msg.hwnd = Window->hSelf;
Message->Msg.message = Msg;
Message->Msg.lParam = MAKELONG(Message->Msg.pt.x, Message->Msg.pt.y);
/* remove the reference to the current WM_(NC)MOUSEMOVE message, if this message
is it */
if (Message->Msg.message == WM_MOUSEMOVE ||
Message->Msg.message == WM_NCMOUSEMOVE)
{
if(FromGlobalQueue)
{
/* Lock the message queue so no other thread can mess with it.
Our own message queue is not locked while fetching from the global
queue, so we have to make sure nothing interferes! */
IntLockHardwareMessageQueue(Window->MessageQueue);
if(Window->MessageQueue->MouseMoveMsg)
{
/* delete the WM_(NC)MOUSEMOVE message in the private queue, we're dealing
with one that's been sent later */
RemoveEntryList(&Window->MessageQueue->MouseMoveMsg->ListEntry);
ExFreePool(Window->MessageQueue->MouseMoveMsg);
/* our message is not in the private queue so we can remove the pointer
instead of setting it to the current message we're processing */
Window->MessageQueue->MouseMoveMsg = NULL;
}
IntUnLockHardwareMessageQueue(Window->MessageQueue);
}
else if(Window->MessageQueue->MouseMoveMsg == Message)
{
Window->MessageQueue->MouseMoveMsg = NULL;
}
}
UserDerefObject(Window);
*Freed = FALSE;
return(TRUE);
}
BOOL STDCALL
co_MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd,
UINT FilterLow, UINT FilterHigh, BOOL Remove,
PUSER_MESSAGE* Message)
{
KIRQL OldIrql;
POINT ScreenPoint;
BOOL Accept, Freed;
PLIST_ENTRY CurrentEntry;
PWINDOW_OBJECT DesktopWindow = NULL;
PVOID WaitObjects[2];
NTSTATUS WaitStatus;
DECLARE_RETURN(BOOL);
USER_REFERENCE_ENTRY Ref;
if( !IntGetScreenDC() ||
PsGetWin32Thread()->MessageQueue == W32kGetPrimitiveMessageQueue() )
{
RETURN(FALSE);
}
WaitObjects[1] = MessageQueue->NewMessages;
WaitObjects[0] = &HardwareMessageQueueLock;
do
{
UserLeaveCo();
WaitStatus = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, UserRequest,
UserMode, FALSE, NULL, NULL);
UserEnterCo();
while (co_MsqDispatchOneSentMessage(MessageQueue))
{
;
}
}
while (NT_SUCCESS(WaitStatus) && STATUS_WAIT_0 != WaitStatus);
DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
if (DesktopWindow) UserRefObjectCo(DesktopWindow, &Ref);//can DesktopWindow be NULL?
/* Process messages in the message queue itself. */
IntLockHardwareMessageQueue(MessageQueue);
CurrentEntry = MessageQueue->HardwareMessagesListHead.Flink;
while (CurrentEntry != &MessageQueue->HardwareMessagesListHead)
{
PUSER_MESSAGE Current =
CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry);
CurrentEntry = CurrentEntry->Flink;
if (Current->Msg.message >= WM_MOUSEFIRST &&
Current->Msg.message <= WM_MOUSELAST)
{
Accept = co_MsqTranslateMouseMessage(MessageQueue, hWnd, FilterLow, FilterHigh,
Current, Remove, &Freed,
DesktopWindow, &ScreenPoint, FALSE);
if (Accept)
{
if (Remove)
{
RemoveEntryList(&Current->ListEntry);
}
IntUnLockHardwareMessageQueue(MessageQueue);
IntUnLockSystemHardwareMessageQueueLock(FALSE);
*Message = Current;
RETURN(TRUE);
}
}
}
IntUnLockHardwareMessageQueue(MessageQueue);
/* Now try the global queue. */
/* Transfer all messages from the DPC accessible queue to the main queue. */
IntLockSystemMessageQueue(OldIrql);
while (SystemMessageQueueCount > 0)
{
PUSER_MESSAGE UserMsg;
MSG Msg;
BOOL ProcessMessage;
ASSERT(SystemMessageQueueHead < SYSTEM_MESSAGE_QUEUE_SIZE);
Msg = SystemMessageQueue[SystemMessageQueueHead];
SystemMessageQueueHead =
(SystemMessageQueueHead + 1) % SYSTEM_MESSAGE_QUEUE_SIZE;
SystemMessageQueueCount--;
IntUnLockSystemMessageQueue(OldIrql);
if (WM_MOUSEFIRST <= Msg.message && Msg.message <= WM_MOUSELAST)
{
MSLLHOOKSTRUCT MouseHookData;
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;
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);
}
HardwareMessageQueueStamp++;
IntUnLockSystemMessageQueue(OldIrql);
/* Process messages in the queue until we find one to return. */
CurrentEntry = HardwareMessageQueueHead.Flink;
while (CurrentEntry != &HardwareMessageQueueHead)
{
PUSER_MESSAGE Current =
CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry);
CurrentEntry = CurrentEntry->Flink;
RemoveEntryList(&Current->ListEntry);
HardwareMessageQueueStamp++;
if (Current->Msg.message >= WM_MOUSEFIRST &&
Current->Msg.message <= WM_MOUSELAST)
{
const ULONG ActiveStamp = HardwareMessageQueueStamp;
/* Translate the message. */
Accept = co_MsqTranslateMouseMessage(MessageQueue, hWnd, FilterLow, FilterHigh,
Current, Remove, &Freed,
DesktopWindow, &ScreenPoint, TRUE);
if (Accept)
{
/* Check for no more messages in the system queue. */
IntLockSystemMessageQueue(OldIrql);
if (SystemMessageQueueCount == 0 &&
IsListEmpty(&HardwareMessageQueueHead))
{
KeClearEvent(&HardwareMessageEvent);
}
IntUnLockSystemMessageQueue(OldIrql);
/*
If we aren't removing the message then add it to the private
queue.
*/
if (!Remove)
{
IntLockHardwareMessageQueue(MessageQueue);
if(Current->Msg.message == WM_MOUSEMOVE)
{
if(MessageQueue->MouseMoveMsg)
{
RemoveEntryList(&MessageQueue->MouseMoveMsg->ListEntry);
ExFreePool(MessageQueue->MouseMoveMsg);
}
MessageQueue->MouseMoveMsg = Current;
}
InsertTailList(&MessageQueue->HardwareMessagesListHead,
&Current->ListEntry);
IntUnLockHardwareMessageQueue(MessageQueue);
}
IntUnLockSystemHardwareMessageQueueLock(FALSE);
*Message = Current;
RETURN(TRUE);
}
/* If the contents of the queue changed then restart processing. */
if (HardwareMessageQueueStamp != ActiveStamp)
{
CurrentEntry = HardwareMessageQueueHead.Flink;
continue;
}
}
}
/* Check if the system message queue is now empty. */
IntLockSystemMessageQueue(OldIrql);
if (SystemMessageQueueCount == 0 && IsListEmpty(&HardwareMessageQueueHead))
{
KeClearEvent(&HardwareMessageEvent);
}
IntUnLockSystemMessageQueue(OldIrql);
IntUnLockSystemHardwareMessageQueueLock(FALSE);
RETURN(FALSE);
CLEANUP:
if (DesktopWindow) UserDerefObjectCo(DesktopWindow);
END_CLEANUP;
}
VOID FASTCALL
co_MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PUSER_MESSAGE_QUEUE FocusMessageQueue;
MSG Msg;
LARGE_INTEGER LargeTickCount;
KBDLLHOOKSTRUCT KbdHookData;
DPRINT("MsqPostKeyboardMessage(uMsg 0x%x, wParam 0x%x, lParam 0x%x)\n",
uMsg, wParam, lParam);
Msg.hwnd = 0;
Msg.message = uMsg;
Msg.wParam = wParam;
Msg.lParam = lParam;
KeQueryTickCount(&LargeTickCount);
Msg.time = LargeTickCount.u.LowPart;
/* 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. */
KbdHookData.vkCode = Msg.wParam;
KbdHookData.scanCode = (Msg.lParam >> 16) & 0xff;
KbdHookData.flags = (0 == (Msg.lParam & 0x01000000) ? 0 : LLKHF_EXTENDED) |
(0 == (Msg.lParam & 0x20000000) ? 0 : LLKHF_ALTDOWN) |
(0 == (Msg.lParam & 0x80000000) ? 0 : LLKHF_UP);
KbdHookData.time = Msg.time;
KbdHookData.dwExtraInfo = 0;
if (co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, Msg.message, (LPARAM) &KbdHookData))
{
DPRINT("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
Msg.message, Msg.wParam, Msg.lParam);
return;
}
FocusMessageQueue = IntGetFocusMessageQueue();
if( !IntGetScreenDC() )
{
/* FIXME: What to do about Msg.pt here? */
if( W32kGetPrimitiveMessageQueue() )
{
MsqPostMessage(W32kGetPrimitiveMessageQueue(), &Msg, FALSE, QS_KEY);
}
}
else
{
if (FocusMessageQueue == NULL)
{
DPRINT("No focus message queue\n");
return;
}
if (FocusMessageQueue->FocusWindow != (HWND)0)
{
Msg.hwnd = FocusMessageQueue->FocusWindow;
DPRINT("Msg.hwnd = %x\n", Msg.hwnd);
IntGetCursorLocation(FocusMessageQueue->Desktop->WindowStation,
&Msg.pt);
MsqPostMessage(FocusMessageQueue, &Msg, FALSE, QS_KEY);
}
else
{
DPRINT("Invalid focus window handle\n");
}
}
}
VOID FASTCALL
MsqPostHotKeyMessage(PVOID Thread, HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PWINDOW_OBJECT Window;
PW32THREAD Win32Thread;
PWINSTATION_OBJECT WinSta;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?