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-12-20 21:45:14 +00:00
|
|
|
/* $Id: message.c,v 1.39 2003/12/20 21:45:14 weiden 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-10-09 06:13:05 +00:00
|
|
|
#include <include/input.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
|
2003-08-19 11:48:50 +00:00
|
|
|
IntInitMessageImpl(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
|
2003-08-19 11:48:50 +00:00
|
|
|
IntCleanupMessageImpl(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-08-19 11:48:50 +00:00
|
|
|
return IntCallWindowProc((WNDPROC)Msg.lParam,
|
2003-05-21 22:58:43 +00:00
|
|
|
Msg.hwnd,
|
|
|
|
Msg.message,
|
|
|
|
Msg.wParam,
|
|
|
|
0 /* GetTickCount() */);
|
2002-01-27 01:11:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-09 06:13:05 +00:00
|
|
|
if( Msg.hwnd == 0 ) return 0;
|
|
|
|
|
2002-07-04 19:56:38 +00:00
|
|
|
/* Get the window object. */
|
2003-11-23 12:41:42 +00:00
|
|
|
WindowObject = IntGetWindowObject(Msg.hwnd);
|
|
|
|
if(!WindowObject)
|
2002-07-04 19:56:38 +00:00
|
|
|
{
|
2003-11-23 12:41:42 +00:00
|
|
|
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
2003-05-21 22:58:43 +00:00
|
|
|
return 0;
|
2002-07-04 19:56:38 +00:00
|
|
|
}
|
2003-12-14 23:52:54 +00:00
|
|
|
if(WindowObject->OwnerThread != PsGetCurrentThread())
|
|
|
|
{
|
|
|
|
IntReleaseWindowObject(WindowObject);
|
|
|
|
DPRINT1("Window doesn't belong to the calling thread!\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2002-07-04 19:56:38 +00:00
|
|
|
/* FIXME: Call hook procedures. */
|
|
|
|
|
|
|
|
/* Call the window procedure. */
|
2003-08-19 11:48:50 +00:00
|
|
|
Result = IntCallWindowProc(WindowObject->WndProcW,
|
2003-08-05 15:41:03 +00:00
|
|
|
Msg.hwnd,
|
|
|
|
Msg.message,
|
|
|
|
Msg.wParam,
|
|
|
|
Msg.lParam);
|
2003-11-23 12:41:42 +00:00
|
|
|
|
|
|
|
IntReleaseWindowObject(WindowObject);
|
|
|
|
|
2003-05-21 22:58:43 +00:00
|
|
|
return Result;
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-12-20 21:45:14 +00:00
|
|
|
VOID FASTCALL
|
|
|
|
IntSendSpecialMessages(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg)
|
|
|
|
{
|
|
|
|
if(!Msg->hwnd || ThreadQueue->CaptureWindow)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(Msg->message)
|
|
|
|
{
|
|
|
|
case WM_MOUSEMOVE:
|
|
|
|
{
|
|
|
|
IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(HTCLIENT, Msg->message), TRUE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_NCMOUSEMOVE:
|
|
|
|
{
|
|
|
|
IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(Msg->wParam, Msg->message), TRUE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
case WM_RBUTTONDOWN:
|
|
|
|
case WM_XBUTTONDOWN:
|
|
|
|
case WM_LBUTTONDBLCLK:
|
|
|
|
case WM_MBUTTONDBLCLK:
|
|
|
|
case WM_RBUTTONDBLCLK:
|
|
|
|
case WM_XBUTTONDBLCLK:
|
|
|
|
{
|
|
|
|
WPARAM wParam;
|
|
|
|
|
|
|
|
if(!IntGetWindowStationObject(InputWindowStation))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
wParam = (WPARAM)InputWindowStation->SystemCursor.ButtonsDown;
|
|
|
|
ObDereferenceObject(InputWindowStation);
|
|
|
|
|
|
|
|
IntSendMessage(Msg->hwnd, WM_MOUSEMOVE, wParam, Msg->lParam, TRUE);
|
|
|
|
IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(HTCLIENT, Msg->message), TRUE);
|
|
|
|
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:
|
|
|
|
{
|
|
|
|
IntSendMessage(Msg->hwnd, WM_NCMOUSEMOVE, (WPARAM)Msg->wParam, Msg->lParam, TRUE);
|
|
|
|
IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(Msg->wParam, Msg->message), TRUE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-08-19 11:48:50 +00:00
|
|
|
IntPeekMessage(LPMSG Msg,
|
2003-05-21 22:58:43 +00:00
|
|
|
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)
|
|
|
|
{
|
2003-07-25 23:53:36 +00:00
|
|
|
MsqDestroyMessage(Message);
|
2003-12-20 21:45:14 +00:00
|
|
|
IntSendSpecialMessages(ThreadQueue, Msg);
|
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)
|
|
|
|
{
|
2003-07-25 23:53:36 +00:00
|
|
|
MsqDestroyMessage(Message);
|
2003-12-20 21:45:14 +00:00
|
|
|
IntSendSpecialMessages(ThreadQueue, Msg);
|
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. */
|
2003-11-21 17:01:16 +00:00
|
|
|
if (IntGetPaintMessage(Wnd, PsGetWin32Thread(), Msg, RemoveMessages))
|
2003-05-18 06:47:19 +00:00
|
|
|
{
|
2003-11-21 17:01:16 +00:00
|
|
|
return TRUE;
|
2003-05-21 22:58:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2003-11-23 12:41:42 +00:00
|
|
|
Window = IntGetWindowObject(Wnd);
|
|
|
|
if(!Window)
|
|
|
|
Wnd = NULL;
|
2003-05-21 22:58:43 +00:00
|
|
|
else
|
2003-11-23 12:41:42 +00:00
|
|
|
IntReleaseWindowObject(Window);
|
2003-05-21 22:58:43 +00:00
|
|
|
}
|
|
|
|
if (MsgFilterMax < MsgFilterMin)
|
|
|
|
{
|
|
|
|
MsgFilterMin = 0;
|
|
|
|
MsgFilterMax = 0;
|
|
|
|
}
|
|
|
|
|
2003-08-19 11:48:50 +00:00
|
|
|
Present = IntPeekMessage(&SafeMsg, Wnd, MsgFilterMin, MsgFilterMax, RemoveMsg);
|
2003-05-21 22:58:43 +00:00
|
|
|
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
|
2003-08-19 11:48:50 +00:00
|
|
|
IntWaitMessage(HWND Wnd,
|
2003-05-21 22:58:43 +00:00
|
|
|
UINT MsgFilterMin,
|
|
|
|
UINT MsgFilterMax)
|
|
|
|
{
|
|
|
|
PUSER_MESSAGE_QUEUE ThreadQueue;
|
|
|
|
NTSTATUS Status;
|
|
|
|
MSG Msg;
|
|
|
|
|
|
|
|
ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2003-08-19 11:48:50 +00:00
|
|
|
if (IntPeekMessage(&Msg, Wnd, MsgFilterMin, MsgFilterMax, PM_NOREMOVE))
|
2003-05-21 22:58:43 +00:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2003-11-23 12:41:42 +00:00
|
|
|
Window = IntGetWindowObject(Wnd);
|
|
|
|
if(!Window)
|
|
|
|
Wnd = NULL;
|
2003-05-21 22:58:43 +00:00
|
|
|
else
|
2003-11-23 12:41:42 +00:00
|
|
|
IntReleaseWindowObject(Window);
|
2003-05-21 22:58:43 +00:00
|
|
|
}
|
|
|
|
if (MsgFilterMax < MsgFilterMin)
|
|
|
|
{
|
|
|
|
MsgFilterMin = 0;
|
|
|
|
MsgFilterMax = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2003-08-19 11:48:50 +00:00
|
|
|
GotMessage = IntPeekMessage(&SafeMsg, Wnd, MsgFilterMin, MsgFilterMax, PM_REMOVE);
|
2003-05-21 22:58:43 +00:00
|
|
|
if (GotMessage)
|
|
|
|
{
|
|
|
|
Status = MmCopyToCaller(UnsafeMsg, &SafeMsg, sizeof(MSG));
|
|
|
|
if (! NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastNtError(Status);
|
|
|
|
return (BOOL) -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-08-19 11:48:50 +00:00
|
|
|
IntWaitMessage(Wnd, MsgFilterMin, MsgFilterMax);
|
2003-05-21 22:58:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
2003-09-27 15:41:54 +00:00
|
|
|
LARGE_INTEGER LargeTickCount;
|
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
|
|
|
|
{
|
2003-11-23 12:41:42 +00:00
|
|
|
Window = IntGetWindowObject(hWnd);
|
|
|
|
if (!Window)
|
2003-05-21 22:58:43 +00:00
|
|
|
{
|
2003-11-23 12:41:42 +00:00
|
|
|
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
2003-05-21 22:58:43 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
Mesg.hwnd = hWnd;
|
|
|
|
Mesg.message = Msg;
|
|
|
|
Mesg.wParam = wParam;
|
|
|
|
Mesg.lParam = lParam;
|
2003-09-27 15:41:54 +00:00
|
|
|
Mesg.pt.x = PsGetWin32Process()->WindowStation->SystemCursor.x;
|
|
|
|
Mesg.pt.y = PsGetWin32Process()->WindowStation->SystemCursor.y;
|
|
|
|
KeQueryTickCount(&LargeTickCount);
|
|
|
|
Mesg.time = LargeTickCount.u.LowPart;
|
2003-05-21 22:58:43 +00:00
|
|
|
Message = MsqCreateMessage(&Mesg);
|
|
|
|
MsqPostMessage(Window->MessageQueue, Message);
|
2003-11-23 12:41:42 +00:00
|
|
|
IntReleaseWindowObject(Window);
|
2003-05-21 22:58:43 +00:00
|
|
|
}
|
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;
|
2003-07-24 05:51:26 +00:00
|
|
|
|
2003-07-23 17:00:55 +00:00
|
|
|
PUSER_MESSAGE Message;
|
|
|
|
PETHREAD peThread;
|
|
|
|
PW32THREAD pThread;
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2003-07-24 05:51:26 +00:00
|
|
|
Status = PsLookupThreadByThreadId((void *)idThread,&peThread);
|
|
|
|
|
2003-07-23 17:00:55 +00:00
|
|
|
if( Status == STATUS_SUCCESS ) {
|
|
|
|
pThread = peThread->Win32Thread;
|
2003-07-24 05:51:26 +00:00
|
|
|
if( !pThread || !pThread->MessageQueue )
|
|
|
|
{
|
|
|
|
ObDereferenceObject( peThread );
|
|
|
|
return FALSE;
|
|
|
|
}
|
2003-07-23 17:00:55 +00:00
|
|
|
Mesg.hwnd = 0;
|
|
|
|
Mesg.message = Msg;
|
|
|
|
Mesg.wParam = wParam;
|
|
|
|
Mesg.lParam = lParam;
|
|
|
|
Message = MsqCreateMessage(&Mesg);
|
|
|
|
MsqPostMessage(pThread->MessageQueue, Message);
|
2003-07-24 05:51:26 +00:00
|
|
|
ObDereferenceObject( peThread );
|
2003-07-23 17:00:55 +00:00
|
|
|
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
|
2003-08-19 11:48:50 +00:00
|
|
|
IntSendMessage(HWND hWnd,
|
2002-07-17 21:04:57 +00:00
|
|
|
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. */
|
2003-11-23 12:41:42 +00:00
|
|
|
Window = IntGetWindowObject(hWnd);
|
|
|
|
if (!Window)
|
2002-07-04 19:56:38 +00:00
|
|
|
{
|
2003-11-23 12:41:42 +00:00
|
|
|
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
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)
|
|
|
|
{
|
2003-08-19 11:48:50 +00:00
|
|
|
Result = IntCallTrampolineWindowProc(NULL, hWnd, Msg, wParam,
|
2002-07-17 21:04:57 +00:00
|
|
|
lParam);
|
2003-11-23 12:41:42 +00:00
|
|
|
IntReleaseWindowObject(Window);
|
|
|
|
return Result;
|
2002-07-17 21:04:57 +00:00
|
|
|
}
|
|
|
|
else
|
2003-08-05 15:41:03 +00:00
|
|
|
{
|
2003-08-19 11:48:50 +00:00
|
|
|
Result = IntCallWindowProc(Window->WndProcW, hWnd, Msg, wParam, lParam);
|
2003-11-23 12:41:42 +00:00
|
|
|
IntReleaseWindowObject(Window);
|
|
|
|
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);
|
|
|
|
|
2003-11-23 12:41:42 +00:00
|
|
|
IntReleaseWindowObject(Window);
|
2002-07-04 19:56:38 +00:00
|
|
|
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,
|
2003-12-14 11:36:43 +00:00
|
|
|
LPARAM lParam,
|
|
|
|
PNTUSERSENDMESSAGEINFO UnsafeInfo)
|
2002-07-17 21:04:57 +00:00
|
|
|
{
|
2003-12-14 11:36:43 +00:00
|
|
|
LRESULT Result;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PWINDOW_OBJECT Window;
|
|
|
|
NTUSERSENDMESSAGEINFO Info;
|
|
|
|
|
|
|
|
/* FIXME: Check for a broadcast or topmost destination. */
|
|
|
|
|
|
|
|
/* FIXME: Call hooks. */
|
|
|
|
Window = IntGetWindowObject(Wnd);
|
|
|
|
if (NULL == Window)
|
|
|
|
{
|
|
|
|
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: Check for an exiting window. */
|
|
|
|
|
|
|
|
/* See if the current thread can handle the message */
|
|
|
|
if (NULL != PsGetWin32Thread() &&
|
|
|
|
Window->MessageQueue == PsGetWin32Thread()->MessageQueue)
|
|
|
|
{
|
|
|
|
/* Gather the information usermode needs to call the window proc directly */
|
|
|
|
Info.HandledByKernel = FALSE;
|
|
|
|
if (0xFFFF0000 != ((DWORD) Window->WndProcW & 0xFFFF0000))
|
|
|
|
{
|
|
|
|
if (0xFFFF0000 != ((DWORD) Window->WndProcA & 0xFFFF0000))
|
|
|
|
{
|
|
|
|
/* Both Unicode and Ansi winprocs are real */
|
|
|
|
Info.Ansi = ! Window->Unicode;
|
|
|
|
Info.Proc = (Window->Unicode ? Window->WndProcW : Window->WndProcA);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Real Unicode winproc */
|
|
|
|
Info.Ansi = FALSE;
|
|
|
|
Info.Proc = Window->WndProcW;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Must have real Ansi winproc */
|
|
|
|
Info.Ansi = TRUE;
|
|
|
|
Info.Proc = Window->WndProcA;
|
|
|
|
}
|
|
|
|
IntReleaseWindowObject(Window);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Must be handled by other thread */
|
|
|
|
IntReleaseWindowObject(Window);
|
|
|
|
Info.HandledByKernel = TRUE;
|
|
|
|
Result = IntSendMessage(Wnd, Msg, wParam, lParam, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
|
|
|
|
if (! NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
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-08-19 11:48:50 +00:00
|
|
|
return IntWaitMessage(NULL, 0, 0);
|
2001-06-12 17:51:51 +00:00
|
|
|
}
|
|
|
|
|
2003-08-02 16:53:08 +00:00
|
|
|
DWORD STDCALL
|
|
|
|
NtUserGetQueueStatus(BOOL ClearChanges)
|
|
|
|
{
|
|
|
|
PUSER_MESSAGE_QUEUE Queue;
|
|
|
|
DWORD Result;
|
|
|
|
|
|
|
|
Queue = PsGetWin32Thread()->MessageQueue;
|
|
|
|
|
|
|
|
ExAcquireFastMutex(&Queue->Lock);
|
|
|
|
|
|
|
|
Result = MAKELONG(Queue->ChangedBits, Queue->WakeBits);
|
|
|
|
if (ClearChanges)
|
|
|
|
{
|
|
|
|
Queue->ChangedBits = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExReleaseFastMutex(&Queue->Lock);
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2003-11-19 13:19:40 +00:00
|
|
|
BOOL STDCALL
|
|
|
|
IntInitMessagePumpHook()
|
|
|
|
{
|
|
|
|
PsGetCurrentThread()->Win32Thread->MessagePumpHookValue++;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL STDCALL
|
|
|
|
IntUninitMessagePumpHook()
|
|
|
|
{
|
|
|
|
if (PsGetCurrentThread()->Win32Thread->MessagePumpHookValue <= 0)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
PsGetCurrentThread()->Win32Thread->MessagePumpHookValue--;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2001-06-12 17:51:51 +00:00
|
|
|
/* EOF */
|