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

📄 message.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
            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 + -