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

📄 message.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
      if(uResult)
      {
         *uResult = Result;
      }

      if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam)))
      {
         DPRINT1("Failed to unpack message parameters\n");
          RETURN( TRUE);
      }

       RETURN( TRUE);
   }

   if(uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->MessageQueue))
   {
      /* FIXME - Set a LastError? */
       RETURN( FALSE);
   }

   if(Window->Status & WINDOWSTATUS_DESTROYING)
   {
      /* FIXME - last error? */
      DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd);
       RETURN( FALSE);
   }

   Status = co_MsqSendMessage(Window->MessageQueue, hWnd, Msg, wParam, lParam,
                              uTimeout, (uFlags & SMTO_BLOCK), FALSE, uResult);


   if (STATUS_TIMEOUT == Status)
   {
      /* MSDN says GetLastError() should return 0 after timeout */
      SetLastWin32Error(0);
       RETURN( FALSE);
   }
   else if (! NT_SUCCESS(Status))
   {
      SetLastNtError(Status);
       RETURN( FALSE);
   }

   RETURN( TRUE);
   
CLEANUP:
   if (Window) UserDerefObjectCo(Window);
   END_CLEANUP;
}

LRESULT FASTCALL
co_IntSendMessageTimeout(HWND hWnd,
                         UINT Msg,
                         WPARAM wParam,
                         LPARAM lParam,
                         UINT uFlags,
                         UINT uTimeout,
                         ULONG_PTR *uResult)
{
   PWINDOW_OBJECT DesktopWindow;
   HWND *Children;
   HWND *Child;

   if (HWND_BROADCAST != hWnd)
   {
      return co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, uFlags, uTimeout, uResult);
   }

   DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
   if (NULL == DesktopWindow)
   {
      SetLastWin32Error(ERROR_INTERNAL_ERROR);
      return 0;
   }

   Children = IntWinListChildren(DesktopWindow);
   if (NULL == Children)
   {
      return 0;
   }

   for (Child = Children; NULL != *Child; Child++)
   {
      co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout, uResult);
   }

   ExFreePool(Children);

   return (LRESULT) TRUE;
}


/* This function posts a message if the destination's message queue belongs to
   another thread, otherwise it sends the message. It does not support broadcast
   messages! */
