win32u: Move reply_message_result implementation from user32.
[wine.git] / dlls / win32u / message.c
blob2a582d7c85b6e19c5e6159e42e3a37d5d87b6df9
1 /*
2 * Window messaging support
4 * Copyright 2001 Alexandre Julliard
5 * Copyright 2008 Maarten Lankhorst
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #if 0
24 #pragma makedep unix
25 #endif
27 #include "win32u_private.h"
28 #include "ntuser_private.h"
29 #include "wine/server.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(msg);
34 #define MAX_WINPROC_RECURSION 64
36 #define MAX_PACK_COUNT 4
38 struct packed_hook_extra_info
40 user_handle_t handle;
41 DWORD __pad;
42 ULONGLONG lparam;
45 /* the structures are unpacked on top of the packed ones, so make sure they fit */
46 C_ASSERT( sizeof(struct packed_CREATESTRUCTW) >= sizeof(CREATESTRUCTW) );
47 C_ASSERT( sizeof(struct packed_DRAWITEMSTRUCT) >= sizeof(DRAWITEMSTRUCT) );
48 C_ASSERT( sizeof(struct packed_MEASUREITEMSTRUCT) >= sizeof(MEASUREITEMSTRUCT) );
49 C_ASSERT( sizeof(struct packed_DELETEITEMSTRUCT) >= sizeof(DELETEITEMSTRUCT) );
50 C_ASSERT( sizeof(struct packed_COMPAREITEMSTRUCT) >= sizeof(COMPAREITEMSTRUCT) );
51 C_ASSERT( sizeof(struct packed_WINDOWPOS) >= sizeof(WINDOWPOS) );
52 C_ASSERT( sizeof(struct packed_COPYDATASTRUCT) >= sizeof(COPYDATASTRUCT) );
53 C_ASSERT( sizeof(struct packed_HELPINFO) >= sizeof(HELPINFO) );
54 C_ASSERT( sizeof(struct packed_NCCALCSIZE_PARAMS) >= sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS) );
55 C_ASSERT( sizeof(struct packed_MSG) >= sizeof(MSG) );
56 C_ASSERT( sizeof(struct packed_MDINEXTMENU) >= sizeof(MDINEXTMENU) );
57 C_ASSERT( sizeof(struct packed_MDICREATESTRUCTW) >= sizeof(MDICREATESTRUCTW) );
58 C_ASSERT( sizeof(struct packed_hook_extra_info) >= sizeof(struct hook_extra_info) );
60 union packed_structs
62 struct packed_CREATESTRUCTW cs;
63 struct packed_DRAWITEMSTRUCT dis;
64 struct packed_MEASUREITEMSTRUCT mis;
65 struct packed_DELETEITEMSTRUCT dls;
66 struct packed_COMPAREITEMSTRUCT cis;
67 struct packed_WINDOWPOS wp;
68 struct packed_COPYDATASTRUCT cds;
69 struct packed_HELPINFO hi;
70 struct packed_NCCALCSIZE_PARAMS ncp;
71 struct packed_MSG msg;
72 struct packed_MDINEXTMENU mnm;
73 struct packed_MDICREATESTRUCTW mcs;
74 struct packed_hook_extra_info hook;
77 /* description of the data fields that need to be packed along with a sent message */
78 struct packed_message
80 union packed_structs ps;
81 int count;
82 const void *data[MAX_PACK_COUNT];
83 size_t size[MAX_PACK_COUNT];
86 static BOOL init_win_proc_params( struct win_proc_params *params, HWND hwnd, UINT msg,
87 WPARAM wparam, LPARAM lparam, BOOL ansi )
89 if (!params->func) return FALSE;
91 user_check_not_lock();
93 params->hwnd = get_full_window_handle( hwnd );
94 params->msg = msg;
95 params->wparam = wparam;
96 params->lparam = lparam;
97 params->ansi = params->ansi_dst = ansi;
98 params->is_dialog = FALSE;
99 params->mapping = WMCHAR_MAP_CALLWINDOWPROC;
100 params->dpi_awareness = get_window_dpi_awareness_context( params->hwnd );
101 get_winproc_params( params );
102 return TRUE;
105 static BOOL init_window_call_params( struct win_proc_params *params, HWND hwnd, UINT msg, WPARAM wParam,
106 LPARAM lParam, LRESULT *result, BOOL ansi,
107 enum wm_char_mapping mapping )
109 WND *win;
111 user_check_not_lock();
113 if (!(win = get_win_ptr( hwnd ))) return FALSE;
114 if (win == WND_OTHER_PROCESS || win == WND_DESKTOP) return FALSE;
115 if (win->tid != GetCurrentThreadId())
117 release_win_ptr( win );
118 return FALSE;
120 params->func = win->winproc;
121 params->ansi_dst = !(win->flags & WIN_ISUNICODE);
122 params->is_dialog = win->dlgInfo != NULL;
123 release_win_ptr( win );
125 params->hwnd = get_full_window_handle( hwnd );
126 get_winproc_params( params );
127 params->msg = msg;
128 params->wparam = wParam;
129 params->lparam = lParam;
130 params->result = result;
131 params->ansi = ansi;
132 params->mapping = mapping;
133 params->dpi_awareness = get_window_dpi_awareness_context( params->hwnd );
134 return TRUE;
137 static BOOL dispatch_win_proc_params( struct win_proc_params *params, size_t size )
139 struct user_thread_info *thread_info = get_user_thread_info();
140 void *ret_ptr;
141 ULONG ret_len;
143 if (thread_info->recursion_count > MAX_WINPROC_RECURSION) return FALSE;
144 thread_info->recursion_count++;
146 KeUserModeCallback( NtUserCallWindowProc, params, size, &ret_ptr, &ret_len );
148 thread_info->recursion_count--;
149 return TRUE;
152 /* add a data field to a packed message */
153 static inline void push_data( struct packed_message *data, const void *ptr, size_t size )
155 data->data[data->count] = ptr;
156 data->size[data->count] = size;
157 data->count++;
160 /* pack a pointer into a 32/64 portable format */
161 static inline ULONGLONG pack_ptr( const void *ptr )
163 return (ULONG_PTR)ptr;
166 /***********************************************************************
167 * pack_reply
169 * Pack a reply to a message for sending to another process.
171 static void pack_reply( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam,
172 LRESULT res, struct packed_message *data )
174 data->count = 0;
175 switch(message)
177 case WM_NCCREATE:
178 case WM_CREATE:
180 CREATESTRUCTW *cs = (CREATESTRUCTW *)lparam;
181 data->ps.cs.lpCreateParams = (ULONG_PTR)cs->lpCreateParams;
182 data->ps.cs.hInstance = (ULONG_PTR)cs->hInstance;
183 data->ps.cs.hMenu = wine_server_user_handle( cs->hMenu );
184 data->ps.cs.hwndParent = wine_server_user_handle( cs->hwndParent );
185 data->ps.cs.cy = cs->cy;
186 data->ps.cs.cx = cs->cx;
187 data->ps.cs.y = cs->y;
188 data->ps.cs.x = cs->x;
189 data->ps.cs.style = cs->style;
190 data->ps.cs.dwExStyle = cs->dwExStyle;
191 data->ps.cs.lpszName = (ULONG_PTR)cs->lpszName;
192 data->ps.cs.lpszClass = (ULONG_PTR)cs->lpszClass;
193 push_data( data, &data->ps.cs, sizeof(data->ps.cs) );
194 break;
196 case WM_GETTEXT:
197 case CB_GETLBTEXT:
198 case LB_GETTEXT:
199 push_data( data, (WCHAR *)lparam, (res + 1) * sizeof(WCHAR) );
200 break;
201 case WM_GETMINMAXINFO:
202 push_data( data, (MINMAXINFO *)lparam, sizeof(MINMAXINFO) );
203 break;
204 case WM_MEASUREITEM:
206 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lparam;
207 data->ps.mis.CtlType = mis->CtlType;
208 data->ps.mis.CtlID = mis->CtlID;
209 data->ps.mis.itemID = mis->itemID;
210 data->ps.mis.itemWidth = mis->itemWidth;
211 data->ps.mis.itemHeight = mis->itemHeight;
212 data->ps.mis.itemData = mis->itemData;
213 push_data( data, &data->ps.mis, sizeof(data->ps.mis) );
214 break;
216 case WM_WINDOWPOSCHANGING:
217 case WM_WINDOWPOSCHANGED:
219 WINDOWPOS *wp = (WINDOWPOS *)lparam;
220 data->ps.wp.hwnd = wine_server_user_handle( wp->hwnd );
221 data->ps.wp.hwndInsertAfter = wine_server_user_handle( wp->hwndInsertAfter );
222 data->ps.wp.x = wp->x;
223 data->ps.wp.y = wp->y;
224 data->ps.wp.cx = wp->cx;
225 data->ps.wp.cy = wp->cy;
226 data->ps.wp.flags = wp->flags;
227 push_data( data, &data->ps.wp, sizeof(data->ps.wp) );
228 break;
230 case WM_GETDLGCODE:
231 if (lparam)
233 MSG *msg = (MSG *)lparam;
234 data->ps.msg.hwnd = wine_server_user_handle( msg->hwnd );
235 data->ps.msg.message = msg->message;
236 data->ps.msg.wParam = msg->wParam;
237 data->ps.msg.lParam = msg->lParam;
238 data->ps.msg.time = msg->time;
239 data->ps.msg.pt = msg->pt;
240 push_data( data, &data->ps.msg, sizeof(data->ps.msg) );
242 break;
243 case SBM_GETSCROLLINFO:
244 push_data( data, (SCROLLINFO *)lparam, sizeof(SCROLLINFO) );
245 break;
246 case EM_GETRECT:
247 case LB_GETITEMRECT:
248 case CB_GETDROPPEDCONTROLRECT:
249 case WM_SIZING:
250 case WM_MOVING:
251 push_data( data, (RECT *)lparam, sizeof(RECT) );
252 break;
253 case EM_GETLINE:
255 WORD *ptr = (WORD *)lparam;
256 push_data( data, ptr, ptr[-1] * sizeof(WCHAR) );
257 break;
259 case LB_GETSELITEMS:
260 push_data( data, (UINT *)lparam, wparam * sizeof(UINT) );
261 break;
262 case WM_MDIGETACTIVE:
263 if (lparam) push_data( data, (BOOL *)lparam, sizeof(BOOL) );
264 break;
265 case WM_NCCALCSIZE:
266 if (!wparam)
267 push_data( data, (RECT *)lparam, sizeof(RECT) );
268 else
270 NCCALCSIZE_PARAMS *ncp = (NCCALCSIZE_PARAMS *)lparam;
271 data->ps.ncp.rgrc[0] = ncp->rgrc[0];
272 data->ps.ncp.rgrc[1] = ncp->rgrc[1];
273 data->ps.ncp.rgrc[2] = ncp->rgrc[2];
274 data->ps.ncp.hwnd = wine_server_user_handle( ncp->lppos->hwnd );
275 data->ps.ncp.hwndInsertAfter = wine_server_user_handle( ncp->lppos->hwndInsertAfter );
276 data->ps.ncp.x = ncp->lppos->x;
277 data->ps.ncp.y = ncp->lppos->y;
278 data->ps.ncp.cx = ncp->lppos->cx;
279 data->ps.ncp.cy = ncp->lppos->cy;
280 data->ps.ncp.flags = ncp->lppos->flags;
281 push_data( data, &data->ps.ncp, sizeof(data->ps.ncp) );
283 break;
284 case EM_GETSEL:
285 case SBM_GETRANGE:
286 case CB_GETEDITSEL:
287 if (wparam) push_data( data, (DWORD *)wparam, sizeof(DWORD) );
288 if (lparam) push_data( data, (DWORD *)lparam, sizeof(DWORD) );
289 break;
290 case WM_NEXTMENU:
292 MDINEXTMENU *mnm = (MDINEXTMENU *)lparam;
293 data->ps.mnm.hmenuIn = wine_server_user_handle( mnm->hmenuIn );
294 data->ps.mnm.hmenuNext = wine_server_user_handle( mnm->hmenuNext );
295 data->ps.mnm.hwndNext = wine_server_user_handle( mnm->hwndNext );
296 push_data( data, &data->ps.mnm, sizeof(data->ps.mnm) );
297 break;
299 case WM_MDICREATE:
301 MDICREATESTRUCTW *mcs = (MDICREATESTRUCTW *)lparam;
302 data->ps.mcs.szClass = pack_ptr( mcs->szClass );
303 data->ps.mcs.szTitle = pack_ptr( mcs->szTitle );
304 data->ps.mcs.hOwner = pack_ptr( mcs->hOwner );
305 data->ps.mcs.x = mcs->x;
306 data->ps.mcs.y = mcs->y;
307 data->ps.mcs.cx = mcs->cx;
308 data->ps.mcs.cy = mcs->cy;
309 data->ps.mcs.style = mcs->style;
310 data->ps.mcs.lParam = mcs->lParam;
311 push_data( data, &data->ps.mcs, sizeof(data->ps.mcs) );
312 break;
314 case WM_ASKCBFORMATNAME:
315 push_data( data, (WCHAR *)lparam, (lstrlenW((WCHAR *)lparam) + 1) * sizeof(WCHAR) );
316 break;
320 /***********************************************************************
321 * reply_message
323 * Send a reply to a sent message.
325 static void reply_message( struct received_message_info *info, LRESULT result, MSG *msg )
327 struct packed_message data;
328 int i, replied = info->flags & ISMEX_REPLIED;
330 if (info->flags & ISMEX_NOTIFY) return; /* notify messages don't get replies */
331 if (!msg && replied) return; /* replied already */
333 memset( &data, 0, sizeof(data) );
334 info->flags |= ISMEX_REPLIED;
336 if (info->type == MSG_OTHER_PROCESS && !replied)
338 pack_reply( msg->hwnd, msg->message, msg->wParam, msg->lParam, result, &data );
341 SERVER_START_REQ( reply_message )
343 req->result = result;
344 req->remove = msg != NULL;
345 for (i = 0; i < data.count; i++) wine_server_add_data( req, data.data[i], data.size[i] );
346 wine_server_call( req );
348 SERVER_END_REQ;
351 /***********************************************************************
352 * reply_message_result
354 * Send a reply to a sent message and update thread receive info.
356 BOOL reply_message_result( LRESULT result, MSG *msg )
358 struct received_message_info *info = get_user_thread_info()->receive_info;
360 if (!info) return FALSE;
361 reply_message( info, result, msg );
362 if (msg) get_user_thread_info()->receive_info = info->prev;
363 return TRUE;
366 /***********************************************************************
367 * handle_internal_message
369 * Handle an internal Wine message instead of calling the window proc.
371 LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
373 switch(msg)
375 case WM_WINE_DESTROYWINDOW:
376 return destroy_window( hwnd );
377 case WM_WINE_SETWINDOWPOS:
378 if (is_desktop_window( hwnd )) return 0;
379 return set_window_pos( (WINDOWPOS *)lparam, 0, 0 );
380 case WM_WINE_SHOWWINDOW:
381 if (is_desktop_window( hwnd )) return 0;
382 return NtUserShowWindow( hwnd, wparam );
383 case WM_WINE_SETPARENT:
384 if (is_desktop_window( hwnd )) return 0;
385 return HandleToUlong( NtUserSetParent( hwnd, UlongToHandle(wparam) ));
386 case WM_WINE_SETWINDOWLONG:
387 return set_window_long( hwnd, (short)LOWORD(wparam), HIWORD(wparam), lparam, FALSE );
388 case WM_WINE_SETSTYLE:
389 if (is_desktop_window( hwnd )) return 0;
390 return set_window_style( hwnd, wparam, lparam );
391 case WM_WINE_SETACTIVEWINDOW:
392 if (!wparam && NtUserGetForegroundWindow() == hwnd) return 0;
393 return (LRESULT)NtUserSetActiveWindow( (HWND)wparam );
394 case WM_WINE_KEYBOARD_LL_HOOK:
395 case WM_WINE_MOUSE_LL_HOOK:
397 struct hook_extra_info *h_extra = (struct hook_extra_info *)lparam;
399 return call_current_hook( h_extra->handle, HC_ACTION, wparam, h_extra->lparam );
401 case WM_WINE_CLIPCURSOR:
402 if (wparam)
404 RECT rect;
405 get_clip_cursor( &rect );
406 return user_driver->pClipCursor( &rect );
408 return user_driver->pClipCursor( NULL );
409 case WM_WINE_UPDATEWINDOWSTATE:
410 update_window_state( hwnd );
411 return 0;
412 default:
413 if (msg >= WM_WINE_FIRST_DRIVER_MSG && msg <= WM_WINE_LAST_DRIVER_MSG)
414 return user_driver->pWindowMessage( hwnd, msg, wparam, lparam );
415 FIXME( "unknown internal message %x\n", msg );
416 return 0;
420 /***********************************************************************
421 * NtUserWaitForInputIdle (win32u.@)
423 DWORD WINAPI NtUserWaitForInputIdle( HANDLE process, DWORD timeout, BOOL wow )
425 if (!user_callbacks) return 0;
426 return user_callbacks->pWaitForInputIdle( process, timeout );
429 /**********************************************************************
430 * NtUserGetGUIThreadInfo (win32u.@)
432 BOOL WINAPI NtUserGetGUIThreadInfo( DWORD id, GUITHREADINFO *info )
434 BOOL ret;
436 if (info->cbSize != sizeof(*info))
438 SetLastError( ERROR_INVALID_PARAMETER );
439 return FALSE;
442 SERVER_START_REQ( get_thread_input )
444 req->tid = id;
445 if ((ret = !wine_server_call_err( req )))
447 info->flags = 0;
448 info->hwndActive = wine_server_ptr_handle( reply->active );
449 info->hwndFocus = wine_server_ptr_handle( reply->focus );
450 info->hwndCapture = wine_server_ptr_handle( reply->capture );
451 info->hwndMenuOwner = wine_server_ptr_handle( reply->menu_owner );
452 info->hwndMoveSize = wine_server_ptr_handle( reply->move_size );
453 info->hwndCaret = wine_server_ptr_handle( reply->caret );
454 info->rcCaret.left = reply->rect.left;
455 info->rcCaret.top = reply->rect.top;
456 info->rcCaret.right = reply->rect.right;
457 info->rcCaret.bottom = reply->rect.bottom;
458 if (reply->menu_owner) info->flags |= GUI_INMENUMODE;
459 if (reply->move_size) info->flags |= GUI_INMOVESIZE;
460 if (reply->caret) info->flags |= GUI_CARETBLINKING;
463 SERVER_END_REQ;
464 return ret;
467 /**********************************************************************
468 * dispatch_message
470 LRESULT dispatch_message( const MSG *msg, BOOL ansi )
472 struct win_proc_params params;
473 LRESULT retval = 0;
475 /* Process timer messages */
476 if (msg->lParam && (msg->message == WM_TIMER || msg->message == WM_SYSTIMER))
478 params.func = (WNDPROC)msg->lParam;
479 params.result = &retval; /* FIXME */
480 if (!init_win_proc_params( &params, msg->hwnd, msg->message,
481 msg->wParam, NtGetTickCount(), ansi ))
482 return 0;
483 __TRY
485 dispatch_win_proc_params( &params, sizeof(params) );
487 __EXCEPT
489 retval = 0;
491 __ENDTRY
492 return retval;
494 if (!msg->hwnd) return 0;
496 spy_enter_message( SPY_DISPATCHMESSAGE, msg->hwnd, msg->message, msg->wParam, msg->lParam );
498 if (init_window_call_params( &params, msg->hwnd, msg->message, msg->wParam, msg->lParam,
499 &retval, ansi, WMCHAR_MAP_DISPATCHMESSAGE ))
500 dispatch_win_proc_params( &params, sizeof(params) );
501 else if (!is_window( msg->hwnd )) SetLastError( ERROR_INVALID_WINDOW_HANDLE );
502 else SetLastError( ERROR_MESSAGE_SYNC_ONLY );
504 spy_exit_message( SPY_RESULT_OK, msg->hwnd, msg->message, retval, msg->wParam, msg->lParam );
506 if (msg->message == WM_PAINT)
508 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
509 HRGN hrgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
510 NtUserGetUpdateRgn( msg->hwnd, hrgn, TRUE );
511 NtGdiDeleteObjectApp( hrgn );
513 return retval;
516 /**********************************************************************
517 * NtUserDispatchMessage (win32u.@)
519 LRESULT WINAPI NtUserDispatchMessage( const MSG *msg )
521 return dispatch_message( msg, FALSE );
524 /***********************************************************************
525 * NtUserSetTimer (win32u.@)
527 UINT_PTR WINAPI NtUserSetTimer( HWND hwnd, UINT_PTR id, UINT timeout, TIMERPROC proc, ULONG tolerance )
529 UINT_PTR ret;
530 WNDPROC winproc = 0;
532 if (proc) winproc = alloc_winproc( (WNDPROC)proc, TRUE );
534 timeout = min( max( USER_TIMER_MINIMUM, timeout ), USER_TIMER_MAXIMUM );
536 SERVER_START_REQ( set_win_timer )
538 req->win = wine_server_user_handle( hwnd );
539 req->msg = WM_TIMER;
540 req->id = id;
541 req->rate = timeout;
542 req->lparam = (ULONG_PTR)winproc;
543 if (!wine_server_call_err( req ))
545 ret = reply->id;
546 if (!ret) ret = TRUE;
548 else ret = 0;
550 SERVER_END_REQ;
552 TRACE( "Added %p %lx %p timeout %d\n", hwnd, id, winproc, timeout );
553 return ret;
556 /***********************************************************************
557 * NtUserSetSystemTimer (win32u.@)
559 UINT_PTR WINAPI NtUserSetSystemTimer( HWND hwnd, UINT_PTR id, UINT timeout, TIMERPROC proc )
561 UINT_PTR ret;
562 WNDPROC winproc = 0;
564 if (proc) winproc = alloc_winproc( (WNDPROC)proc, TRUE );
566 timeout = min( max( USER_TIMER_MINIMUM, timeout ), USER_TIMER_MAXIMUM );
568 SERVER_START_REQ( set_win_timer )
570 req->win = wine_server_user_handle( hwnd );
571 req->msg = WM_SYSTIMER;
572 req->id = id;
573 req->rate = timeout;
574 req->lparam = (ULONG_PTR)winproc;
575 if (!wine_server_call_err( req ))
577 ret = reply->id;
578 if (!ret) ret = TRUE;
580 else ret = 0;
582 SERVER_END_REQ;
584 TRACE( "Added %p %lx %p timeout %d\n", hwnd, id, winproc, timeout );
585 return ret;
588 /***********************************************************************
589 * NtUserKillTimer (win32u.@)
591 BOOL WINAPI NtUserKillTimer( HWND hwnd, UINT_PTR id )
593 BOOL ret;
595 SERVER_START_REQ( kill_win_timer )
597 req->win = wine_server_user_handle( hwnd );
598 req->msg = WM_TIMER;
599 req->id = id;
600 ret = !wine_server_call_err( req );
602 SERVER_END_REQ;
603 return ret;
606 /* see KillSystemTimer */
607 BOOL kill_system_timer( HWND hwnd, UINT_PTR id )
609 BOOL ret;
611 SERVER_START_REQ( kill_win_timer )
613 req->win = wine_server_user_handle( hwnd );
614 req->msg = WM_SYSTIMER;
615 req->id = id;
616 ret = !wine_server_call_err( req );
618 SERVER_END_REQ;
619 return ret;
622 static BOOL send_window_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
623 LRESULT *result, BOOL ansi )
625 /* FIXME: move implementation from user32 */
626 if (!user_callbacks) return FALSE;
627 *result = ansi
628 ? user_callbacks->pSendMessageA( hwnd, msg, wparam, lparam )
629 : user_callbacks->pSendMessageW( hwnd, msg, wparam, lparam );
630 return TRUE;
633 /* see SendMessageW */
634 LRESULT send_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
636 LRESULT result = 0;
637 send_window_message( hwnd, msg, wparam, lparam, &result, FALSE );
638 return result;
641 /* see SendNotifyMessageW */
642 static BOOL send_notify_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi )
644 return user_callbacks && user_callbacks->pSendNotifyMessageW( hwnd, msg, wparam, lparam );
647 /* see PostMessageW */
648 LRESULT post_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
650 /* FIXME: move implementation from user32 */
651 if (!user_callbacks) return 0;
652 return user_callbacks->pPostMessageW( hwnd, msg, wparam, lparam );
655 BOOL WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
656 ULONG_PTR result_info, DWORD type, BOOL ansi )
658 switch (type)
660 case FNID_CALLWNDPROC:
661 return init_win_proc_params( (struct win_proc_params *)result_info, hwnd, msg,
662 wparam, lparam, ansi );
663 case FNID_SENDMESSAGE:
664 return send_window_message( hwnd, msg, wparam, lparam, (LRESULT *)result_info, ansi );
665 case FNID_SENDNOTIFYMESSAGE:
666 return send_notify_message( hwnd, msg, wparam, lparam, ansi );
667 case FNID_SPYENTER:
668 spy_enter_message( ansi, hwnd, msg, wparam, lparam );
669 return 0;
670 case FNID_SPYEXIT:
671 spy_exit_message( ansi, hwnd, msg, result_info, wparam, lparam );
672 return 0;
673 default:
674 FIXME( "%p %x %lx %lx %lx %x %x\n", hwnd, msg, wparam, lparam, result_info, type, ansi );
676 return 0;