⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msgqueue.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
                          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;
   
   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 = MsqCalculateMessageTime(&LargeTickCount);
   /* 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 (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;
   MSG Mesg;
   LARGE_INTEGER LargeTickCount;
   NTSTATUS Status;

   Status = ObReferenceObjectByPointer (Thread,
                                        THREAD_ALL_ACCESS,
                                        PsThreadType,
                                        KernelMode);
   if (!NT_SUCCESS(Status))
      return;

   Win32Thread = ((PETHREAD)Thread)->Tcb.Win32Thread;
   if (Win32Thread == NULL || Win32Thread->MessageQueue == NULL)
   {
      ObDereferenceObject ((PETHREAD)Thread);
      return;
   }

   WinSta = Win32Thread->Desktop->WindowStation;
   Window = IntGetWindowObject(hWnd);
   if (!Window)
   {
      ObDereferenceObject ((PETHREAD)Thread);
      return;
   }

   Mesg.hwnd = hWnd;
   Mesg.message = WM_HOTKEY;
   Mesg.wParam = wParam;
   Mesg.lParam = lParam;
   KeQueryTickCount(&LargeTickCount);
   Mesg.time = MsqCalculateMessageTime(&LargeTickCount);
   IntGetCursorLocation(WinSta, &Mesg.pt);
   MsqPostMessage(Window->MessageQueue, &Mesg, FALSE, QS_HOTKEY);
   ObmDereferenceObject(Window);
   ObDereferenceObject (Thread);

   //  InsertHeadList(&pThread->MessageQueue->PostedMessagesListHead,
   //   &Message->ListEntry);
   //  KeSetEvent(pThread->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
}

PUSER_MESSAGE FASTCALL
MsqCreateMessage(LPMSG Msg, BOOLEAN FreeLParam)
{
   PUSER_MESSAGE Message;

   Message = ExAllocateFromPagedLookasideList(&MessageLookasideList);
   if (!Message)
   {
      return NULL;
   }

   Message->FreeLParam = FreeLParam;
   RtlMoveMemory(&Message->Msg, Msg, sizeof(MSG));

   return Message;
}

VOID FASTCALL
MsqDestroyMessage(PUSER_MESSAGE Message)
{
   ExFreeToPagedLookasideList(&MessageLookasideList, Message);
}

VOID FASTCALL
co_MsqDispatchSentNotifyMessages(PUSER_MESSAGE_QUEUE MessageQueue)
{
   PLIST_ENTRY ListEntry;
   PUSER_SENT_MESSAGE_NOTIFY Message;

   while (!IsListEmpty(&MessageQueue->SentMessagesListHead))
   {
      ListEntry = RemoveHeadList(&MessageQueue->SentMessagesListHead);
      Message = CONTAINING_RECORD(ListEntry, USER_SENT_MESSAGE_NOTIFY,
                                  ListEntry);

      co_IntCallSentMessageCallback(Message->CompletionCallback,
                                    Message->hWnd,
                                    Message->Msg,
                                    Message->CompletionCallbackContext,
                                    Message->Result);

   }

}

BOOLEAN FASTCALL
MsqPeekSentMessages(PUSER_MESSAGE_QUEUE MessageQueue)
{
   return(!IsListEmpty(&MessageQueue->SentMessagesListHead));
}

BOOLEAN FASTCALL
co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
{
   PUSER_SENT_MESSAGE Message;
   PLIST_ENTRY Entry;
   LRESULT Result;
   BOOL SenderReturned;
   PUSER_SENT_MESSAGE_NOTIFY NotifyMessage;

   if (IsListEmpty(&MessageQueue->SentMessagesListHead))
   {
      return(FALSE);
   }

   /* remove it from the list of pending messages */
   Entry = RemoveHeadList(&MessageQueue->SentMessagesListHead);
   Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);

   /* insert it to the list of messages that are currently dispatched by this
      message queue */
   InsertTailList(&MessageQueue->LocalDispatchingMessagesHead,
                  &Message->ListEntry);

   if (Message->HookMessage)
   {
      Result = co_HOOK_CallHooks(Message->Msg.message,
                                 (INT) Message->Msg.hwnd,
                                 Message->Msg.wParam,
                                 Message->Msg.lParam);
   }
   else
   {
      /* Call the window procedure. */
      Result = co_IntSendMessage(Message->Msg.hwnd,
                                 Message->Msg.message,
                                 Message->Msg.wParam,
                                 Message->Msg.lParam);
   }

   /* remove the message from the local dispatching list, because it doesn't need
      to be cleaned up on thread termination anymore */
   RemoveEntryList(&Message->ListEntry);

   /* remove the message from the dispatching list, so lock the sender's message queue */
   SenderReturned = (Message->DispatchingListEntry.Flink == NULL);
   if(!SenderReturned)
   {
      /* only remove it from the dispatching list if not already removed by a timeout */
      RemoveEntryList(&Message->DispatchingListEntry);
   }
   /* still keep the sender's message queue locked, so the sender can't exit the
      MsqSendMessage() function (if timed out) */

   /* Let the sender know the result. */
   if (Message->Result != NULL)
   {
      *Message->Result = Result;
   }

   /* Notify the sender. */
   if (Message->CompletionEvent != NULL)
   {
      KeSetEvent(Message->CompletionEvent, IO_NO_INCREMENT, FALSE);
   }

   /* Notify the sender if they specified a callback. */
   if (!SenderReturned && Message->CompletionCallback != NULL)
   {
      if(!(NotifyMessage = ExAllocatePoolWithTag(NonPagedPool,
                           sizeof(USER_SENT_MESSAGE_NOTIFY), TAG_USRMSG)))
      {
         DPRINT1("MsqDispatchOneSentMessage(): Not enough memory to create a callback notify message\n");
         goto Notified;
      }
      NotifyMessage->CompletionCallback =
         Message->CompletionCallback;
      NotifyMessage->CompletionCallbackContext =
         Message->CompletionCallbackContext;
      NotifyMessage->Result = Result;
      NotifyMessage->hWnd = Message->Msg.hwnd;
      NotifyMessage->Msg = Message->Msg.message;
      MsqSendNotifyMessage(Message->SenderQueue, NotifyMessage);
   }

Notified:

   /* dereference both sender and our queue */
   IntDereferenceMessageQueue(MessageQueue);
   IntDereferenceMessageQueue(Message->SenderQueue);

   /* free the message */
   ExFreePool(Message);
   return(TRUE);
}

VOID STDCALL
MsqRemoveWindowMessagesFromQueue(PVOID pWindow)
{
   PUSER_SENT_MESSAGE SentMessage;
   PUSER_MESSAGE PostedMessage;
   PUSER_MESSAGE_QUEUE MessageQueue;
   PLIST_ENTRY CurrentEntry, ListHead;
   PWINDOW_OBJECT Window = pWindow;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -