Fixed some bugs.
[reactos.git] / reactos / subsys / win32k / ntuser / msgqueue.c
1 /* $Id: msgqueue.c,v 1.5 2002/07/17 21:04:57 dwelch Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: Message queues
6 * FILE: subsys/win32k/ntuser/msgqueue.c
7 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * REVISION HISTORY:
9 * 06-06-2001 CSH Created
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <win32k/win32k.h>
16 #include <include/msgqueue.h>
17 #include <include/callback.h>
18
19 #define NDEBUG
20 #include <debug.h>
21
22 /* GLOBALS *******************************************************************/
23
24 static PUSER_MESSAGE_QUEUE CurrentFocusMessageQueue;
25
26 /* FUNCTIONS *****************************************************************/
27
28 VOID
29 MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue)
30 {
31 ExAcquireFastMutex(&Queue->Lock);
32 Queue->PaintCount++;
33 Queue->PaintPosted = TRUE;
34 ExReleaseFastMutex(&Queue->Lock);
35 }
36
37 VOID
38 MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue)
39 {
40 ExAcquireFastMutex(&Queue->Lock);
41 Queue->PaintCount--;
42 if (Queue->PaintCount == 0)
43 {
44 Queue->PaintPosted = FALSE;
45 }
46 ExReleaseFastMutex(&Queue->Lock);
47 }
48
49
50 NTSTATUS
51 MsqInitializeImpl(VOID)
52 {
53 CurrentFocusMessageQueue = NULL;
54 return(STATUS_SUCCESS);
55 }
56
57 VOID
58 MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
59 {
60 MSG Msg;
61 PUSER_MESSAGE Message;
62
63 Msg.hwnd = CurrentFocusMessageQueue->FocusWindow;
64 Msg.message = uMsg;
65 Msg.wParam = wParam;
66 Msg.lParam = lParam;
67 /* FIXME: Initialize time and point. */
68
69 Message = MsqCreateMessage(&Msg);
70 MsqPostMessage(CurrentFocusMessageQueue, Message, TRUE);
71 }
72
73 VOID
74 MsqInitializeMessage(PUSER_MESSAGE Message,
75 LPMSG Msg)
76 {
77 RtlMoveMemory(&Message->Msg, Msg, sizeof(MSG));
78 }
79
80 PUSER_MESSAGE
81 MsqCreateMessage(LPMSG Msg)
82 {
83 PUSER_MESSAGE Message;
84
85 Message = (PUSER_MESSAGE)ExAllocatePool(PagedPool, sizeof(USER_MESSAGE));
86 if (!Message)
87 {
88 return NULL;
89 }
90
91 MsqInitializeMessage(Message, Msg);
92
93 return Message;
94 }
95
96 VOID
97 MsqDestroyMessage(PUSER_MESSAGE Message)
98 {
99 ExFreePool(Message);
100 }
101
102 VOID
103 MsqDispatchSentNotifyMessages(PUSER_MESSAGE_QUEUE MessageQueue)
104 {
105 PLIST_ENTRY ListEntry;
106 PUSER_SENT_MESSAGE_NOTIFY Message;
107
108 while (!IsListEmpty(&MessageQueue->SentMessagesListHead))
109 {
110 ExAcquireFastMutex(&MessageQueue->Lock);
111 ListEntry = RemoveHeadList(&MessageQueue->SentMessagesListHead);
112 Message = CONTAINING_RECORD(ListEntry, USER_SENT_MESSAGE_NOTIFY,
113 ListEntry);
114 ExReleaseFastMutex(&MessageQueue->Lock);
115
116 W32kCallSentMessageCallback(Message->CompletionCallback,
117 Message->hWnd,
118 Message->Msg,
119 Message->CompletionCallbackContext,
120 Message->Result);
121 }
122 }
123
124 BOOLEAN
125 MsqPeekSentMessages(PUSER_MESSAGE_QUEUE MessageQueue)
126 {
127 return(!IsListEmpty(&MessageQueue->SentMessagesListHead));
128 }
129
130 BOOLEAN
131 MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
132 {
133 PUSER_SENT_MESSAGE Message;
134 PLIST_ENTRY Entry;
135 LRESULT Result;
136 PUSER_SENT_MESSAGE_NOTIFY NotifyMessage;
137
138 ExAcquireFastMutex(&MessageQueue->Lock);
139 if (IsListEmpty(&MessageQueue->SentMessagesListHead))
140 {
141 ExReleaseFastMutex(&MessageQueue->Lock);
142 return(FALSE);
143 }
144 Entry = RemoveHeadList(&MessageQueue->SentMessagesListHead);
145 Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
146 ExReleaseFastMutex(&MessageQueue->Lock);
147
148 /* Call the window procedure. */
149 Result = W32kCallWindowProc(NULL,
150 Message->Msg.hwnd,
151 Message->Msg.message,
152 Message->Msg.wParam,
153 Message->Msg.lParam);
154
155 /* Let the sender know the result. */
156 if (Message->Result != NULL)
157 {
158 *Message->Result = Result;
159 }
160
161 /* Notify the sender. */
162 if (Message->CompletionEvent != NULL)
163 {
164 KeSetEvent(Message->CompletionEvent, IO_NO_INCREMENT, FALSE);
165 }
166
167 /* Notify the sender if they specified a callback. */
168 if (Message->CompletionCallback != NULL)
169 {
170 NotifyMessage = ExAllocatePool(NonPagedPool,
171 sizeof(USER_SENT_MESSAGE_NOTIFY));
172 NotifyMessage->CompletionCallback =
173 Message->CompletionCallback;
174 NotifyMessage->CompletionCallbackContext =
175 Message->CompletionCallbackContext;
176 NotifyMessage->Result = Result;
177 NotifyMessage->hWnd = Message->Msg.hwnd;
178 NotifyMessage->Msg = Message->Msg.message;
179 MsqSendNotifyMessage(Message->CompletionQueue, NotifyMessage);
180 }
181
182 ExFreePool(Message);
183 return(TRUE);
184 }
185
186 VOID
187 MsqSendNotifyMessage(PUSER_MESSAGE_QUEUE MessageQueue,
188 PUSER_SENT_MESSAGE_NOTIFY NotifyMessage)
189 {
190 ExAcquireFastMutex(&MessageQueue->Lock);
191 InsertTailList(&MessageQueue->NotifyMessagesListHead,
192 &NotifyMessage->ListEntry);
193 ExReleaseFastMutex(&MessageQueue->Lock);
194 }
195
196 VOID
197 MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
198 PUSER_SENT_MESSAGE Message)
199 {
200 ExAcquireFastMutex(&MessageQueue->Lock);
201 InsertTailList(&MessageQueue->SentMessagesListHead, &Message->ListEntry);
202 ExReleaseFastMutex(&MessageQueue->Lock);
203 }
204
205 VOID
206 MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue,
207 PUSER_MESSAGE Message,
208 BOOLEAN Hardware)
209 {
210 ExAcquireFastMutex(&MessageQueue->Lock);
211 if (Hardware)
212 {
213 InsertTailList(&MessageQueue->HardwareMessagesListHead,
214 &Message->ListEntry);
215 }
216 else
217 {
218 InsertTailList(&MessageQueue->PostedMessagesListHead,
219 &Message->ListEntry);
220 }
221 KeSetEvent(&MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
222 ExReleaseFastMutex(&MessageQueue->Lock);
223 }
224
225 BOOLEAN
226 MsqFindMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
227 IN BOOLEAN Hardware,
228 IN BOOLEAN Remove,
229 IN HWND Wnd,
230 IN UINT MsgFilterLow,
231 IN UINT MsgFilterHigh,
232 OUT PUSER_MESSAGE* Message)
233 {
234 PLIST_ENTRY CurrentEntry;
235 PUSER_MESSAGE CurrentMessage;
236 PLIST_ENTRY ListHead;
237
238 ExAcquireFastMutex(&MessageQueue->Lock);
239 if (Hardware)
240 {
241 CurrentEntry = MessageQueue->HardwareMessagesListHead.Flink;
242 ListHead = &MessageQueue->HardwareMessagesListHead;
243 }
244 else
245 {
246 CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
247 ListHead = &MessageQueue->PostedMessagesListHead;
248 }
249 while (CurrentEntry != ListHead)
250 {
251 CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
252 ListEntry);
253 if ((Wnd == 0 || Wnd == CurrentMessage->Msg.hwnd) &&
254 ((MsgFilterLow == 0 && MsgFilterHigh == 0) ||
255 (MsgFilterLow <= CurrentMessage->Msg.message &&
256 MsgFilterHigh >= CurrentMessage->Msg.message)))
257 {
258 if (Remove)
259 {
260 RemoveEntryList(&CurrentMessage->ListEntry);
261 }
262 ExReleaseFastMutex(&MessageQueue->Lock);
263 *Message = CurrentMessage;
264 return(TRUE);
265 }
266 CurrentEntry = CurrentEntry->Flink;
267 }
268 ExReleaseFastMutex(&MessageQueue->Lock);
269 return(FALSE);
270 }
271
272 NTSTATUS
273 MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue)
274 {
275 return(KeWaitForSingleObject(&MessageQueue->NewMessages,
276 0,
277 UserMode,
278 TRUE,
279 NULL));
280 }
281
282 VOID
283 MsqInitializeMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
284 {
285 InitializeListHead(&MessageQueue->PostedMessagesListHead);
286 InitializeListHead(&MessageQueue->HardwareMessagesListHead);
287 InitializeListHead(&MessageQueue->SentMessagesListHead);
288 ExInitializeFastMutex(&MessageQueue->Lock);
289 MessageQueue->QuitPosted = FALSE;
290 MessageQueue->QuitExitCode = 0;
291 KeInitializeEvent(&MessageQueue->NewMessages, NotificationEvent, FALSE);
292 MessageQueue->QueueStatus = 0;
293 MessageQueue->FocusWindow = NULL;
294 }
295
296 VOID
297 MsqFreeMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
298 {
299 PLIST_ENTRY CurrentEntry;
300 PUSER_MESSAGE CurrentMessage;
301
302 CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
303 while (CurrentEntry != &MessageQueue->PostedMessagesListHead)
304 {
305 CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
306 ListEntry);
307 CurrentEntry = CurrentEntry->Flink;
308 ExFreePool(CurrentMessage);
309 }
310
311 CurrentEntry = MessageQueue->HardwareMessagesListHead.Flink;
312 while (CurrentEntry != &MessageQueue->HardwareMessagesListHead)
313 {
314 CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
315 ListEntry);
316 CurrentEntry = CurrentEntry->Flink;
317 ExFreePool(CurrentMessage);
318 }
319 }
320
321 PUSER_MESSAGE_QUEUE
322 MsqCreateMessageQueue(VOID)
323 {
324 PUSER_MESSAGE_QUEUE MessageQueue;
325
326 MessageQueue = (PUSER_MESSAGE_QUEUE)ExAllocatePool(PagedPool,
327 sizeof(USER_MESSAGE_QUEUE));
328 if (!MessageQueue)
329 {
330 return NULL;
331 }
332
333 MsqInitializeMessageQueue(MessageQueue);
334
335 return MessageQueue;
336 }
337
338 VOID
339 MsqDestroyMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
340 {
341 MsqFreeMessageQueue(MessageQueue);
342 ExFreePool(MessageQueue);
343 }
344
345 /* EOF */