source: trunk/src/user32/message.cpp@ 7801

Last change on this file since 7801 was 7801, checked in by sandervl, 24 years ago

message handling changes

File size: 20.6 KB
Line 
1/* $Id: message.cpp,v 1.1 2002-02-05 17:58:59 sandervl Exp $ */
2/*
3 * Win32 window message APIs for OS/2
4 *
5 * Copyright 1999-2002 Sander van Leeuwen
6 *
7 * Based on Wine Windows code (dlls\user\message.c) 20020122
8 *
9 * Window messaging support
10 *
11 * Copyright 2001 Alexandre Julliard
12 *
13 * Project Odin Software License can be found in LICENSE.TXT
14 *
15 */
16
17#include <odin.h>
18#include <odinwrap.h>
19#include <os2sel.h>
20
21#include <os2win.h>
22#include <misc.h>
23#include <win32wbase.h>
24#include <win.h>
25#include <heapstring.h>
26#include <handlemanager.h>
27#include "oslibutil.h"
28#include "oslibwin.h"
29#include "oslibmsg.h"
30#include "hook.h"
31
32#define DBG_LOCALLOG DBG_message
33#include "dbglocal.h"
34
35ODINDEBUGCHANNEL(USER32-MESSAGE)
36
37#define WIN_GetFullHandle(a) a
38
39#define is_broadcast(hwnd) (hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST)
40
41
42enum message_type
43{
44 MSG_ASCII,
45 MSG_UNICODE,
46 MSG_NOTIFY,
47 MSG_CALLBACK_ASCII,
48 MSG_CALLBACK_UNICODE,
49 MSG_OTHER_PROCESS,
50 MSG_POSTED_ASCII,
51 MSG_POSTED_UNICODE
52};
53
54/* structure to group all parameters for sent messages of the various kinds */
55struct send_message_info
56{
57 enum message_type type;
58 HWND hwnd;
59 UINT msg;
60 WPARAM wparam;
61 LPARAM lparam;
62 UINT flags; /* flags for SendMessageTimeout */
63 UINT timeout; /* timeout for SendMessageTimeout */
64 SENDASYNCPROC callback; /* callback function for SendMessageCallback */
65 ULONG_PTR data; /* callback data */
66};
67
68/***********************************************************************
69 * broadcast_message_callback
70 *
71 * Helper callback for broadcasting messages.
72 */
73static BOOL CALLBACK broadcast_message_callback( HWND hwnd, LPARAM lparam )
74{
75 struct send_message_info *info = (struct send_message_info *)lparam;
76 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & (WS_POPUP|WS_CAPTION))) return TRUE;
77 switch(info->type)
78 {
79 case MSG_UNICODE:
80 SendMessageTimeoutW( hwnd, info->msg, info->wparam, info->lparam,
81 info->flags, info->timeout, NULL );
82 break;
83 case MSG_ASCII:
84 SendMessageTimeoutA( hwnd, info->msg, info->wparam, info->lparam,
85 info->flags, info->timeout, NULL );
86 break;
87 case MSG_NOTIFY:
88 SendNotifyMessageW( hwnd, info->msg, info->wparam, info->lparam );
89 break;
90 case MSG_CALLBACK_ASCII:
91 SendMessageCallbackA( hwnd, info->msg, info->wparam, info->lparam,
92 info->callback, info->data );
93 break;
94 case MSG_CALLBACK_UNICODE:
95 SendMessageCallbackW( hwnd, info->msg, info->wparam, info->lparam,
96 info->callback, info->data );
97 break;
98 case MSG_POSTED_ASCII:
99 PostMessageA( hwnd, info->msg, info->wparam, info->lparam );
100 break;
101 case MSG_POSTED_UNICODE:
102 PostMessageW( hwnd, info->msg, info->wparam, info->lparam );
103 break;
104 default:
105 dprintf(("!ERROR!: broadcast_message_callback: bad type %d\n", info->type ));
106 DebugInt3();
107 break;
108 }
109 return TRUE;
110}
111/***********************************************************************
112 * call_window_proc
113 *
114 * Call a window procedure and the corresponding hooks.
115 */
116static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL unicode )
117{
118 LRESULT result;
119 WNDPROC winproc;
120
121 /* first the WH_CALLWNDPROC hook */
122 if (HOOK_IsHooked( WH_CALLWNDPROC ))
123 {
124 CWPSTRUCT cwp;
125 cwp.lParam = lparam;
126 cwp.wParam = wparam;
127 cwp.message = msg;
128 cwp.hwnd = WIN_GetFullHandle( hwnd );
129 if (unicode) HOOK_CallHooksW( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp );
130 else HOOK_CallHooksA( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp );
131 lparam = cwp.lParam;
132 wparam = cwp.wParam;
133 msg = cwp.message;
134 hwnd = cwp.hwnd;
135 }
136
137 /* now call the window procedure */
138 if (unicode)
139 {
140 if (!(winproc = (WNDPROC)GetWindowLongW( hwnd, GWL_WNDPROC ))) return 0;
141 result = CallWindowProcW( winproc, hwnd, msg, wparam, lparam );
142 }
143 else
144 {
145 if (!(winproc = (WNDPROC)GetWindowLongA( hwnd, GWL_WNDPROC ))) return 0;
146 result = CallWindowProcA( winproc, hwnd, msg, wparam, lparam );
147 }
148#ifdef __WIN32OS2__
149 //hittest caching
150 if(msg == WM_NCHITTEST)
151 {
152 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
153 if(window) {
154 window->setLastHitTestVal(result);
155 RELEASE_WNDOBJ(window);
156 }
157 else DebugInt3();
158 }
159#endif
160
161 /* and finally the WH_CALLWNDPROCRET hook */
162 if (HOOK_IsHooked( WH_CALLWNDPROCRET ))
163 {
164 CWPRETSTRUCT cwp;
165 cwp.lResult = result;
166 cwp.lParam = lparam;
167 cwp.wParam = wparam;
168 cwp.message = msg;
169 cwp.hwnd = WIN_GetFullHandle( hwnd );
170 if (unicode) HOOK_CallHooksW( WH_CALLWNDPROCRET, HC_ACTION, 1, (LPARAM)&cwp );
171 else HOOK_CallHooksA( WH_CALLWNDPROCRET, HC_ACTION, 1, (LPARAM)&cwp );
172 }
173 return result;
174}
175/***********************************************************************
176 * SendMessageTimeoutW (USER32.@)
177 */
178LRESULT WINAPI SendMessageTimeoutW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
179 UINT flags, UINT timeout, LPDWORD res_ptr )
180{
181 struct send_message_info info;
182 DWORD dest_tid, dest_pid;
183 LRESULT ret, result;
184
185 info.type = MSG_UNICODE;
186 info.hwnd = hwnd;
187 info.msg = msg;
188 info.wparam = wparam;
189 info.lparam = lparam;
190 info.flags = flags;
191 info.timeout = timeout;
192
193 if (is_broadcast(hwnd))
194 {
195 EnumWindows( broadcast_message_callback, (LPARAM)&info );
196 if (res_ptr) *res_ptr = 1;
197 return 1;
198 }
199
200 if (!(dest_tid = GetWindowThreadProcessId( hwnd, &dest_pid ))) return 0;
201
202 if (dest_tid == GetCurrentThreadId())
203 {
204 result = call_window_proc( hwnd, msg, wparam, lparam, TRUE );
205 ret = 1;
206 }
207 else
208 {
209 //otherwise use WinSendMsg to send it to the right process/thread
210 dprintf(("SendMessages (inter-process) %x %x %x %x", Win32ToOS2Handle(hwnd), msg, wparam, lparam));
211 ret = OSLibSendMessage(Win32ToOS2Handle(hwnd), msg, wparam, lparam, TRUE);
212 }
213
214 if (ret && res_ptr) *res_ptr = result;
215 return ret;
216}
217
218
219/***********************************************************************
220 * SendMessageTimeoutA (USER32.@)
221 */
222LRESULT WINAPI SendMessageTimeoutA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
223 UINT flags, UINT timeout, LPDWORD res_ptr )
224{
225 struct send_message_info info;
226 DWORD dest_tid, dest_pid;
227 LRESULT ret, result;
228
229 info.type = MSG_ASCII;
230 info.hwnd = hwnd;
231 info.msg = msg;
232 info.wparam = wparam;
233 info.lparam = lparam;
234 info.flags = flags;
235 info.timeout = timeout;
236
237 if (is_broadcast(hwnd))
238 {
239 EnumWindows( broadcast_message_callback, (LPARAM)&info );
240 if (res_ptr) *res_ptr = 1;
241 return 1;
242 }
243
244 if (!(dest_tid = GetWindowThreadProcessId( hwnd, &dest_pid ))) return 0;
245
246 if (dest_tid == GetCurrentThreadId())
247 {
248 result = call_window_proc( hwnd, msg, wparam, lparam, FALSE );
249 ret = 1;
250 }
251 else
252 {
253 //otherwise use WinSendMsg to send it to the right process/thread
254 dprintf(("SendMessages (inter-process) %x %x %x %x", Win32ToOS2Handle(hwnd), msg, wparam, lparam));
255 ret = OSLibSendMessage(Win32ToOS2Handle(hwnd), msg, wparam, lparam, FALSE);
256 }
257 if (ret && res_ptr) *res_ptr = result;
258 return ret;
259}
260//******************************************************************************
261//******************************************************************************
262LRESULT WIN32API SendMessageA(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
263{
264 LRESULT res = 0;
265 SendMessageTimeoutA(hwnd, msg, wParam, lParam, SMTO_NORMAL, INFINITE, (LPDWORD)&res);
266 return res;
267}
268//******************************************************************************
269//******************************************************************************
270LRESULT WIN32API SendMessageW(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
271{
272 LRESULT res = 0;
273 SendMessageTimeoutW(hwnd, msg, wParam, lParam, SMTO_NORMAL, INFINITE, (LPDWORD)&res);
274 return res;
275}
276//******************************************************************************
277//******************************************************************************
278BOOL WIN32API PostMessageA(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
279{
280 Win32BaseWindow *window;
281 HWND hwndOS2;
282
283 struct send_message_info info;
284 DWORD dest_tid;
285
286#if 0
287 if (is_pointer_message( msg ))
288 {
289 SetLastError( ERROR_INVALID_PARAMETER );
290 return FALSE;
291 }
292#endif
293
294 info.type = MSG_POSTED_ASCII;
295 info.hwnd = hwnd;
296 info.msg = msg;
297 info.wparam = wParam;
298 info.lparam = lParam;
299
300 if (is_broadcast(hwnd))
301 {
302 EnumWindows( broadcast_message_callback, (LPARAM)&info );
303 return TRUE;
304 }
305
306 if(hwnd == NULL)
307 return PostThreadMessageA(GetCurrentThreadId(), msg, wParam, lParam);
308
309 window = Win32BaseWindow::GetWindowFromHandle(hwnd);
310 if(!window) {
311 dprintf(("PostMessageA, window %x not found", hwnd));
312 return FALSE;
313 }
314 hwndOS2 = window->getOS2WindowHandle();
315 RELEASE_WNDOBJ(window);
316 dprintf(("PostMessageA, %x %x %x %x", hwnd, msg, wParam, lParam));
317 return OSLibPostMessage(hwndOS2, msg, wParam, lParam, FALSE);
318}
319//******************************************************************************
320//******************************************************************************
321BOOL WIN32API PostMessageW(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
322{
323 Win32BaseWindow *window;
324 HWND hwndOS2;
325
326 struct send_message_info info;
327 DWORD dest_tid;
328
329 info.type = MSG_POSTED_UNICODE;
330 info.hwnd = hwnd;
331 info.msg = msg;
332 info.wparam = wParam;
333 info.lparam = lParam;
334
335 if (is_broadcast(hwnd))
336 {
337 EnumWindows( broadcast_message_callback, (LPARAM)&info );
338 return TRUE;
339 }
340
341 if(hwnd == NULL)
342 return PostThreadMessageW(GetCurrentThreadId(), msg, wParam, lParam);
343
344 window = Win32BaseWindow::GetWindowFromHandle(hwnd);
345 if(!window) {
346 dprintf(("PostMessageW, window %x not found", hwnd));
347 return FALSE;
348 }
349 hwndOS2 = window->getOS2WindowHandle();
350 RELEASE_WNDOBJ(window);
351 dprintf(("PostMessageW, %x %x %x %x", hwnd, msg, wParam, lParam));
352 return OSLibPostMessage(hwndOS2, msg, wParam, lParam, TRUE);
353}
354//******************************************************************************
355//******************************************************************************
356BOOL WIN32API PostThreadMessageA( DWORD threadid, UINT msg, WPARAM wParam, LPARAM lParam)
357{
358 return OSLibPostThreadMessage(threadid, msg, wParam, lParam, FALSE);
359}
360//******************************************************************************
361//******************************************************************************
362BOOL WIN32API PostThreadMessageW( DWORD threadid, UINT msg, WPARAM wParam, LPARAM lParam)
363{
364 return OSLibPostThreadMessage(threadid, msg, wParam, lParam, TRUE);
365}
366//******************************************************************************
367//******************************************************************************
368BOOL WIN32API SendNotifyMessageA(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
369{
370 DWORD dest_tid;
371
372 dprintf(("USER32: SendNotifyMessageA %x %x %x %x", hwnd, Msg, wParam, lParam));
373
374 if (!(dest_tid = GetWindowThreadProcessId( hwnd, NULL ))) return FALSE;
375
376 if (dest_tid == GetCurrentThreadId())
377 {
378 SendMessageA( hwnd, Msg, wParam, lParam);
379 return TRUE;
380 }
381 //Must not block when window thread != current thread
382 return PostMessageA(hwnd, Msg, wParam, lParam);
383}
384//******************************************************************************
385//******************************************************************************
386BOOL WIN32API SendNotifyMessageW(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
387{
388 DWORD dest_tid;
389
390 dprintf(("USER32: SendNotifyMessageW %x %x %x %x", hwnd, Msg, wParam, lParam));
391
392 if (!(dest_tid = GetWindowThreadProcessId( hwnd, NULL ))) return FALSE;
393
394 if (dest_tid == GetCurrentThreadId())
395 {
396 SendMessageW( hwnd, Msg, wParam, lParam);
397 return TRUE;
398 }
399 //Must not block when window thread != current thread
400 return PostMessageW(hwnd, Msg, wParam, lParam);
401}
402/*****************************************************************************
403 * Name : BOOL WIN32API SendMessageCallbackA
404 * Purpose : The SendMessageCallback function sends the specified message to
405 * a window or windows. The function calls the window procedure for
406 * the specified window and returns immediately. After the window
407 * procedure processes the message, the system calls the specified
408 * callback function, passing the result of the message processing
409 * and an application-defined value to the callback function.
410 * Parameters: HWND hwnd handle of destination window
411 * UINT uMsg message to send
412 * WPARAM wParam first message parameter
413 * LPARAM lParam second message parameter
414 * SENDASYNCPROC lpResultCallBack function to receive message value
415 * DWORD dwData value to pass to callback function
416 * Variables :
417 * Result : If the function succeeds, the return value is TRUE.
418 * If the function fails, the return value is FALSE. To get extended
419 * error information, call GetLastError.
420 * Remark :
421 * Status :
422 *
423 * Author : Wine
424 *****************************************************************************/
425
426BOOL WIN32API SendMessageCallbackA(HWND hwnd,
427 UINT uMsg,
428 WPARAM wParam,
429 LPARAM lParam,
430 SENDASYNCPROC lpResultCallBack,
431 DWORD dwData)
432{
433 struct send_message_info info;
434 LRESULT result;
435 DWORD dest_tid;
436
437#if 0
438 if (is_pointer_message(msg))
439 {
440 SetLastError(ERROR_INVALID_PARAMETER);
441 return FALSE;
442 }
443#endif
444
445 dprintf(("USER32:SendMessageCallBackW (%08xh,%08xh,%08xh,%08xh,%08xh,%08x)",
446 hwnd, uMsg, wParam, lParam, lpResultCallBack, dwData));
447
448 info.type = MSG_CALLBACK_ASCII;
449 info.hwnd = hwnd;
450 info.msg = uMsg;
451 info.wparam = wParam;
452 info.lparam = lParam;
453 info.callback = lpResultCallBack;
454 info.data = dwData;
455
456 if (is_broadcast(hwnd))
457 {
458 EnumWindows( broadcast_message_callback, (LPARAM)&info );
459 return TRUE;
460 }
461
462 if (!(dest_tid = GetWindowThreadProcessId( hwnd, NULL ))) return FALSE;
463
464 if (dest_tid == GetCurrentThreadId())
465 {
466 result = call_window_proc( hwnd, uMsg, wParam, lParam, FALSE );
467 lpResultCallBack( hwnd, uMsg, dwData, result );
468 return TRUE;
469 }
470 else
471 {
472 dprintf(("!WARNING!: callback will not be called" ));
473
474 //otherwise use PostMessage to send it to the right process/thread
475 dprintf(("SendMessageCallbackA (inter-process) %x %x %x %x", hwnd, uMsg, wParam, lParam));
476 PostMessageA(hwnd, uMsg, wParam, lParam);
477 return TRUE;
478 }
479}
480
481
482/*****************************************************************************
483 * Name : BOOL WIN32API SendMessageCallbackW
484 * Purpose : The SendMessageCallback function sends the specified message to
485 * a window or windows. The function calls the window procedure for
486 * the specified window and returns immediately. After the window
487 * procedure processes the message, the system calls the specified
488 * callback function, passing the result of the message processing
489 * and an application-defined value to the callback function.
490 * Parameters: HWND hwnd handle of destination window
491 * UINT uMsg message to send
492 * WPARAM wParam first message parameter
493 * LPARAM lParam second message parameter
494 * SENDASYNCPROC lpResultCallBack function to receive message value
495 * DWORD dwData value to pass to callback function
496 * Variables :
497 * Result : If the function succeeds, the return value is TRUE.
498 * If the function fails, the return value is FALSE. To get extended
499 * error information, call GetLastError.
500 * Remark :
501 * Status :
502 *
503 * Author : Wine
504 *****************************************************************************/
505
506BOOL WIN32API SendMessageCallbackW(HWND hwnd,
507 UINT uMsg,
508 WPARAM wParam,
509 LPARAM lParam,
510 SENDASYNCPROC lpResultCallBack,
511 DWORD dwData)
512{
513 struct send_message_info info;
514 LRESULT result;
515 DWORD dest_tid;
516
517#if 0
518 if (is_pointer_message(msg))
519 {
520 SetLastError(ERROR_INVALID_PARAMETER);
521 return FALSE;
522 }
523#endif
524
525 dprintf(("USER32:SendMessageCallBackW (%08xh,%08xh,%08xh,%08xh,%08xh,%08x)",
526 hwnd, uMsg, wParam, lParam, lpResultCallBack, dwData));
527
528 info.type = MSG_CALLBACK_UNICODE;
529 info.hwnd = hwnd;
530 info.msg = uMsg;
531 info.wparam = wParam;
532 info.lparam = lParam;
533 info.callback = lpResultCallBack;
534 info.data = dwData;
535
536 if (is_broadcast(hwnd))
537 {
538 EnumWindows( broadcast_message_callback, (LPARAM)&info );
539 return TRUE;
540 }
541
542 if (!(dest_tid = GetWindowThreadProcessId( hwnd, NULL ))) return FALSE;
543
544 if (dest_tid == GetCurrentThreadId())
545 {
546 result = call_window_proc( hwnd, uMsg, wParam, lParam, TRUE );
547 lpResultCallBack( hwnd, uMsg, dwData, result );
548 return TRUE;
549 }
550 else
551 {
552 dprintf(("!WARNING!: callback will not be called" ));
553
554 //otherwise use PostMessage to send it to the right process/thread
555 dprintf(("SendMessageCallbackW (inter-process) %x %x %x %x", hwnd, uMsg, wParam, lParam));
556 PostMessageW(hwnd, uMsg, wParam, lParam);
557 return TRUE;
558 }
559}
560/*****************************************************************************
561 * Name : long WIN32API BroadcastSystemMessage
562 * Purpose : The BroadcastSystemMessage function sends a message to the given
563 * recipients. The recipients can be applications, installable
564 * drivers, Windows-based network drivers, system-level device
565 * drivers, or any combination of these system components.
566 * Parameters: DWORD dwFlags,
567 LPDWORD lpdwRecipients,
568 UINT uiMessage,
569 WPARAM wParam,
570 LPARAM lParam
571 * Variables :
572 * Result : If the function succeeds, the return value is a positive value.
573 * If the function is unable to broadcast the message, the return value is -1.
574 * If the dwFlags parameter is BSF_QUERY and at least one recipient returned FALSE to the corresponding message, the return value is zero.
575 * Remark :
576 * Status : UNTESTED STUB
577 *
578 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
579 *****************************************************************************/
580
581long WIN32API BroadcastSystemMessage(DWORD dwFlags,
582 LPDWORD lpdwRecipients,
583 UINT uiMessage,
584 WPARAM wParam,
585 LPARAM lParam)
586{
587 dprintf(("USER32:BroadcastSystemMessage(%08xh,%08xh,%08xh,%08xh,%08x) not implemented.\n",
588 dwFlags,
589 lpdwRecipients,
590 uiMessage,
591 wParam,
592 lParam));
593
594 return (-1);
595}
596#if 0
597//******************************************************************************
598//******************************************************************************
599VOID WIN32API PostQuitMessage( int nExitCode)
600{
601 dprintf(("USER32: PostQuitMessage %d", nExitCode));
602 PostThreadMessageW(GetCurrentThreadId(), WM_QUIT, nExitCode, 0);
603}
604//******************************************************************************
605//******************************************************************************
606#endif
Note: See TracBrowser for help on using the repository browser.