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

📄 message.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
         return TRUE;
      }

      /* Nothing found. Wait for new messages. */
      Status = co_MsqWaitForNewMessages(ThreadQueue, Wnd, MsgFilterMin, MsgFilterMax);
   }
   while ((STATUS_WAIT_0 <= Status && Status <= STATUS_WAIT_63) || STATUS_TIMEOUT == Status);

   SetLastNtError(Status);

   return FALSE;
}

BOOL STDCALL
NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
                 HWND hWnd,
                 UINT MsgFilterMin,
                 UINT MsgFilterMax)
/*
 * FUNCTION: Get a message from the calling thread's message queue.
 * ARGUMENTS:
 *      UnsafeMsg - Pointer to the structure which receives the returned message.
 *      Wnd - Window whose messages are to be retrieved.
 *      MsgFilterMin - Integer value of the lowest message value to be
 *                     retrieved.
 *      MsgFilterMax - Integer value of the highest message value to be
 *                     retrieved.
 */
{
   BOOL GotMessage;
   NTUSERGETMESSAGEINFO Info;
   NTSTATUS Status;
   PWINDOW_OBJECT Window = NULL;
   PMSGMEMORY MsgMemoryEntry;
   PVOID UserMem;
   UINT Size;
   USER_MESSAGE Msg;
   DECLARE_RETURN(BOOL);
//   USER_REFERENCE_ENTRY Ref;

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

   /* Validate input */
   if (hWnd && !(Window = UserGetWindowObject(hWnd)))
   {
      RETURN(-1);
   }
   
//   if (Window) UserRefObjectCo(Window, &Ref);
   
   if (MsgFilterMax < MsgFilterMin)
   {
      MsgFilterMin = 0;
      MsgFilterMax = 0;
   }

   do
   {
      GotMessage = co_IntPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE);
      if (GotMessage)
      {
         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 (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);
         }
      }
      else if (! co_IntWaitMessage(hWnd, MsgFilterMin, MsgFilterMax))
      {
         RETURN( (BOOL) -1);
      }
   }
   while (! GotMessage);

   RETURN( WM_QUIT != Info.Msg.message);

CLEANUP:
//   if (Window) UserDerefObjectCo(Window);

   DPRINT("Leave NtUserGetMessage\n");
   UserLeave();
   END_CLEANUP;
}

DWORD
STDCALL
NtUserMessageCall(
   DWORD Unknown0,
   DWORD Unknown1,
   DWORD Unknown2,
   DWORD Unknown3,
   DWORD Unknown4,
   DWORD Unknown5,
   DWORD Unknown6)
{
   UNIMPLEMENTED

   return 0;
}

static NTSTATUS FASTCALL
CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEntry)
{
   NTSTATUS Status;

   PVOID KernelMem;
   UINT Size;

   *KernelModeMsg = *UserModeMsg;

   /* See if this message type is present in the table */
   if (NULL == MsgMemoryEntry)
   {
      /* Not present, no copying needed */
      return STATUS_SUCCESS;
   }

   /* Determine required size */
   Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);

   if (0 != Size)
   {
      /* Allocate kernel mem */
      KernelMem = ExAllocatePoolWithTag(PagedPool, Size, TAG_MSG);
      if (NULL == KernelMem)
      {
         DPRINT1("Not enough memory to copy message to kernel mem\n");
         return STATUS_NO_MEMORY;
      }
      KernelModeMsg->lParam = (LPARAM) KernelMem;

      /* Copy data if required */
      if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_READ))
      {
         Status = MmCopyFromCaller(KernelMem, (PVOID) UserModeMsg->lParam, Size);
         if (! NT_SUCCESS(Status))
         {
            DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
            ExFreePool(KernelMem);
            return Status;
         }
      }
      else
      {
         /* Make sure we don't pass any secrets to usermode */
         RtlZeroMemory(KernelMem, Size);
      }
   }
   else
   {
      KernelModeMsg->lParam = 0;
   }

   return STATUS_SUCCESS;
}

static NTSTATUS FASTCALL
CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
{
   NTSTATUS Status;
   PMSGMEMORY MsgMemoryEntry;
   UINT Size;

   /* See if this message type is present in the table */
   MsgMemoryEntry = FindMsgMemory(UserModeMsg->message);
   if (NULL == MsgMemoryEntry)
   {
      /* Not present, no copying needed */
      return STATUS_SUCCESS;
   }

   /* Determine required size */
   Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);

   if (0 != Size)
   {
      /* Copy data if required */
      if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_WRITE))
      {
         Status = MmCopyToCaller((PVOID) UserModeMsg->lParam, (PVOID) KernelModeMsg->lParam, Size);
         if (! NT_SUCCESS(Status))
         {
            DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
            ExFreePool((PVOID) KernelModeMsg->lParam);
            return Status;
         }
      }

      ExFreePool((PVOID) KernelModeMsg->lParam);
   }

   return STATUS_SUCCESS;
}

