2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: message.c,v 1.18 2003/05/18 17:16:17 ea Exp $
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
24 * FILE: subsys/win32k/ntuser/message.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
30 /* INCLUDES ******************************************************************/
32 #include <ddk/ntddk.h>
33 #include <win32k/win32k.h>
34 #include <include/guicheck.h>
35 #include <include/msgqueue.h>
36 #include <include/window.h>
37 #include <include/class.h>
38 #include <include/error.h>
39 #include <include/object.h>
40 #include <include/winsta.h>
41 #include <include/callback.h>
42 #include <include/painting.h>
47 /* FUNCTIONS *****************************************************************/
50 W32kInitMessageImpl(VOID
)
52 return(STATUS_SUCCESS
);
56 W32kCleanupMessageImpl(VOID
)
58 return(STATUS_SUCCESS
);
63 NtUserDispatchMessage(CONST MSG
* lpMsg
)
67 PWINDOW_OBJECT WindowObject
;
70 /* Process timer messages. */
71 if (lpMsg
->message
== WM_TIMER
)
75 /* FIXME: Call hooks. */
77 /* FIXME: Check for continuing validity of timer. */
79 return(W32kCallWindowProc((WNDPROC
)lpMsg
->lParam
,
83 0 /* GetTickCount() */));
87 /* Get the window object. */
89 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation
->HandleTable
,
92 (PVOID
*)&WindowObject
);
93 if (!NT_SUCCESS(Status
))
98 /* FIXME: Check for paint message. */
99 PaintingFlag
= (lpMsg
->message
== WM_PAINT
);
102 WindowObject
->Flags
|= WINDOWOBJECT_NEED_BEGINPAINT
;
105 /* FIXME: Call hook procedures. */
107 /* Call the window procedure. */
108 Result
= W32kCallWindowProc(NULL
/* WndProc */,
114 if (PaintingFlag
&& WindowObject
->Flags
& WINDOWOBJECT_NEED_BEGINPAINT
&&
115 WindowObject
->UpdateRegion
)
124 NtUserGetMessage(LPMSG lpMsg
,
129 * FUNCTION: Get a message from the calling thread's message queue.
131 * lpMsg - Pointer to the structure which receives the returned message.
132 * hWnd - Window whose messages are to be retrieved.
133 * wMsgFilterMin - Integer value of the lowest message value to be
135 * wMsgFilterMax - Integer value of the highest message value to be
139 PUSER_MESSAGE_QUEUE ThreadQueue
;
141 PUSER_MESSAGE Message
;
144 /* Initialize the thread's win32 state if necessary. */
147 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetWin32Thread()->MessageQueue
;
151 /* Dispatch sent messages here. */
152 while (MsqDispatchOneSentMessage(ThreadQueue
));
154 /* Now look for a quit message. */
155 /* FIXME: WINE checks the message number filter here. */
156 if (ThreadQueue
->QuitPosted
)
159 lpMsg
->message
= WM_QUIT
;
160 lpMsg
->wParam
= ThreadQueue
->QuitExitCode
;
162 ThreadQueue
->QuitPosted
= FALSE
;
166 /* Now check for normal messages. */
167 Present
= MsqFindMessage(ThreadQueue
,
176 RtlCopyMemory(lpMsg
, &Message
->Msg
, sizeof(MSG
));
181 /* Check for hardware events. */
182 Present
= MsqFindMessage(ThreadQueue
,
191 RtlCopyMemory(lpMsg
, &Message
->Msg
, sizeof(MSG
));
196 /* Check for sent messages again. */
197 while (MsqDispatchOneSentMessage(ThreadQueue
));
199 /* Check for paint messages. */
200 if (ThreadQueue
->PaintPosted
)
202 PWINDOW_OBJECT WindowObject
;
204 lpMsg
->hwnd
= PaintingFindWinToRepaint(hWnd
, PsGetWin32Thread());
205 lpMsg
->message
= WM_PAINT
;
206 lpMsg
->wParam
= lpMsg
->lParam
= 0;
208 WindowObject
= W32kGetWindowObject(lpMsg
->hwnd
);
209 if (WindowObject
!= NULL
)
211 if (WindowObject
->Style
& WS_MINIMIZE
&&
212 (HICON
)NtUserGetClassLong(lpMsg
->hwnd
, GCL_HICON
) != NULL
)
214 lpMsg
->message
= WM_PAINTICON
;
218 if (lpMsg
->hwnd
== NULL
|| lpMsg
->hwnd
== hWnd
||
219 W32kIsChildWindow(hWnd
, lpMsg
->hwnd
))
221 if (WindowObject
->Flags
& WINDOWOBJECT_NEED_INTERNALPAINT
&&
222 WindowObject
->UpdateRegion
== NULL
)
224 WindowObject
->Flags
&= ~WINDOWOBJECT_NEED_INTERNALPAINT
;
225 MsqDecPaintCountQueue(WindowObject
->MessageQueue
);
228 W32kReleaseWindowObject(WindowObject
);
234 /* Nothing found so far. Wait for new messages. */
235 Status
= MsqWaitForNewMessages(ThreadQueue
);
237 while (Status
>= STATUS_WAIT_0
&& Status
<= STATUS_WAIT_63
);
238 return((BOOLEAN
)(-1));
258 NtUserPeekMessage(LPMSG lpMsg
,
264 * FUNCTION: Get a message from the calling thread's message queue.
266 * lpMsg - Pointer to the structure which receives the returned message.
267 * hWnd - Window whose messages are to be retrieved.
268 * wMsgFilterMin - Integer value of the lowest message value to be
270 * wMsgFilterMax - Integer value of the highest message value to be
272 * wRemoveMsg - Specificies whether or not to remove messages from the queue after processing
275 PUSER_MESSAGE_QUEUE ThreadQueue
;
277 PUSER_MESSAGE Message
;
278 BOOLEAN RemoveMessages
;
280 /* Initialize the thread's win32 state if necessary. */
283 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetWin32Thread()->MessageQueue
;
285 /* Inspect wRemoveMsg flags */
286 /* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
287 RemoveMessages
= wRemoveMsg
& PM_REMOVE
;
289 /* Dispatch sent messages here. */
290 while (MsqDispatchOneSentMessage(ThreadQueue
));
292 /* Now look for a quit message. */
293 /* FIXME: WINE checks the message number filter here. */
294 if (ThreadQueue
->QuitPosted
)
297 lpMsg
->message
= WM_QUIT
;
298 lpMsg
->wParam
= ThreadQueue
->QuitExitCode
;
300 ThreadQueue
->QuitPosted
= FALSE
;
304 /* Now check for normal messages. */
305 Present
= MsqFindMessage(ThreadQueue
,
314 RtlCopyMemory(lpMsg
, &Message
->Msg
, sizeof(MSG
));
319 /* Check for hardware events. */
320 Present
= MsqFindMessage(ThreadQueue
,
329 RtlCopyMemory(lpMsg
, &Message
->Msg
, sizeof(MSG
));
334 /* Check for sent messages again. */
335 while (MsqDispatchOneSentMessage(ThreadQueue
));
337 /* Check for paint messages. */
339 /* Check for paint messages. */
340 if (ThreadQueue
->PaintPosted
)
342 PWINDOW_OBJECT WindowObject
;
344 lpMsg
->hwnd
= PaintingFindWinToRepaint(hWnd
, PsGetWin32Thread());
345 lpMsg
->message
= WM_PAINT
;
346 lpMsg
->wParam
= lpMsg
->lParam
= 0;
348 WindowObject
= W32kGetWindowObject(lpMsg
->hwnd
);
349 if (WindowObject
!= NULL
)
351 if (WindowObject
->Style
& WS_MINIMIZE
&&
352 (HICON
)NtUserGetClassLong(lpMsg
->hwnd
, GCL_HICON
) != NULL
)
354 lpMsg
->message
= WM_PAINTICON
;
358 if (lpMsg
->hwnd
== NULL
|| lpMsg
->hwnd
== hWnd
||
359 W32kIsChildWindow(hWnd
, lpMsg
->hwnd
))
361 if (WindowObject
->Flags
& WINDOWOBJECT_NEED_INTERNALPAINT
&&
362 WindowObject
->UpdateRegion
== NULL
)
364 WindowObject
->Flags
&= ~WINDOWOBJECT_NEED_INTERNALPAINT
;
365 MsqDecPaintCountQueue(WindowObject
->MessageQueue
);
368 W32kReleaseWindowObject(WindowObject
);
378 NtUserPostMessage(HWND hWnd
,
383 PUSER_MESSAGE_QUEUE ThreadQueue
;
391 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetWin32Thread()->MessageQueue
;
392 ThreadQueue
->QuitPosted
= TRUE
;
393 ThreadQueue
->QuitExitCode
= wParam
;
397 DPRINT1("Unhandled message: %u\n", Msg
);
405 NtUserPostThreadMessage(DWORD idThread
,
416 NtUserQuerySendMessage(DWORD Unknown0
)
424 W32kSendMessage(HWND hWnd
,
432 PWINDOW_OBJECT Window
;
434 /* FIXME: Check for a broadcast or topmost destination. */
436 /* FIXME: Call hooks. */
439 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation
->HandleTable
,
443 if (!NT_SUCCESS(Status
))
448 /* FIXME: Check for an exiting window. */
450 if (NULL
!= PsGetWin32Thread() &&
451 Window
->MessageQueue
== PsGetWin32Thread()->MessageQueue
)
455 Result
= W32kCallTrampolineWindowProc(NULL
, hWnd
, Msg
, wParam
,
461 Result
= W32kCallWindowProc(NULL
, hWnd
, Msg
, wParam
, lParam
);
467 PUSER_SENT_MESSAGE Message
;
468 PKEVENT CompletionEvent
;
470 CompletionEvent
= ExAllocatePool(NonPagedPool
, sizeof(KEVENT
));
471 KeInitializeEvent(CompletionEvent
, NotificationEvent
, FALSE
);
473 Message
= ExAllocatePool(NonPagedPool
, sizeof(USER_SENT_MESSAGE
));
474 Message
->Msg
.hwnd
= hWnd
;
475 Message
->Msg
.message
= Msg
;
476 Message
->Msg
.wParam
= wParam
;
477 Message
->Msg
.lParam
= lParam
;
478 Message
->CompletionEvent
= CompletionEvent
;
479 Message
->Result
= &Result
;
480 Message
->CompletionQueue
= NULL
;
481 Message
->CompletionCallback
= NULL
;
482 MsqSendMessage(Window
->MessageQueue
, Message
);
484 ObmDereferenceObject(Window
);
485 Status
= KeWaitForSingleObject(CompletionEvent
,
490 if (Status
== STATUS_WAIT_0
)
502 NtUserSendMessage(HWND hWnd
,
507 return(W32kSendMessage(hWnd
, Msg
, wParam
, lParam
, FALSE
));
511 NtUserSendMessageCallback(HWND hWnd
,
515 SENDASYNCPROC lpCallBack
,
524 NtUserSendNotifyMessage(HWND hWnd
,
535 NtUserWaitMessage(VOID
)