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

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

minor logging updates

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