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
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
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
) );
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 */
80 union packed_structs ps
;
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
);
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
);
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
)
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
);
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
);
128 params
->wparam
= wParam
;
129 params
->lparam
= lParam
;
130 params
->result
= result
;
132 params
->mapping
= mapping
;
133 params
->dpi_awareness
= get_window_dpi_awareness_context( params
->hwnd
);
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();
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
--;
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
;
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 /***********************************************************************
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
)
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
) );
199 push_data( data
, (WCHAR
*)lparam
, (res
+ 1) * sizeof(WCHAR
) );
201 case WM_GETMINMAXINFO
:
202 push_data( data
, (MINMAXINFO
*)lparam
, sizeof(MINMAXINFO
) );
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
) );
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
) );
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
) );
243 case SBM_GETSCROLLINFO
:
244 push_data( data
, (SCROLLINFO
*)lparam
, sizeof(SCROLLINFO
) );
248 case CB_GETDROPPEDCONTROLRECT
:
251 push_data( data
, (RECT
*)lparam
, sizeof(RECT
) );
255 WORD
*ptr
= (WORD
*)lparam
;
256 push_data( data
, ptr
, ptr
[-1] * sizeof(WCHAR
) );
260 push_data( data
, (UINT
*)lparam
, wparam
* sizeof(UINT
) );
262 case WM_MDIGETACTIVE
:
263 if (lparam
) push_data( data
, (BOOL
*)lparam
, sizeof(BOOL
) );
267 push_data( data
, (RECT
*)lparam
, sizeof(RECT
) );
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
) );
287 if (wparam
) push_data( data
, (DWORD
*)wparam
, sizeof(DWORD
) );
288 if (lparam
) push_data( data
, (DWORD
*)lparam
, sizeof(DWORD
) );
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
) );
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
) );
314 case WM_ASKCBFORMATNAME
:
315 push_data( data
, (WCHAR
*)lparam
, (lstrlenW((WCHAR
*)lparam
) + 1) * sizeof(WCHAR
) );
320 /***********************************************************************
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
);
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
;
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
)
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
:
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
);
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
);
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
)
436 if (info
->cbSize
!= sizeof(*info
))
438 SetLastError( ERROR_INVALID_PARAMETER
);
442 SERVER_START_REQ( get_thread_input
)
445 if ((ret
= !wine_server_call_err( req
)))
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
;
467 /**********************************************************************
470 LRESULT
dispatch_message( const MSG
*msg
, BOOL ansi
)
472 struct win_proc_params params
;
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( ¶ms
, msg
->hwnd
, msg
->message
,
481 msg
->wParam
, NtGetTickCount(), ansi
))
485 dispatch_win_proc_params( ¶ms
, sizeof(params
) );
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( ¶ms
, msg
->hwnd
, msg
->message
, msg
->wParam
, msg
->lParam
,
499 &retval
, ansi
, WMCHAR_MAP_DISPATCHMESSAGE
))
500 dispatch_win_proc_params( ¶ms
, 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
);
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
)
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
);
542 req
->lparam
= (ULONG_PTR
)winproc
;
543 if (!wine_server_call_err( req
))
546 if (!ret
) ret
= TRUE
;
552 TRACE( "Added %p %lx %p timeout %d\n", hwnd
, id
, winproc
, timeout
);
556 /***********************************************************************
557 * NtUserSetSystemTimer (win32u.@)
559 UINT_PTR WINAPI
NtUserSetSystemTimer( HWND hwnd
, UINT_PTR id
, UINT timeout
, TIMERPROC proc
)
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
;
574 req
->lparam
= (ULONG_PTR
)winproc
;
575 if (!wine_server_call_err( req
))
578 if (!ret
) ret
= TRUE
;
584 TRACE( "Added %p %lx %p timeout %d\n", hwnd
, id
, winproc
, timeout
);
588 /***********************************************************************
589 * NtUserKillTimer (win32u.@)
591 BOOL WINAPI
NtUserKillTimer( HWND hwnd
, UINT_PTR id
)
595 SERVER_START_REQ( kill_win_timer
)
597 req
->win
= wine_server_user_handle( hwnd
);
600 ret
= !wine_server_call_err( req
);
606 /* see KillSystemTimer */
607 BOOL
kill_system_timer( HWND hwnd
, UINT_PTR id
)
611 SERVER_START_REQ( kill_win_timer
)
613 req
->win
= wine_server_user_handle( hwnd
);
614 req
->msg
= WM_SYSTIMER
;
616 ret
= !wine_server_call_err( req
);
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
;
628 ? user_callbacks
->pSendMessageA( hwnd
, msg
, wparam
, lparam
)
629 : user_callbacks
->pSendMessageW( hwnd
, msg
, wparam
, lparam
);
633 /* see SendMessageW */
634 LRESULT
send_message( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
637 send_window_message( hwnd
, msg
, wparam
, lparam
, &result
, FALSE
);
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
)
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
);
668 spy_enter_message( ansi
, hwnd
, msg
, wparam
, lparam
);
671 spy_exit_message( ansi
, hwnd
, msg
, result_info
, wparam
, lparam
);
674 FIXME( "%p %x %lx %lx %lx %x %x\n", hwnd
, msg
, wparam
, lparam
, result_info
, type
, ansi
);