BOOL FASTCALL
UserPostMessage(HWND Wnd,
                UINT Msg,
                WPARAM wParam,
                LPARAM lParam)
{
   MSG UserModeMsg, KernelModeMsg;
   LARGE_INTEGER LargeTickCount;
   NTSTATUS Status;
   PMSGMEMORY MsgMemoryEntry;

   if (WM_QUIT == Msg)
   {
      MsqPostQuitMessage(PsGetCurrentThreadWin32Thread()->MessageQueue, wParam);
   }
   else if (Wnd == HWND_BROADCAST)
   {
      HWND *List;
      PWINDOW_OBJECT DesktopWindow;
      ULONG i;

      DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
      List = IntWinListChildren(DesktopWindow);
      
      if (List != NULL)
      {
         for (i = 0; List[i]; i++)
            UserPostMessage(List[i], Msg, wParam, lParam);
         ExFreePool(List);
      }
   }
   else
   {
      PWINDOW_OBJECT Window;
      
      Window = UserGetWindowObject(Wnd);
      if (NULL == Window)
      {
         return FALSE;
      }
      if(Window->Status & WINDOWSTATUS_DESTROYING)
      {
         DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd);
         /* FIXME - last error code? */
         return FALSE;
      }

      UserModeMsg.hwnd = Wnd;
      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;
      }
      IntGetCursorLocation(PsGetCurrentThreadWin32Thread()->Desktop->WindowStation,
                           &KernelModeMsg.pt);
      KeQueryTickCount(&LargeTickCount);
      KernelModeMsg.time = MsqCalculateMessageTime(&LargeTickCount);
      MsqPostMessage(Window->MessageQueue, &KernelModeMsg,
                     NULL != MsgMemoryEntry && 0 != KernelModeMsg.lParam,
                     QS_POSTMESSAGE);
   }

   return TRUE;
}


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

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

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

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



BOOL STDCALL
NtUserPostThreadMessage(DWORD idThread,
                        UINT Msg,
                        WPARAM wParam,
                        LPARAM lParam)
{
   MSG UserModeMsg, KernelModeMsg;
   PETHREAD peThread;
   PW32THREAD pThread;
   NTSTATUS Status;
   PMSGMEMORY MsgMemoryEntry;
   DECLARE_RETURN(BOOL);

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

   Status = PsLookupThreadByThreadId((HANDLE)idThread,&peThread);

   if( Status == STATUS_SUCCESS )
   {
      pThread = (PW32THREAD)peThread->Tcb.Win32Thread;
      if( !pThread || !pThread->MessageQueue )
      {
         ObDereferenceObject( peThread );
         RETURN( FALSE);
      }

      UserModeMsg.hwnd = NULL;
      UserModeMsg.message = Msg;
      UserModeMsg.wParam = wParam;
      UserModeMsg.lParam = lParam;
      MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
      Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
      if (! NT_SUCCESS(Status))
      {
         ObDereferenceObject( peThread );
         SetLastWin32Error(ERROR_INVALID_PARAMETER);
         RETURN( FALSE);
      }
      MsqPostMessage(pThread->MessageQueue, &KernelModeMsg,
                     NULL != MsgMemoryEntry && 0 != KernelModeMsg.lParam,
                     QS_POSTMESSAGE);
      ObDereferenceObject( peThread );
      RETURN( TRUE);
   }
   else
   {
      SetLastNtError( Status );
      RETURN( FALSE);
   }

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

DWORD STDCALL
NtUserQuerySendMessage(DWORD Unknown0)
{
   UNIMPLEMENTED;

   return 0;
}

LRESULT FASTCALL
co_IntSendMessage(HWND hWnd,
                  UINT Msg,
                  WPARAM wParam,
                  LPARAM lParam)
{
   ULONG_PTR Result = 0;
   if(co_IntSendMessageTimeout(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
   {
      return (LRESULT)Result;
   }
   return 0;
}

static 
LRESULT FASTCALL
co_IntSendMessageTimeoutSingle(HWND hWnd,
                               UINT Msg,
                               WPARAM wParam,
                               LPARAM lParam,
                               UINT uFlags,
                               UINT uTimeout,
                               ULONG_PTR *uResult)
{
   ULONG_PTR Result;
   NTSTATUS Status;
   PWINDOW_OBJECT Window = NULL;
   PMSGMEMORY MsgMemoryEntry;
   INT lParamBufferSize;
   LPARAM lParamPacked;
   PW32THREAD Win32Thread;
   DECLARE_RETURN(LRESULT);
   USER_REFERENCE_ENTRY Ref;

   /* FIXME: Call hooks. */
   if (!(Window = UserGetWindowObject(hWnd)))
   {
       RETURN( FALSE);
   }
   
   UserRefObjectCo(Window, &Ref);

   Win32Thread = PsGetCurrentThreadWin32Thread();

   if (NULL != Win32Thread &&
         Window->MessageQueue == Win32Thread->MessageQueue)
   {
      if (Win32Thread->IsExiting)
      {
         /* Never send messages to exiting threads */
          RETURN( FALSE);
      }

      /* See if this message type is present in the table */
      MsgMemoryEntry = FindMsgMemory(Msg);
      if (NULL == MsgMemoryEntry)
      {
         lParamBufferSize = -1;
      }
      else
      {
         lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
      }

      if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam)))
      {
         DPRINT1("Failed to pack message parameters\n");
          RETURN( FALSE);
      }

      Result = (ULONG_PTR)co_IntCallWindowProc(Window->WndProc, !Window->Unicode, hWnd, Msg, wParam,
               lParamPacked,lParamBufferSize);

⌨️ 快捷键说明

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