2003-05-18 17:16:18 +00:00
|
|
|
/*
|
|
|
|
* ReactOS W32 Subsystem
|
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
2003-07-23 17:00:55 +00:00
|
|
|
/* $Id: message.c,v 1.23 2003/07/23 17:00:55 gvg Exp $
|
2001-06-12 17:51:51 +00:00
|
|
|
*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* PURPOSE: Messages
|
|
|
|
* FILE: subsys/win32k/ntuser/message.c
|
|
|
|
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
|
|
* REVISION HISTORY:
|
|
|
|
* 06-06-2001 CSH Created
|
|
|
|
*/
|
2002-01-13 22:52:08 +00:00
|
|
|
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
|
2001-06-12 17:51:51 +00:00
|
|
|
#include <ddk/ntddk.h>
|
|
|
|
#include <win32k/win32k.h>
|
2002-01-13 22:52:08 +00:00
|
|
|
#include <include/msgqueue.h>
|
2001-06-12 17:51:51 +00:00
|
|
|
#include <include/window.h>
|
|
|
|
#include <include/class.h>
|
|
|
|
#include <include/error.h>
|
|
|
|
#include <include/object.h>
|
|
|
|
#include <include/winsta.h>
|
2002-01-27 01:11:24 +00:00
|
|
|
#include <include/callback.h>
|
2002-07-04 19:56:38 +00:00
|
|
|
#include <include/painting.h>
|
2003-05-21 22:58:43 +00:00
|
|
|
#include <internal/safe.h>
|
2001-06-12 17:51:51 +00:00
|
|
|
|
2003-05-04 15:42:21 +00:00
|
|
|
#define NDEBUG
|
2001-06-12 17:51:51 +00:00
|
|
|
#include <debug.h>
|
|
|
|
|
2002-01-13 22:52:08 +00:00
|
|
|
/* FUNCTIONS *****************************************************************/
|
2001-06-12 17:51:51 +00:00
|
|
|
|
2003-05-18 17:16:18 +00:00
|
|
|
NTSTATUS FASTCALL
|
2002-01-13 22:52:08 +00:00
|
|
|
W32kInitMessageImpl(VOID)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2003-05-21 22:58:43 +00:00
|
|
|
return STATUS_SUCCESS;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-05-18 17:16:18 +00:00
|
|
|
NTSTATUS FASTCALL
|
2002-01-13 22:52:08 +00:00
|
|
|
W32kCleanupMessageImpl(VOID)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2003-05-21 22:58:43 +00:00
|
|
|
return STATUS_SUCCESS;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-01-13 22:52:08 +00:00
|
|
|
LRESULT STDCALL
|
2003-05-21 22:58:43 +00:00
|
|
|
NtUserDispatchMessage(CONST MSG* UnsafeMsg)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2002-01-27 01:11:24 +00:00
|
|
|
LRESULT Result;
|
2002-07-04 19:56:38 +00:00
|
|
|
PWINDOW_OBJECT WindowObject;
|
|
|
|
NTSTATUS Status;
|
2003-05-21 22:58:43 +00:00
|
|
|
MSG Msg;
|
|
|
|
|
|
|
|
Status = MmCopyFromCaller(&Msg, (PVOID) UnsafeMsg, sizeof(MSG));
|
|
|
|
if (! NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastNtError(Status);
|
|
|
|
return 0;
|
|
|
|
}
|
2002-01-27 01:11:24 +00:00
|
|
|
|
|
|
|
/* Process timer messages. */
|
2003-05-21 22:58:43 +00:00
|
|
|
if (Msg.message == WM_TIMER)
|
2002-01-27 01:11:24 +00:00
|
|
|
{
|
2003-05-21 22:58:43 +00:00
|
|
|
if (Msg.lParam)
|
2002-01-27 01:11:24 +00:00
|
|
|
{
|
|
|
|
/* FIXME: Call hooks. */
|
|
|
|
|
|
|
|
/* FIXME: Check for continuing validity of timer. */
|
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
return W32kCallWindowProc((WNDPROC)Msg.lParam,
|
|
|
|
Msg.hwnd,
|
|
|
|
Msg.message,
|
|
|
|
Msg.wParam,
|
|
|
|
0 /* GetTickCount() */);
|
2002-01-27 01:11:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-07-04 19:56:38 +00:00
|
|
|
/* Get the window object. */
|
|
|
|
Status =
|
|
|
|
ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
|
2003-05-21 22:58:43 +00:00
|
|
|
Msg.hwnd,
|
2002-07-04 19:56:38 +00:00
|
|
|
otWindow,
|
|
|
|
(PVOID*)&WindowObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2003-05-21 22:58:43 +00:00
|
|
|
SetLastNtError(Status);
|
|
|
|
return 0;
|
2002-07-04 19:56:38 +00:00
|
|
|
}
|
2002-01-27 01:11:24 +00:00
|
|
|
|
2002-07-04 19:56:38 +00:00
|
|
|
/* FIXME: Call hook procedures. */
|
|
|
|
|
|
|
|
/* Call the window procedure. */
|
2003-06-14 21:21:23 +00:00
|
|
|
Result = W32kCallWindowProc(WindowObject->WndProc,
|
2003-05-21 22:58:43 +00:00
|
|
|
Msg.hwnd,
|
|
|
|
Msg.message,
|
|
|
|
Msg.wParam,
|
|
|
|
Msg.lParam);
|
2002-01-27 01:11:24 +00:00
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
return Result;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2002-01-13 22:52:08 +00:00
|
|
|
/*
|
2003-05-21 22:58:43 +00:00
|
|
|
* Internal version of PeekMessage() doing all the work
|
2002-01-13 22:52:08 +00:00
|
|
|
*/
|
|
|
|
BOOL STDCALL
|
2003-05-21 22:58:43 +00:00
|
|
|
W32kPeekMessage(LPMSG Msg,
|
|
|
|
HWND Wnd,
|
|
|
|
UINT MsgFilterMin,
|
|
|
|
UINT MsgFilterMax,
|
|
|
|
UINT RemoveMsg)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2002-06-06 17:50:16 +00:00
|
|
|
PUSER_MESSAGE_QUEUE ThreadQueue;
|
|
|
|
BOOLEAN Present;
|
|
|
|
PUSER_MESSAGE Message;
|
|
|
|
BOOLEAN RemoveMessages;
|
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
/* The queues and order in which they are checked are documented in the MSDN
|
|
|
|
article on GetMessage() */
|
2002-06-06 17:50:16 +00:00
|
|
|
|
|
|
|
ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
|
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
/* Inspect RemoveMsg flags */
|
2002-06-06 17:50:16 +00:00
|
|
|
/* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
|
2003-05-21 22:58:43 +00:00
|
|
|
RemoveMessages = RemoveMsg & PM_REMOVE;
|
2002-06-06 17:50:16 +00:00
|
|
|
|
2003-05-10 21:47:04 +00:00
|
|
|
/* Dispatch sent messages here. */
|
2003-05-21 22:58:43 +00:00
|
|
|
while (MsqDispatchOneSentMessage(ThreadQueue))
|
|
|
|
;
|
2002-06-06 17:50:16 +00:00
|
|
|
|
|
|
|
/* Now look for a quit message. */
|
|
|
|
/* FIXME: WINE checks the message number filter here. */
|
|
|
|
if (ThreadQueue->QuitPosted)
|
|
|
|
{
|
2003-05-21 22:58:43 +00:00
|
|
|
Msg->hwnd = Wnd;
|
|
|
|
Msg->message = WM_QUIT;
|
|
|
|
Msg->wParam = ThreadQueue->QuitExitCode;
|
|
|
|
Msg->lParam = 0;
|
|
|
|
if (RemoveMessages)
|
|
|
|
{
|
|
|
|
ThreadQueue->QuitPosted = FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
2002-06-06 17:50:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Now check for normal messages. */
|
|
|
|
Present = MsqFindMessage(ThreadQueue,
|
2003-05-21 22:58:43 +00:00
|
|
|
FALSE,
|
|
|
|
RemoveMessages,
|
|
|
|
Wnd,
|
|
|
|
MsgFilterMin,
|
|
|
|
MsgFilterMax,
|
|
|
|
&Message);
|
2002-06-06 17:50:16 +00:00
|
|
|
if (Present)
|
2003-05-21 22:58:43 +00:00
|
|
|
{
|
|
|
|
RtlCopyMemory(Msg, &Message->Msg, sizeof(MSG));
|
|
|
|
if (RemoveMessages)
|
|
|
|
{
|
2002-06-06 17:50:16 +00:00
|
|
|
ExFreePool(Message);
|
2003-05-21 22:58:43 +00:00
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
2002-06-06 17:50:16 +00:00
|
|
|
|
|
|
|
/* Check for hardware events. */
|
|
|
|
Present = MsqFindMessage(ThreadQueue,
|
2003-05-21 22:58:43 +00:00
|
|
|
TRUE,
|
|
|
|
RemoveMessages,
|
|
|
|
Wnd,
|
|
|
|
MsgFilterMin,
|
|
|
|
MsgFilterMax,
|
|
|
|
&Message);
|
2002-06-06 17:50:16 +00:00
|
|
|
if (Present)
|
2003-05-21 22:58:43 +00:00
|
|
|
{
|
|
|
|
RtlCopyMemory(Msg, &Message->Msg, sizeof(MSG));
|
|
|
|
if (RemoveMessages)
|
|
|
|
{
|
2002-06-06 17:50:16 +00:00
|
|
|
ExFreePool(Message);
|
2003-05-21 22:58:43 +00:00
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
2002-06-06 17:50:16 +00:00
|
|
|
|
2003-05-10 21:47:04 +00:00
|
|
|
/* Check for sent messages again. */
|
2003-05-21 22:58:43 +00:00
|
|
|
while (MsqDispatchOneSentMessage(ThreadQueue))
|
|
|
|
;
|
2003-05-18 06:47:19 +00:00
|
|
|
|
|
|
|
/* Check for paint messages. */
|
|
|
|
if (ThreadQueue->PaintPosted)
|
|
|
|
{
|
|
|
|
PWINDOW_OBJECT WindowObject;
|
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
Msg->hwnd = PaintingFindWinToRepaint(Wnd, PsGetWin32Thread());
|
|
|
|
Msg->message = WM_PAINT;
|
|
|
|
Msg->wParam = Msg->lParam = 0;
|
2003-05-18 06:47:19 +00:00
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
WindowObject = W32kGetWindowObject(Msg->hwnd);
|
2003-05-18 06:47:19 +00:00
|
|
|
if (WindowObject != NULL)
|
|
|
|
{
|
|
|
|
if (WindowObject->Style & WS_MINIMIZE &&
|
2003-05-21 22:58:43 +00:00
|
|
|
(HICON)NtUserGetClassLong(Msg->hwnd, GCL_HICON) != NULL)
|
2003-05-18 06:47:19 +00:00
|
|
|
{
|
2003-05-21 22:58:43 +00:00
|
|
|
Msg->message = WM_PAINTICON;
|
|
|
|
Msg->wParam = 1;
|
2003-05-18 06:47:19 +00:00
|
|
|
}
|
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
if (Msg->hwnd == NULL || Msg->hwnd == Wnd ||
|
|
|
|
W32kIsChildWindow(Wnd, Msg->hwnd))
|
2003-05-18 06:47:19 +00:00
|
|
|
{
|
|
|
|
if (WindowObject->Flags & WINDOWOBJECT_NEED_INTERNALPAINT &&
|
|
|
|
WindowObject->UpdateRegion == NULL)
|
|
|
|
{
|
|
|
|
WindowObject->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
|
2003-05-21 22:58:43 +00:00
|
|
|
if (RemoveMessages)
|
|
|
|
{
|
|
|
|
MsqDecPaintCountQueue(WindowObject->MessageQueue);
|
|
|
|
}
|
2003-05-18 06:47:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
W32kReleaseWindowObject(WindowObject);
|
|
|
|
}
|
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL STDCALL
|
|
|
|
NtUserPeekMessage(LPMSG UnsafeMsg,
|
|
|
|
HWND Wnd,
|
|
|
|
UINT MsgFilterMin,
|
|
|
|
UINT MsgFilterMax,
|
|
|
|
UINT RemoveMsg)
|
|
|
|
{
|
|
|
|
MSG SafeMsg;
|
|
|
|
NTSTATUS Status;
|
|
|
|
BOOL Present;
|
|
|
|
PWINDOW_OBJECT Window;
|
|
|
|
|
|
|
|
/* Validate input */
|
|
|
|
if (NULL != Wnd)
|
|
|
|
{
|
|
|
|
Status = ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
|
|
|
|
Wnd, otWindow, (PVOID*)&Window);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Wnd = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ObmDereferenceObject(Window);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (MsgFilterMax < MsgFilterMin)
|
|
|
|
{
|
|
|
|
MsgFilterMin = 0;
|
|
|
|
MsgFilterMax = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Present = W32kPeekMessage(&SafeMsg, Wnd, MsgFilterMin, MsgFilterMax, RemoveMsg);
|
|
|
|
if (Present)
|
|
|
|
{
|
|
|
|
Status = MmCopyToCaller(UnsafeMsg, &SafeMsg, sizeof(MSG));
|
|
|
|
if (! NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* There is error return documented for PeekMessage().
|
|
|
|
Do the best we can */
|
|
|
|
SetLastNtError(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2003-05-18 06:47:19 +00:00
|
|
|
}
|
2002-06-06 17:50:16 +00:00
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
return Present;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL STDCALL
|
|
|
|
W32kWaitMessage(HWND Wnd,
|
|
|
|
UINT MsgFilterMin,
|
|
|
|
UINT MsgFilterMax)
|
|
|
|
{
|
|
|
|
PUSER_MESSAGE_QUEUE ThreadQueue;
|
|
|
|
NTSTATUS Status;
|
|
|
|
MSG Msg;
|
|
|
|
|
|
|
|
ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (W32kPeekMessage(&Msg, Wnd, MsgFilterMin, MsgFilterMax, PM_NOREMOVE))
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Nothing found. Wait for new messages. */
|
|
|
|
Status = MsqWaitForNewMessages(ThreadQueue);
|
|
|
|
}
|
|
|
|
while (STATUS_WAIT_0 <= STATUS_WAIT_0 && Status <= STATUS_WAIT_63);
|
|
|
|
|
|
|
|
SetLastNtError(Status);
|
|
|
|
|
2003-05-10 21:47:04 +00:00
|
|
|
return FALSE;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
BOOL STDCALL
|
|
|
|
NtUserGetMessage(LPMSG UnsafeMsg,
|
|
|
|
HWND Wnd,
|
|
|
|
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;
|
|
|
|
MSG SafeMsg;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PWINDOW_OBJECT Window;
|
|
|
|
|
|
|
|
/* Validate input */
|
|
|
|
if (NULL != Wnd)
|
|
|
|
{
|
|
|
|
Status = ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
|
|
|
|
Wnd, otWindow, (PVOID*)&Window);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
Wnd = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ObmDereferenceObject(Window);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (MsgFilterMax < MsgFilterMin)
|
|
|
|
{
|
|
|
|
MsgFilterMin = 0;
|
|
|
|
MsgFilterMax = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
GotMessage = W32kPeekMessage(&SafeMsg, Wnd, MsgFilterMin, MsgFilterMax, PM_REMOVE);
|
|
|
|
if (GotMessage)
|
|
|
|
{
|
|
|
|
Status = MmCopyToCaller(UnsafeMsg, &SafeMsg, sizeof(MSG));
|
|
|
|
if (! NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastNtError(Status);
|
|
|
|
return (BOOL) -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
W32kWaitMessage(Wnd, MsgFilterMin, MsgFilterMax);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (! GotMessage);
|
|
|
|
|
|
|
|
return WM_QUIT != SafeMsg.message;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
|
|
STDCALL
|
|
|
|
NtUserMessageCall(
|
|
|
|
DWORD Unknown0,
|
|
|
|
DWORD Unknown1,
|
|
|
|
DWORD Unknown2,
|
|
|
|
DWORD Unknown3,
|
|
|
|
DWORD Unknown4,
|
|
|
|
DWORD Unknown5,
|
|
|
|
DWORD Unknown6)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-01-13 22:52:08 +00:00
|
|
|
BOOL STDCALL
|
|
|
|
NtUserPostMessage(HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2003-05-21 22:58:43 +00:00
|
|
|
PWINDOW_OBJECT Window;
|
|
|
|
MSG Mesg;
|
|
|
|
PUSER_MESSAGE Message;
|
|
|
|
NTSTATUS Status;
|
2003-03-06 23:57:03 +00:00
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
if (WM_QUIT == Msg)
|
|
|
|
{
|
|
|
|
MsqPostQuitMessage(PsGetWin32Thread()->MessageQueue, wParam);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Status = ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
|
|
|
|
hWnd, otWindow, (PVOID*)&Window);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastNtError(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
Mesg.hwnd = hWnd;
|
|
|
|
Mesg.message = Msg;
|
|
|
|
Mesg.wParam = wParam;
|
|
|
|
Mesg.lParam = lParam;
|
|
|
|
Message = MsqCreateMessage(&Mesg);
|
|
|
|
MsqPostMessage(Window->MessageQueue, Message);
|
|
|
|
ObmDereferenceObject(Window);
|
|
|
|
}
|
2003-03-06 23:57:03 +00:00
|
|
|
|
2003-05-11 10:47:33 +00:00
|
|
|
return TRUE;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2002-01-13 22:52:08 +00:00
|
|
|
BOOL STDCALL
|
|
|
|
NtUserPostThreadMessage(DWORD idThread,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2003-07-23 17:00:55 +00:00
|
|
|
MSG Mesg;
|
|
|
|
|
|
|
|
PUSER_MESSAGE Message;
|
|
|
|
PETHREAD peThread;
|
|
|
|
PW32THREAD pThread;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
Status = PsLookupThreadByThreadId(idThread,&peThread);
|
|
|
|
|
|
|
|
if( Status == STATUS_SUCCESS ) {
|
|
|
|
pThread = peThread->Win32Thread;
|
|
|
|
Mesg.hwnd = 0;
|
|
|
|
Mesg.message = Msg;
|
|
|
|
Mesg.wParam = wParam;
|
|
|
|
Mesg.lParam = lParam;
|
|
|
|
Message = MsqCreateMessage(&Mesg);
|
|
|
|
MsqPostMessage(pThread->MessageQueue, Message);
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
SetLastNtError( Status );
|
|
|
|
return FALSE;
|
|
|
|
}
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2002-01-13 22:52:08 +00:00
|
|
|
DWORD STDCALL
|
|
|
|
NtUserQuerySendMessage(DWORD Unknown0)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2002-01-13 22:52:08 +00:00
|
|
|
UNIMPLEMENTED;
|
2001-06-12 17:51:51 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-07-04 19:56:38 +00:00
|
|
|
LRESULT STDCALL
|
2002-07-17 21:04:57 +00:00
|
|
|
W32kSendMessage(HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam,
|
|
|
|
BOOL KernelMessage)
|
2002-05-06 22:20:32 +00:00
|
|
|
{
|
2002-07-04 19:56:38 +00:00
|
|
|
LRESULT Result;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PWINDOW_OBJECT Window;
|
|
|
|
|
|
|
|
/* FIXME: Check for a broadcast or topmost destination. */
|
|
|
|
|
|
|
|
/* FIXME: Call hooks. */
|
|
|
|
|
|
|
|
Status =
|
|
|
|
ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
|
|
|
|
hWnd,
|
|
|
|
otWindow,
|
|
|
|
(PVOID*)&Window);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2003-05-21 22:58:43 +00:00
|
|
|
return 0;
|
2002-07-04 19:56:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: Check for an exiting window. */
|
|
|
|
|
2003-05-04 15:42:21 +00:00
|
|
|
if (NULL != PsGetWin32Thread() &&
|
|
|
|
Window->MessageQueue == PsGetWin32Thread()->MessageQueue)
|
2002-07-04 19:56:38 +00:00
|
|
|
{
|
2002-07-17 21:04:57 +00:00
|
|
|
if (KernelMessage)
|
|
|
|
{
|
|
|
|
Result = W32kCallTrampolineWindowProc(NULL, hWnd, Msg, wParam,
|
|
|
|
lParam);
|
2003-05-21 22:58:43 +00:00
|
|
|
return Result;
|
2002-07-17 21:04:57 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-06-14 21:21:23 +00:00
|
|
|
Result = W32kCallWindowProc(Window->WndProc, hWnd, Msg, wParam, lParam);
|
2003-05-21 22:58:43 +00:00
|
|
|
return Result;
|
2002-07-17 21:04:57 +00:00
|
|
|
}
|
2002-07-04 19:56:38 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PUSER_SENT_MESSAGE Message;
|
|
|
|
PKEVENT CompletionEvent;
|
2003-05-10 21:47:04 +00:00
|
|
|
|
2002-07-04 19:56:38 +00:00
|
|
|
CompletionEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
|
|
|
|
KeInitializeEvent(CompletionEvent, NotificationEvent, FALSE);
|
|
|
|
|
|
|
|
Message = ExAllocatePool(NonPagedPool, sizeof(USER_SENT_MESSAGE));
|
|
|
|
Message->Msg.hwnd = hWnd;
|
|
|
|
Message->Msg.message = Msg;
|
|
|
|
Message->Msg.wParam = wParam;
|
|
|
|
Message->Msg.lParam = lParam;
|
|
|
|
Message->CompletionEvent = CompletionEvent;
|
|
|
|
Message->Result = &Result;
|
|
|
|
Message->CompletionQueue = NULL;
|
|
|
|
Message->CompletionCallback = NULL;
|
|
|
|
MsqSendMessage(Window->MessageQueue, Message);
|
|
|
|
|
|
|
|
ObmDereferenceObject(Window);
|
|
|
|
Status = KeWaitForSingleObject(CompletionEvent,
|
|
|
|
UserRequest,
|
|
|
|
UserMode,
|
|
|
|
FALSE,
|
|
|
|
NULL);
|
|
|
|
if (Status == STATUS_WAIT_0)
|
|
|
|
{
|
2003-05-21 22:58:43 +00:00
|
|
|
return Result;
|
2002-07-04 19:56:38 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-05-21 22:58:43 +00:00
|
|
|
return FALSE;
|
2002-07-04 19:56:38 +00:00
|
|
|
}
|
|
|
|
}
|
2002-05-06 22:20:32 +00:00
|
|
|
}
|
|
|
|
|
2002-07-17 21:04:57 +00:00
|
|
|
LRESULT STDCALL
|
2003-05-21 22:58:43 +00:00
|
|
|
NtUserSendMessage(HWND Wnd,
|
2002-07-17 21:04:57 +00:00
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
2003-05-21 22:58:43 +00:00
|
|
|
return W32kSendMessage(Wnd, Msg, wParam, lParam, FALSE);
|
2002-07-17 21:04:57 +00:00
|
|
|
}
|
|
|
|
|
2002-01-13 22:52:08 +00:00
|
|
|
BOOL STDCALL
|
|
|
|
NtUserSendMessageCallback(HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam,
|
|
|
|
SENDASYNCPROC lpCallBack,
|
|
|
|
ULONG_PTR dwData)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2003-05-11 12:29:41 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
return 0;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2002-01-13 22:52:08 +00:00
|
|
|
BOOL STDCALL
|
|
|
|
NtUserSendNotifyMessage(HWND hWnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam)
|
2001-06-12 17:51:51 +00:00
|
|
|
{
|
2002-01-13 22:52:08 +00:00
|
|
|
UNIMPLEMENTED;
|
2001-06-12 17:51:51 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-01-13 22:52:08 +00:00
|
|
|
BOOL STDCALL
|
2001-06-12 17:51:51 +00:00
|
|
|
NtUserWaitMessage(VOID)
|
|
|
|
{
|
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
return W32kWaitMessage(NULL, 0, 0);
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|