LRESULT FASTCALL
co_IntPostOrSendMessage(HWND hWnd,
                        UINT Msg,
                        WPARAM wParam,
                        LPARAM lParam)
{
   ULONG_PTR Result;
   PWINDOW_OBJECT Window;

   if(hWnd == HWND_BROADCAST)
   {
      return 0;
   }

   if(!(Window = UserGetWindowObject(hWnd)))
   {
      return 0;
   }

   if(Window->MessageQueue != PsGetCurrentThreadWin32Thread()->MessageQueue)
   {
      Result = UserPostMessage(hWnd, Msg, wParam, lParam);
   }
   else
   {
      if(!co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
      {
         Result = 0;
      }
   }

   return (LRESULT)Result;
}

LRESULT FASTCALL
co_IntDoSendMessage(HWND hWnd,
                    UINT Msg,
                    WPARAM wParam,
                    LPARAM lParam,
                    PDOSENDMESSAGE dsm,
                    PNTUSERSENDMESSAGEINFO UnsafeInfo)
{
   LRESULT Result = TRUE;
   NTSTATUS Status;
   PWINDOW_OBJECT Window;
   NTUSERSENDMESSAGEINFO Info;
   MSG UserModeMsg;
   MSG KernelModeMsg;
   PMSGMEMORY MsgMemoryEntry;

   RtlZeroMemory(&Info, sizeof(NTUSERSENDMESSAGEINFO));

   /* FIXME: Call hooks. */
   if (HWND_BROADCAST != hWnd)
   {
      Window = UserGetWindowObject(hWnd);
      if (NULL == Window)
      {
         /* Tell usermode to not touch this one */
         Info.HandledByKernel = TRUE;
         MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
         return 0;
      }
   }

   /* FIXME: Check for an exiting window. */

   /* See if the current thread can handle the message */
   if (HWND_BROADCAST != hWnd && NULL != PsGetCurrentThreadWin32Thread() &&
         Window->MessageQueue == PsGetCurrentThreadWin32Thread()->MessageQueue)
   {
      /* Gather the information usermode needs to call the window proc directly */
      Info.HandledByKernel = FALSE;

      Status = MmCopyFromCaller(&(Info.Ansi), &(UnsafeInfo->Ansi),
                                sizeof(BOOL));
      if (! NT_SUCCESS(Status))
      {
         Info.Ansi = ! Window->Unicode;
      }

      if (Window->IsSystem)
      {
          Info.Proc = (!Info.Ansi ? Window->WndProc : Window->WndProcExtra);
      }
      else
      {
          Info.Ansi = !Window->Unicode;
          Info.Proc = Window->WndProc;
      }
   }
   else
   {
      /* Must be handled by other thread */
//      if (HWND_BROADCAST != hWnd)
//      {
//         UserDerefObject(Window);
//      }
      Info.HandledByKernel = TRUE;
      UserModeMsg.hwnd = hWnd;
      UserModeMsg.message = Msg;
      UserModeMsg.wParam = wParam;
      UserModeMsg.lParam = lParam;
      MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
      Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
      if (! NT_SUCCESS(Status))
      {
         MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
         SetLastWin32Error(ERROR_INVALID_PARAMETER);
         return (dsm ? 0 : -1);
      }
      if(!dsm)
      {
         Result = co_IntSendMessage(KernelModeMsg.hwnd, KernelModeMsg.message,
                                    KernelModeMsg.wParam, KernelModeMsg.lParam);
      }
      else
      {
         Result = co_IntSendMessageTimeout(KernelModeMsg.hwnd, KernelModeMsg.message,
                                           KernelModeMsg.wParam, KernelModeMsg.lParam,
                                           dsm->uFlags, dsm->uTimeout, &dsm->Result);
      }
      Status = CopyMsgToUserMem(&UserModeMsg, &KernelModeMsg);
      if (! NT_SUCCESS(Status))
      {
         MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
         SetLastWin32Error(ERROR_INVALID_PARAMETER);
         return(dsm ? 0 : -1);
      }
   }

   Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
   if (! NT_SUCCESS(Status))
   {
      SetLastWin32Error(ERROR_INVALID_PARAMETER);
   }

   return (LRESULT)Result;
}

LRESULT STDCALL
NtUserSendMessageTimeout(HWND hWnd,
                         UINT Msg,
                         WPARAM wParam,
                         LPARAM lParam,
                         UINT uFlags,
                         UINT uTimeout,
                         ULONG_PTR *uResult,
                         PNTUSERSENDMESSAGEINFO UnsafeInfo)
{
   DOSENDMESSAGE dsm;
   LRESULT Result;
   DECLARE_RETURN(BOOL);

   DPRINT("Enter NtUserSendMessageTimeout\n");
   UserEnterExclusive();

   dsm.uFlags = uFlags;
   dsm.uTimeout = uTimeout;
   Result = co_IntDoSendMessage(hWnd, Msg, wParam, lParam, &dsm, UnsafeInfo);
   if(uResult != NULL && Result != 0)
   {
      NTSTATUS Status;

      Status = MmCopyToCaller(uResult, &dsm.Result, sizeof(ULONG_PTR));
      if(!NT_SUCCESS(Status))
      {
         SetLastWin32Error(ERROR_INVALID_PARAMETER);
         RETURN( FALSE);
      }
   }
   RETURN( Result);

CLEANUP:
   DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}

LRESULT STDCALL
NtUserSendMessage(HWND Wnd,
                  UINT Msg,
                  WPARAM wParam,
                  LPARAM lParam,
                  PNTUSERSENDMESSAGEINFO UnsafeInfo)
{
   DECLARE_RETURN(BOOL);

   DPRINT("Enter NtUserSendMessage\n");
   UserEnterExclusive();

   RETURN(co_IntDoSendMessage(Wnd, Msg, wParam, lParam, NULL, UnsafeInfo));

CLEANUP:
   DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}

BOOL STDCALL
NtUserSendMessageCallback(HWND hWnd,
                          UINT Msg,
                          WPARAM wParam,
                          LPARAM lParam,
                          SENDASYNCPROC lpCallBack,
                          ULONG_PTR dwData)
{
   UNIMPLEMENTED;

   return 0;
}


BOOL FASTCALL
UserSendNotifyMessage(HWND hWnd,
                      UINT Msg,
                      WPARAM wParam,
                      LPARAM lParam)
{
   BOOL Result = TRUE;
   // Basicly the same as IntPostOrSendMessage
   if (hWnd == HWND_BROADCAST) //Handle Broadcast
   {
      HWND *List;
      PWINDOW_OBJECT DesktopWindow;
      ULONG i;

      DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
      List = IntWinListChildren(DesktopWindow);
      
      if (List != NULL)
      {
         for (i = 0; List[i]; i++)
         {
            UserSendNotifyMessage(List[i], Msg, wParam, lParam);
         }
         ExFreePool(List);
      }
   }
   else
   {
     ULONG_PTR PResult;
     PWINDOW_OBJECT Window;
     NTSTATUS Status;
     MSG UserModeMsg;
     MSG KernelModeMsg;
     PMSGMEMORY MsgMemoryEntry;

      if(!(Window = UserGetWindowObject(hWnd))) return FALSE;

      if(Window->MessageQueue != PsGetCurrentThreadWin32Thread()->MessageQueue)
      { // Send message w/o waiting for it.
         Result = UserPostMessage(hWnd, Msg, wParam, lParam);
      }
      else
      { // Handle message and callback.
         UserModeMsg.hwnd = hWnd;
         UserModeMsg.message = Msg;
         UserModeMsg.wParam = wParam;
         UserModeMsg.lParam = lParam;
         MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
         Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
         if (! NT_SUCCESS(Status))
         {
            SetLastWin32Error(ERROR_INVALID_PARAMETER);
            return FALSE;
         }
         Result = co_IntSendMessageTimeoutSingle(
                                   KernelModeMsg.hwnd, KernelModeMsg.message,
                                   KernelModeMsg.wParam, KernelModeMsg.lParam,
                                   SMTO_NORMAL, 0, &PResult);

         Status = CopyMsgToUserMem(&UserModeMsg, &KernelModeMsg);
         if (! NT_SUCCESS(Status))
         {
            SetLastWin32Error(ERROR_INVALID_PARAMETER);
            return FALSE;
         }
      }
   }
   return Result;
}


BOOL STDCALL
NtUserSendNotifyMessage(HWND hWnd,
                        UINT Msg,
                        WPARAM wParam,
                        LPARAM lParam)
{
   DECLARE_RETURN(BOOL);

   DPRINT("EnterNtUserSendNotifyMessage\n");
   UserEnterExclusive();

   RETURN(UserSendNotifyMessage(hWnd, Msg, wParam, lParam));

CLEANUP:
   DPRINT("Leave NtUserSendNotifyMessage, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;

}


BOOL STDCALL
NtUserWaitMessage(VOID)
{
   DECLARE_RETURN(BOOL);

   DPRINT("EnterNtUserWaitMessage\n");
   UserEnterExclusive();

   RETURN(co_IntWaitMessage(NULL, 0, 0));

CLEANUP:
   DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}

DWORD STDCALL
NtUserGetQueueStatus(BOOL ClearChanges)
{
   PUSER_MESSAGE_QUEUE Queue;
   DWORD Result;
   DECLARE_RETURN(DWORD);

   DPRINT("Enter NtUserGetQueueStatus\n");
   UserEnterExclusive();

   Queue = PsGetCurrentThreadWin32Thread()->MessageQueue;

   Result = MAKELONG(Queue->QueueBits, Queue->ChangedBits);
   if (ClearChanges)
   {
      Queue->ChangedBits = 0;
   }

   RETURN( Result);

CLEANUP:
   DPRINT("Leave NtUserGetQueueStatus, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}

BOOL STDCALL
IntInitMessagePumpHook()
{
   ((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->MessagePumpHookValue++;
   return TRUE;
}

BOOL STDCALL
IntUninitMessagePumpHook()
{
   if (((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->MessagePumpHookValue <= 0)
   {
      return FALSE;
   }
   ((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->MessagePumpHookValue--;
   return TRUE;
}

/* EOF */

⌨️ 快捷键说明

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