2 * Window procedure callbacks
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1996 Alexandre Julliard
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
22 #include "user_private.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(msg
);
29 WINE_DECLARE_DEBUG_CHANNEL(relay
);
33 struct packed_CREATESTRUCTW cs
;
34 struct packed_DRAWITEMSTRUCT dis
;
35 struct packed_MEASUREITEMSTRUCT mis
;
36 struct packed_DELETEITEMSTRUCT dls
;
37 struct packed_COMPAREITEMSTRUCT cis
;
38 struct packed_WINDOWPOS wp
;
39 struct packed_COPYDATASTRUCT cds
;
40 struct packed_HELPINFO hi
;
41 struct packed_NCCALCSIZE_PARAMS ncp
;
42 struct packed_MSG msg
;
43 struct packed_MDINEXTMENU mnm
;
44 struct packed_MDICREATESTRUCTW mcs
;
47 static inline void *get_buffer( void *static_buffer
, size_t size
, size_t need
)
49 if (size
>= need
) return static_buffer
;
50 return HeapAlloc( GetProcessHeap(), 0, need
);
53 static inline void free_buffer( void *static_buffer
, void *buffer
)
55 if (buffer
!= static_buffer
) HeapFree( GetProcessHeap(), 0, buffer
);
59 /* Some window procedures modify registers they shouldn't, or are not
60 * properly declared stdcall; so we need a small assembly wrapper to
62 extern LRESULT
WINPROC_wrapper( WNDPROC proc
, HWND hwnd
, UINT msg
,
63 WPARAM wParam
, LPARAM lParam
);
64 __ASM_GLOBAL_FUNC( WINPROC_wrapper
,
66 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
67 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
69 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
71 __ASM_CFI(".cfi_rel_offset %edi,-4\n\t")
73 __ASM_CFI(".cfi_rel_offset %esi,-8\n\t")
75 __ASM_CFI(".cfi_rel_offset %ebx,-12\n\t")
76 /* TreePad X Enterprise assumes that edi is < 0x80000000 in WM_TIMER messages */
83 "movl 8(%ebp),%eax\n\t"
85 "leal -12(%ebp),%esp\n\t"
87 __ASM_CFI(".cfi_same_value %ebx\n\t")
89 __ASM_CFI(".cfi_same_value %esi\n\t")
91 __ASM_CFI(".cfi_same_value %edi\n\t")
93 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
94 __ASM_CFI(".cfi_same_value %ebp\n\t")
97 static inline LRESULT
WINPROC_wrapper( WNDPROC proc
, HWND hwnd
, UINT msg
,
98 WPARAM wParam
, LPARAM lParam
)
100 return proc( hwnd
, msg
, wParam
, lParam
);
102 #endif /* __i386__ */
104 static WPARAM
map_wparam_char_WtoA( WPARAM wParam
, DWORD len
)
108 DWORD cp
= get_input_codepage();
110 len
= WideCharToMultiByte( cp
, 0, &wch
, 1, (LPSTR
)ch
, len
, NULL
, NULL
);
112 return MAKEWPARAM( (ch
[0] << 8) | ch
[1], HIWORD(wParam
) );
114 return MAKEWPARAM( ch
[0], HIWORD(wParam
) );
117 /* call a 32-bit window procedure */
118 static LRESULT
call_window_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
, LRESULT
*result
, void *arg
)
122 TRACE_(relay
)( "\1Call window proc %p (hwnd=%p,msg=%s,wp=%08Ix,lp=%08Ix)\n",
123 proc
, hwnd
, SPY_GetMsgName(msg
, hwnd
), wp
, lp
);
125 *result
= WINPROC_wrapper( proc
, hwnd
, msg
, wp
, lp
);
127 TRACE_(relay
)( "\1Ret window proc %p (hwnd=%p,msg=%s,wp=%08Ix,lp=%08Ix) retval=%08Ix\n",
128 proc
, hwnd
, SPY_GetMsgName(msg
, hwnd
), wp
, lp
, *result
);
132 /* call a 32-bit dialog procedure */
133 static LRESULT
call_dialog_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
, LRESULT
*result
, void *arg
)
135 DPI_AWARENESS_CONTEXT context
;
139 hwnd
= WIN_GetFullHandle( hwnd
);
140 TRACE_(relay
)( "\1Call dialog proc %p (hwnd=%p,msg=%s,wp=%08Ix,lp=%08Ix)\n",
141 proc
, hwnd
, SPY_GetMsgName(msg
, hwnd
), wp
, lp
);
143 context
= SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd
));
144 ret
= WINPROC_wrapper( proc
, hwnd
, msg
, wp
, lp
);
145 *result
= GetWindowLongPtrW( hwnd
, DWLP_MSGRESULT
);
146 SetThreadDpiAwarenessContext( context
);
148 TRACE_(relay
)( "\1Ret dialog proc %p (hwnd=%p,msg=%s,wp=%08Ix,lp=%08Ix) retval=%08Ix result=%08Ix\n",
149 proc
, hwnd
, SPY_GetMsgName(msg
, hwnd
), wp
, lp
, ret
, *result
);
154 /**********************************************************************
157 * Allocate a window procedure for a window or class.
159 * Note that allocated winprocs are never freed; the idea is that even if an app creates a
160 * lot of windows, it will usually only have a limited number of window procedures, so the
161 * array won't grow too large, and this way we avoid the need to track allocations per window.
163 static WNDPROC
WINPROC_AllocProc( WNDPROC func
, BOOL unicode
)
165 return (WNDPROC
)NtUserCallTwoParam( (UINT_PTR
)func
, !unicode
, NtUserAllocWinProc
);
169 /**********************************************************************
170 * WINPROC_TestLBForStr
172 * Return TRUE if the lparam is a string
174 static inline BOOL
WINPROC_TestLBForStr( HWND hwnd
, UINT msg
)
176 DWORD style
= GetWindowLongA( hwnd
, GWL_STYLE
);
177 if (msg
<= CB_MSGMAX
)
178 return (!(style
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) || (style
& CBS_HASSTRINGS
));
180 return (!(style
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) || (style
& LBS_HASSTRINGS
));
185 /**********************************************************************
186 * WINPROC_CallProcAtoW
188 * Call a window procedure, translating args from Ansi to Unicode.
190 LRESULT
WINPROC_CallProcAtoW( winproc_callback_t callback
, HWND hwnd
, UINT msg
, WPARAM wParam
,
191 LPARAM lParam
, LRESULT
*result
, void *arg
, enum wm_char_mapping mapping
)
195 TRACE_(msg
)("(hwnd=%p,msg=%s,wp=%08Ix,lp=%08Ix)\n",
196 hwnd
, SPY_GetMsgName(msg
, hwnd
), wParam
, lParam
);
203 WCHAR
*ptr
, buffer
[512];
204 CREATESTRUCTA
*csA
= (CREATESTRUCTA
*)lParam
;
205 CREATESTRUCTW csW
= *(CREATESTRUCTW
*)csA
;
206 MDICREATESTRUCTW mdi_cs
;
207 DWORD name_lenA
= 0, name_lenW
= 0, class_lenA
= 0, class_lenW
= 0;
209 if (!IS_INTRESOURCE(csA
->lpszClass
))
211 class_lenA
= strlen(csA
->lpszClass
) + 1;
212 RtlMultiByteToUnicodeSize( &class_lenW
, csA
->lpszClass
, class_lenA
);
214 if (!IS_INTRESOURCE(csA
->lpszName
))
216 name_lenA
= strlen(csA
->lpszName
) + 1;
217 RtlMultiByteToUnicodeSize( &name_lenW
, csA
->lpszName
, name_lenA
);
220 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), class_lenW
+ name_lenW
))) break;
225 RtlMultiByteToUnicodeN( ptr
, class_lenW
, NULL
, csA
->lpszClass
, class_lenA
);
229 csW
.lpszName
= ptr
+ class_lenW
/sizeof(WCHAR
);
230 RtlMultiByteToUnicodeN( ptr
+ class_lenW
/sizeof(WCHAR
), name_lenW
, NULL
,
231 csA
->lpszName
, name_lenA
);
234 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
236 mdi_cs
= *(MDICREATESTRUCTW
*)csA
->lpCreateParams
;
237 mdi_cs
.szTitle
= csW
.lpszName
;
238 mdi_cs
.szClass
= csW
.lpszClass
;
239 csW
.lpCreateParams
= &mdi_cs
;
242 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&csW
, result
, arg
);
243 free_buffer( buffer
, ptr
);
249 WCHAR
*ptr
, buffer
[512];
250 DWORD title_lenA
= 0, title_lenW
= 0, class_lenA
= 0, class_lenW
= 0;
251 MDICREATESTRUCTA
*csA
= (MDICREATESTRUCTA
*)lParam
;
252 MDICREATESTRUCTW csW
;
254 memcpy( &csW
, csA
, sizeof(csW
) );
256 if (!IS_INTRESOURCE(csA
->szTitle
))
258 title_lenA
= strlen(csA
->szTitle
) + 1;
259 RtlMultiByteToUnicodeSize( &title_lenW
, csA
->szTitle
, title_lenA
);
261 if (!IS_INTRESOURCE(csA
->szClass
))
263 class_lenA
= strlen(csA
->szClass
) + 1;
264 RtlMultiByteToUnicodeSize( &class_lenW
, csA
->szClass
, class_lenA
);
267 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), title_lenW
+ class_lenW
))) break;
272 RtlMultiByteToUnicodeN( ptr
, title_lenW
, NULL
, csA
->szTitle
, title_lenA
);
276 csW
.szClass
= ptr
+ title_lenW
/sizeof(WCHAR
);
277 RtlMultiByteToUnicodeN( ptr
+ title_lenW
/sizeof(WCHAR
), class_lenW
, NULL
,
278 csA
->szClass
, class_lenA
);
280 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&csW
, result
, arg
);
281 free_buffer( buffer
, ptr
);
286 case WM_ASKCBFORMATNAME
:
288 WCHAR
*ptr
, buffer
[512];
289 LPSTR str
= (LPSTR
)lParam
;
290 DWORD len
= wParam
* sizeof(WCHAR
);
292 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
))) break;
293 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
298 RtlUnicodeToMultiByteN( str
, wParam
- 1, &len
, ptr
, ret
* sizeof(WCHAR
) );
302 free_buffer( buffer
, ptr
);
307 case LB_INSERTSTRING
:
309 case LB_FINDSTRINGEXACT
:
310 case LB_SELECTSTRING
:
312 case CB_INSERTSTRING
:
314 case CB_FINDSTRINGEXACT
:
315 case CB_SELECTSTRING
:
316 if (!lParam
|| !WINPROC_TestLBForStr( hwnd
, msg
))
318 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
323 case WM_WININICHANGE
:
324 case WM_DEVMODECHANGE
:
329 if (!lParam
) ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
332 WCHAR
*ptr
, buffer
[512];
333 LPCSTR strA
= (LPCSTR
)lParam
;
334 DWORD lenW
, lenA
= strlen(strA
) + 1;
336 RtlMultiByteToUnicodeSize( &lenW
, strA
, lenA
);
337 if ((ptr
= get_buffer( buffer
, sizeof(buffer
), lenW
)))
339 RtlMultiByteToUnicodeN( ptr
, lenW
, NULL
, strA
, lenA
);
340 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
341 free_buffer( buffer
, ptr
);
348 if (lParam
&& WINPROC_TestLBForStr( hwnd
, msg
))
350 WCHAR buffer
[512]; /* FIXME: fixed sized buffer */
352 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)buffer
, result
, arg
);
356 RtlUnicodeToMultiByteN( (LPSTR
)lParam
, 512 * 3, &len
,
357 buffer
, (lstrlenW(buffer
) + 1) * sizeof(WCHAR
) );
361 else ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
366 WCHAR
*ptr
, buffer
[512];
367 WORD len
= *(WORD
*)lParam
;
369 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
* sizeof(WCHAR
) ))) break;
370 *((WORD
*)ptr
) = len
; /* store the length */
371 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
375 RtlUnicodeToMultiByteN( (LPSTR
)lParam
, len
, &reslen
, ptr
, *result
* sizeof(WCHAR
) );
376 if (reslen
< len
) ((LPSTR
)lParam
)[reslen
] = 0;
379 free_buffer( buffer
, ptr
);
386 MSG newmsg
= *(MSG
*)lParam
;
387 if (map_wparam_AtoW( newmsg
.message
, &newmsg
.wParam
, WMCHAR_MAP_NOMAPPING
))
388 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&newmsg
, result
, arg
);
390 else ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
399 case EM_SETPASSWORDCHAR
:
401 if (map_wparam_AtoW( msg
, &wParam
, mapping
))
402 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
405 case WM_GETTEXTLENGTH
:
406 case CB_GETLBTEXTLEN
:
408 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
411 WCHAR
*ptr
, buffer
[512];
413 DWORD len
= *result
+ 1;
414 /* Determine respective GETTEXT message */
415 UINT msgGetText
= (msg
== WM_GETTEXTLENGTH
) ? WM_GETTEXT
:
416 ((msg
== CB_GETLBTEXTLEN
) ? CB_GETLBTEXT
: LB_GETTEXT
);
417 /* wParam differs between the messages */
418 WPARAM wp
= (msg
== WM_GETTEXTLENGTH
) ? len
: wParam
;
420 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
* sizeof(WCHAR
) ))) break;
422 if (callback
== call_window_proc
) /* FIXME: hack */
423 callback( hwnd
, msgGetText
, wp
, (LPARAM
)ptr
, &tmp
, arg
);
425 tmp
= SendMessageW( hwnd
, msgGetText
, wp
, (LPARAM
)ptr
);
426 RtlUnicodeToMultiByteSize( &len
, ptr
, tmp
* sizeof(WCHAR
) );
428 free_buffer( buffer
, ptr
);
432 case WM_PAINTCLIPBOARD
:
433 case WM_SIZECLIPBOARD
:
434 FIXME_(msg
)( "message %s (0x%x) needs translation, please report\n",
435 SPY_GetMsgName(msg
, hwnd
), msg
);
439 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
446 /**********************************************************************
447 * WINPROC_CallProcWtoA
449 * Call a window procedure, translating args from Unicode to Ansi.
451 static LRESULT
WINPROC_CallProcWtoA( winproc_callback_t callback
, HWND hwnd
, UINT msg
, WPARAM wParam
,
452 LPARAM lParam
, LRESULT
*result
, void *arg
)
456 TRACE_(msg
)("(hwnd=%p,msg=%s,wp=%08Ix,lp=%08Ix)\n",
457 hwnd
, SPY_GetMsgName(msg
, hwnd
), wParam
, lParam
);
464 char buffer
[1024], *cls
;
465 CREATESTRUCTW
*csW
= (CREATESTRUCTW
*)lParam
;
466 CREATESTRUCTA csA
= *(CREATESTRUCTA
*)csW
;
467 MDICREATESTRUCTA mdi_cs
;
468 DWORD name_lenA
= 0, name_lenW
= 0, class_lenA
= 0, class_lenW
= 0;
469 char int_name_buf
[4];
471 if (!IS_INTRESOURCE(csW
->lpszClass
))
473 class_lenW
= (lstrlenW(csW
->lpszClass
) + 1) * sizeof(WCHAR
);
474 RtlUnicodeToMultiByteSize(&class_lenA
, csW
->lpszClass
, class_lenW
);
476 if (!IS_INTRESOURCE(csW
->lpszName
))
478 /* resource ID string is a special case */
479 if (csW
->lpszName
[0] == 0xffff)
481 int_name_buf
[0] = 0xff;
482 int_name_buf
[1] = csW
->lpszName
[1];
483 int_name_buf
[2] = csW
->lpszName
[1] >> 8;
485 csA
.lpszName
= int_name_buf
;
489 name_lenW
= (lstrlenW(csW
->lpszName
) + 1) * sizeof(WCHAR
);
490 RtlUnicodeToMultiByteSize(&name_lenA
, csW
->lpszName
, name_lenW
);
494 if (!(cls
= get_buffer( buffer
, sizeof(buffer
), class_lenA
+ name_lenA
))) break;
498 RtlUnicodeToMultiByteN(cls
, class_lenA
, NULL
, csW
->lpszClass
, class_lenW
);
503 char *name
= cls
+ class_lenA
;
504 RtlUnicodeToMultiByteN(name
, name_lenA
, NULL
, csW
->lpszName
, name_lenW
);
508 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
510 mdi_cs
= *(MDICREATESTRUCTA
*)csW
->lpCreateParams
;
511 mdi_cs
.szTitle
= csA
.lpszName
;
512 mdi_cs
.szClass
= csA
.lpszClass
;
513 csA
.lpCreateParams
= &mdi_cs
;
516 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&csA
, result
, arg
);
517 free_buffer( buffer
, cls
);
522 case WM_ASKCBFORMATNAME
:
524 char *ptr
, buffer
[512];
525 DWORD len
= wParam
* 2;
527 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
))) break;
528 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
533 RtlMultiByteToUnicodeN( (LPWSTR
)lParam
, wParam
*sizeof(WCHAR
), &len
, ptr
, ret
+ 1 );
534 *result
= len
/sizeof(WCHAR
) - 1; /* do not count terminating null */
536 ((LPWSTR
)lParam
)[*result
] = 0;
538 free_buffer( buffer
, ptr
);
543 case LB_INSERTSTRING
:
545 case LB_FINDSTRINGEXACT
:
546 case LB_SELECTSTRING
:
548 case CB_INSERTSTRING
:
550 case CB_FINDSTRINGEXACT
:
551 case CB_SELECTSTRING
:
552 if (!lParam
|| !WINPROC_TestLBForStr( hwnd
, msg
))
554 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
559 case WM_WININICHANGE
:
560 case WM_DEVMODECHANGE
:
565 if (!lParam
) ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
568 char *ptr
, buffer
[512];
569 LPCWSTR strW
= (LPCWSTR
)lParam
;
570 DWORD lenA
, lenW
= (lstrlenW(strW
) + 1) * sizeof(WCHAR
);
572 RtlUnicodeToMultiByteSize( &lenA
, strW
, lenW
);
573 if ((ptr
= get_buffer( buffer
, sizeof(buffer
), lenA
)))
575 RtlUnicodeToMultiByteN( ptr
, lenA
, NULL
, strW
, lenW
);
576 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
577 free_buffer( buffer
, ptr
);
584 char *ptr
, buffer
[1024];
585 DWORD title_lenA
= 0, title_lenW
= 0, class_lenA
= 0, class_lenW
= 0;
586 MDICREATESTRUCTW
*csW
= (MDICREATESTRUCTW
*)lParam
;
587 MDICREATESTRUCTA csA
;
589 memcpy( &csA
, csW
, sizeof(csA
) );
591 if (!IS_INTRESOURCE(csW
->szTitle
))
593 title_lenW
= (lstrlenW(csW
->szTitle
) + 1) * sizeof(WCHAR
);
594 RtlUnicodeToMultiByteSize( &title_lenA
, csW
->szTitle
, title_lenW
);
596 if (!IS_INTRESOURCE(csW
->szClass
))
598 class_lenW
= (lstrlenW(csW
->szClass
) + 1) * sizeof(WCHAR
);
599 RtlUnicodeToMultiByteSize( &class_lenA
, csW
->szClass
, class_lenW
);
602 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), title_lenA
+ class_lenA
))) break;
606 RtlUnicodeToMultiByteN( ptr
, title_lenA
, NULL
, csW
->szTitle
, title_lenW
);
611 RtlUnicodeToMultiByteN( ptr
+ title_lenA
, class_lenA
, NULL
, csW
->szClass
, class_lenW
);
612 csA
.szClass
= ptr
+ title_lenA
;
614 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&csA
, result
, arg
);
615 free_buffer( buffer
, ptr
);
621 if (lParam
&& WINPROC_TestLBForStr( hwnd
, msg
))
623 char buffer
[512]; /* FIXME: fixed sized buffer */
625 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)buffer
, result
, arg
);
629 RtlMultiByteToUnicodeN( (LPWSTR
)lParam
, 512 * 3, &len
, buffer
, strlen(buffer
) + 1 );
630 *result
= len
/ sizeof(WCHAR
) - 1;
633 else ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
638 char *ptr
, buffer
[512];
639 WORD len
= *(WORD
*)lParam
;
641 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
* 2 ))) break;
642 *((WORD
*)ptr
) = len
* 2; /* store the length */
643 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
647 RtlMultiByteToUnicodeN( (LPWSTR
)lParam
, len
*sizeof(WCHAR
), &reslen
, ptr
, *result
);
648 *result
= reslen
/ sizeof(WCHAR
);
649 if (*result
< len
) ((LPWSTR
)lParam
)[*result
] = 0;
651 free_buffer( buffer
, ptr
);
658 MSG newmsg
= *(MSG
*)lParam
;
659 switch(newmsg
.message
)
665 newmsg
.wParam
= map_wparam_char_WtoA( newmsg
.wParam
, 1 );
668 newmsg
.wParam
= map_wparam_char_WtoA( newmsg
.wParam
, 2 );
671 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&newmsg
, result
, arg
);
673 else ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
680 DWORD cp
= get_input_codepage();
681 DWORD len
= WideCharToMultiByte( cp
, 0, &wch
, 1, ch
, 2, NULL
, NULL
);
682 ret
= callback( hwnd
, msg
, (BYTE
)ch
[0], lParam
, result
, arg
);
683 if (len
== 2) ret
= callback( hwnd
, msg
, (BYTE
)ch
[1], lParam
, result
, arg
);
692 case EM_SETPASSWORDCHAR
:
693 ret
= callback( hwnd
, msg
, map_wparam_char_WtoA(wParam
,1), lParam
, result
, arg
);
697 ret
= callback( hwnd
, msg
, map_wparam_char_WtoA(wParam
,2), lParam
, result
, arg
);
700 case WM_PAINTCLIPBOARD
:
701 case WM_SIZECLIPBOARD
:
702 FIXME_(msg
)( "message %s (%04x) needs translation, please report\n",
703 SPY_GetMsgName(msg
, hwnd
), msg
);
707 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
715 void dispatch_win_proc_params( struct win_proc_params
*params
)
717 DPI_AWARENESS_CONTEXT context
= SetThreadDpiAwarenessContext( params
->dpi_awareness
);
721 if (params
->procW
== WINPROC_PROC16
)
722 WINPROC_CallProcWtoA( wow_handlers
.call_window_proc
, params
->hwnd
, params
->msg
, params
->wparam
,
723 params
->lparam
, params
->result
, params
->func
);
724 else if (!params
->ansi_dst
)
725 call_window_proc( params
->hwnd
, params
->msg
, params
->wparam
, params
->lparam
,
726 params
->result
, params
->procW
);
728 WINPROC_CallProcWtoA( call_window_proc
, params
->hwnd
, params
->msg
, params
->wparam
,
729 params
->lparam
, params
->result
, params
->procA
);
733 if (params
->procA
== WINPROC_PROC16
)
734 wow_handlers
.call_window_proc( params
->hwnd
, params
->msg
, params
->wparam
, params
->lparam
,
735 params
->result
, params
->func
);
736 else if (!params
->ansi_dst
)
737 WINPROC_CallProcAtoW( call_window_proc
, params
->hwnd
, params
->msg
, params
->wparam
,
738 params
->lparam
, params
->result
, params
->procW
, params
->mapping
);
740 call_window_proc( params
->hwnd
, params
->msg
, params
->wparam
, params
->lparam
,
741 params
->result
, params
->procA
);
744 SetThreadDpiAwarenessContext( context
);
747 /* make sure that there is space for 'size' bytes in buffer, growing it if needed */
748 static inline void *get_buffer_space( void **buffer
, size_t size
, size_t prev_size
)
750 if (prev_size
< size
)
751 *buffer
= HeapAlloc( GetProcessHeap(), 0, size
);
755 /* check whether a combobox expects strings or ids in CB_ADDSTRING/CB_INSERTSTRING */
756 static inline BOOL
combobox_has_strings( HWND hwnd
)
758 DWORD style
= GetWindowLongA( hwnd
, GWL_STYLE
);
759 return (!(style
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) || (style
& CBS_HASSTRINGS
));
762 /* check whether a listbox expects strings or ids in LB_ADDSTRING/LB_INSERTSTRING */
763 static inline BOOL
listbox_has_strings( HWND hwnd
)
765 DWORD style
= GetWindowLongA( hwnd
, GWL_STYLE
);
766 return (!(style
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) || (style
& LBS_HASSTRINGS
));
769 /* unpack a potentially 64-bit pointer, returning 0 when truncated */
770 static inline void *unpack_ptr( ULONGLONG ptr64
)
772 if ((ULONG_PTR
)ptr64
!= ptr64
) return 0;
773 return (void *)(ULONG_PTR
)ptr64
;
776 /* convert a server handle to a generic handle */
777 static inline HANDLE
unpack_handle( UINT handle
)
779 return (HANDLE
)(INT_PTR
)(int)handle
;
782 /* make sure that the buffer contains a valid null-terminated Unicode string */
783 static inline BOOL
check_string( LPCWSTR str
, size_t size
)
785 for (size
/= sizeof(WCHAR
); size
; size
--, str
++)
786 if (!*str
) return TRUE
;
790 /***********************************************************************
793 * Unpack a message received from another process.
795 static BOOL
unpack_message( HWND hwnd
, UINT message
, WPARAM
*wparam
, LPARAM
*lparam
,
796 void **buffer
, size_t size
)
798 size_t minsize
= 0, prev_size
= size
;
799 union packed_structs
*ps
= *buffer
;
807 WCHAR
*str
= (WCHAR
*)(&ps
->cs
+ 1);
808 if (size
< sizeof(ps
->cs
)) return FALSE
;
809 size
-= sizeof(ps
->cs
);
810 cs
.lpCreateParams
= unpack_ptr( ps
->cs
.lpCreateParams
);
811 cs
.hInstance
= unpack_ptr( ps
->cs
.hInstance
);
812 cs
.hMenu
= unpack_handle( ps
->cs
.hMenu
);
813 cs
.hwndParent
= unpack_handle( ps
->cs
.hwndParent
);
818 cs
.style
= ps
->cs
.style
;
819 cs
.dwExStyle
= ps
->cs
.dwExStyle
;
820 cs
.lpszName
= unpack_ptr( ps
->cs
.lpszName
);
821 cs
.lpszClass
= unpack_ptr( ps
->cs
.lpszClass
);
822 if (ps
->cs
.lpszName
>> 16)
824 if (!check_string( str
, size
)) return FALSE
;
826 size
-= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
827 str
+= lstrlenW(str
) + 1;
829 if (ps
->cs
.lpszClass
>> 16)
831 if (!check_string( str
, size
)) return FALSE
;
834 memcpy( &ps
->cs
, &cs
, sizeof(cs
) );
838 case WM_ASKCBFORMATNAME
:
839 if (!get_buffer_space( buffer
, (*wparam
* sizeof(WCHAR
)), size
)) return FALSE
;
841 case WM_WININICHANGE
:
842 if (!*lparam
) return TRUE
;
845 case WM_DEVMODECHANGE
:
850 if (!check_string( *buffer
, size
)) return FALSE
;
852 case WM_GETMINMAXINFO
:
853 minsize
= sizeof(MINMAXINFO
);
858 if (size
< sizeof(ps
->dis
)) return FALSE
;
859 dis
.CtlType
= ps
->dis
.CtlType
;
860 dis
.CtlID
= ps
->dis
.CtlID
;
861 dis
.itemID
= ps
->dis
.itemID
;
862 dis
.itemAction
= ps
->dis
.itemAction
;
863 dis
.itemState
= ps
->dis
.itemState
;
864 dis
.hwndItem
= unpack_handle( ps
->dis
.hwndItem
);
865 dis
.hDC
= unpack_handle( ps
->dis
.hDC
);
866 dis
.rcItem
= ps
->dis
.rcItem
;
867 dis
.itemData
= (ULONG_PTR
)unpack_ptr( ps
->dis
.itemData
);
868 memcpy( &ps
->dis
, &dis
, sizeof(dis
) );
873 MEASUREITEMSTRUCT mis
;
874 if (size
< sizeof(ps
->mis
)) return FALSE
;
875 mis
.CtlType
= ps
->mis
.CtlType
;
876 mis
.CtlID
= ps
->mis
.CtlID
;
877 mis
.itemID
= ps
->mis
.itemID
;
878 mis
.itemWidth
= ps
->mis
.itemWidth
;
879 mis
.itemHeight
= ps
->mis
.itemHeight
;
880 mis
.itemData
= (ULONG_PTR
)unpack_ptr( ps
->mis
.itemData
);
881 memcpy( &ps
->mis
, &mis
, sizeof(mis
) );
886 DELETEITEMSTRUCT dls
;
887 if (size
< sizeof(ps
->dls
)) return FALSE
;
888 dls
.CtlType
= ps
->dls
.CtlType
;
889 dls
.CtlID
= ps
->dls
.CtlID
;
890 dls
.itemID
= ps
->dls
.itemID
;
891 dls
.hwndItem
= unpack_handle( ps
->dls
.hwndItem
);
892 dls
.itemData
= (ULONG_PTR
)unpack_ptr( ps
->dls
.itemData
);
893 memcpy( &ps
->dls
, &dls
, sizeof(dls
) );
898 COMPAREITEMSTRUCT cis
;
899 if (size
< sizeof(ps
->cis
)) return FALSE
;
900 cis
.CtlType
= ps
->cis
.CtlType
;
901 cis
.CtlID
= ps
->cis
.CtlID
;
902 cis
.hwndItem
= unpack_handle( ps
->cis
.hwndItem
);
903 cis
.itemID1
= ps
->cis
.itemID1
;
904 cis
.itemData1
= (ULONG_PTR
)unpack_ptr( ps
->cis
.itemData1
);
905 cis
.itemID2
= ps
->cis
.itemID2
;
906 cis
.itemData2
= (ULONG_PTR
)unpack_ptr( ps
->cis
.itemData2
);
907 cis
.dwLocaleId
= ps
->cis
.dwLocaleId
;
908 memcpy( &ps
->cis
, &cis
, sizeof(cis
) );
911 case WM_WINDOWPOSCHANGING
:
912 case WM_WINDOWPOSCHANGED
:
915 if (size
< sizeof(ps
->wp
)) return FALSE
;
916 wp
.hwnd
= unpack_handle( ps
->wp
.hwnd
);
917 wp
.hwndInsertAfter
= unpack_handle( ps
->wp
.hwndInsertAfter
);
922 wp
.flags
= ps
->wp
.flags
;
923 memcpy( &ps
->wp
, &wp
, sizeof(wp
) );
929 if (size
< sizeof(ps
->cds
)) return FALSE
;
930 cds
.dwData
= (ULONG_PTR
)unpack_ptr( ps
->cds
.dwData
);
933 cds
.cbData
= ps
->cds
.cbData
;
934 cds
.lpData
= &ps
->cds
+ 1;
935 minsize
= sizeof(ps
->cds
) + cds
.cbData
;
942 memcpy( &ps
->cds
, &cds
, sizeof(cds
) );
946 /* WM_NOTIFY cannot be sent across processes (MSDN) */
951 if (size
< sizeof(ps
->hi
)) return FALSE
;
952 hi
.cbSize
= sizeof(hi
);
953 hi
.iContextType
= ps
->hi
.iContextType
;
954 hi
.iCtrlId
= ps
->hi
.iCtrlId
;
955 hi
.hItemHandle
= unpack_handle( ps
->hi
.hItemHandle
);
956 hi
.dwContextId
= (ULONG_PTR
)unpack_ptr( ps
->hi
.dwContextId
);
957 hi
.MousePos
= ps
->hi
.MousePos
;
958 memcpy( &ps
->hi
, &hi
, sizeof(hi
) );
961 case WM_STYLECHANGING
:
962 case WM_STYLECHANGED
:
963 minsize
= sizeof(STYLESTRUCT
);
966 if (!*wparam
) minsize
= sizeof(RECT
);
969 NCCALCSIZE_PARAMS ncp
;
971 if (size
< sizeof(ps
->ncp
)) return FALSE
;
972 ncp
.rgrc
[0] = ps
->ncp
.rgrc
[0];
973 ncp
.rgrc
[1] = ps
->ncp
.rgrc
[1];
974 ncp
.rgrc
[2] = ps
->ncp
.rgrc
[2];
975 wp
.hwnd
= unpack_handle( ps
->ncp
.hwnd
);
976 wp
.hwndInsertAfter
= unpack_handle( ps
->ncp
.hwndInsertAfter
);
981 wp
.flags
= ps
->ncp
.flags
;
982 ncp
.lppos
= (WINDOWPOS
*)((NCCALCSIZE_PARAMS
*)&ps
->ncp
+ 1);
983 memcpy( &ps
->ncp
, &ncp
, sizeof(ncp
) );
991 if (size
< sizeof(ps
->msg
)) return FALSE
;
992 msg
.hwnd
= unpack_handle( ps
->msg
.hwnd
);
993 msg
.message
= ps
->msg
.message
;
994 msg
.wParam
= (ULONG_PTR
)unpack_ptr( ps
->msg
.wParam
);
995 msg
.lParam
= (ULONG_PTR
)unpack_ptr( ps
->msg
.lParam
);
996 msg
.time
= ps
->msg
.time
;
998 memcpy( &ps
->msg
, &msg
, sizeof(msg
) );
1002 case SBM_SETSCROLLINFO
:
1003 minsize
= sizeof(SCROLLINFO
);
1005 case SBM_GETSCROLLINFO
:
1006 if (!get_buffer_space( buffer
, sizeof(SCROLLINFO
), size
)) return FALSE
;
1008 case SBM_GETSCROLLBARINFO
:
1009 if (!get_buffer_space( buffer
, sizeof(SCROLLBARINFO
), size
)) return FALSE
;
1014 if (*wparam
|| *lparam
)
1016 if (!get_buffer_space( buffer
, 2*sizeof(DWORD
), size
)) return FALSE
;
1017 if (*wparam
) *wparam
= (WPARAM
)*buffer
;
1018 if (*lparam
) *lparam
= (LPARAM
)((DWORD
*)*buffer
+ 1);
1022 case LB_GETITEMRECT
:
1023 case CB_GETDROPPEDCONTROLRECT
:
1024 if (!get_buffer_space( buffer
, sizeof(RECT
), size
)) return FALSE
;
1028 minsize
= sizeof(RECT
);
1033 if (size
< sizeof(WORD
)) return FALSE
;
1034 len
= *(WORD
*)*buffer
;
1035 if (!get_buffer_space( buffer
, (len
+ 1) * sizeof(WCHAR
), size
)) return FALSE
;
1036 *lparam
= (LPARAM
)*buffer
+ sizeof(WORD
); /* don't erase WORD at start of buffer */
1039 case EM_SETTABSTOPS
:
1040 case LB_SETTABSTOPS
:
1041 if (!*wparam
) return TRUE
;
1042 minsize
= *wparam
* sizeof(UINT
);
1045 case CB_INSERTSTRING
:
1047 case CB_FINDSTRINGEXACT
:
1048 case CB_SELECTSTRING
:
1050 case LB_INSERTSTRING
:
1052 case LB_FINDSTRINGEXACT
:
1053 case LB_SELECTSTRING
:
1054 if (!*buffer
) return TRUE
;
1055 if (!check_string( *buffer
, size
)) return FALSE
;
1059 size
= sizeof(ULONG_PTR
);
1060 if (combobox_has_strings( hwnd
))
1061 size
= (SendMessageW( hwnd
, CB_GETLBTEXTLEN
, *wparam
, 0 ) + 1) * sizeof(WCHAR
);
1062 if (!get_buffer_space( buffer
, size
, prev_size
)) return FALSE
;
1067 size
= sizeof(ULONG_PTR
);
1068 if (listbox_has_strings( hwnd
))
1069 size
= (SendMessageW( hwnd
, LB_GETTEXTLEN
, *wparam
, 0 ) + 1) * sizeof(WCHAR
);
1070 if (!get_buffer_space( buffer
, size
, prev_size
)) return FALSE
;
1073 case LB_GETSELITEMS
:
1074 if (!get_buffer_space( buffer
, *wparam
* sizeof(UINT
), size
)) return FALSE
;
1079 if (size
< sizeof(ps
->mnm
)) return FALSE
;
1080 mnm
.hmenuIn
= unpack_handle( ps
->mnm
.hmenuIn
);
1081 mnm
.hmenuNext
= unpack_handle( ps
->mnm
.hmenuNext
);
1082 mnm
.hwndNext
= unpack_handle( ps
->mnm
.hwndNext
);
1083 memcpy( &ps
->mnm
, &mnm
, sizeof(mnm
) );
1088 minsize
= sizeof(RECT
);
1089 if (!get_buffer_space( buffer
, sizeof(RECT
), size
)) return FALSE
;
1093 MDICREATESTRUCTW mcs
;
1094 WCHAR
*str
= (WCHAR
*)(&ps
->mcs
+ 1);
1095 if (size
< sizeof(ps
->mcs
)) return FALSE
;
1096 size
-= sizeof(ps
->mcs
);
1098 mcs
.szClass
= unpack_ptr( ps
->mcs
.szClass
);
1099 mcs
.szTitle
= unpack_ptr( ps
->mcs
.szTitle
);
1100 mcs
.hOwner
= unpack_ptr( ps
->mcs
.hOwner
);
1103 mcs
.cx
= ps
->mcs
.cx
;
1104 mcs
.cy
= ps
->mcs
.cy
;
1105 mcs
.style
= ps
->mcs
.style
;
1106 mcs
.lParam
= (LPARAM
)unpack_ptr( ps
->mcs
.lParam
);
1107 if (ps
->mcs
.szClass
>> 16)
1109 if (!check_string( str
, size
)) return FALSE
;
1111 size
-= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
1112 str
+= lstrlenW(str
) + 1;
1114 if (ps
->mcs
.szTitle
>> 16)
1116 if (!check_string( str
, size
)) return FALSE
;
1119 memcpy( &ps
->mcs
, &mcs
, sizeof(mcs
) );
1122 case WM_MDIGETACTIVE
:
1123 if (!*lparam
) return TRUE
;
1124 if (!get_buffer_space( buffer
, sizeof(BOOL
), size
)) return FALSE
;
1126 case WM_DEVICECHANGE
:
1127 if (!(*wparam
& 0x8000)) return TRUE
;
1128 minsize
= sizeof(DEV_BROADCAST_HDR
);
1131 if (*wparam
<= 1) return TRUE
;
1132 FIXME( "WM_NCPAINT hdc unpacking not supported\n" );
1135 if (!*wparam
) return TRUE
;
1138 /* these contain an HFONT */
1141 /* these contain an HDC */
1143 case WM_ICONERASEBKGND
:
1144 case WM_CTLCOLORMSGBOX
:
1145 case WM_CTLCOLOREDIT
:
1146 case WM_CTLCOLORLISTBOX
:
1147 case WM_CTLCOLORBTN
:
1148 case WM_CTLCOLORDLG
:
1149 case WM_CTLCOLORSCROLLBAR
:
1150 case WM_CTLCOLORSTATIC
:
1152 case WM_PRINTCLIENT
:
1153 /* these contain an HGLOBAL */
1154 case WM_PAINTCLIPBOARD
:
1155 case WM_SIZECLIPBOARD
:
1156 /* these contain HICON */
1159 case WM_QUERYDRAGICON
:
1160 case WM_QUERYPARKICON
:
1161 /* these contain pointers */
1163 case WM_QUERYDROPOBJECT
:
1167 FIXME( "msg %x (%s) not supported yet\n", message
, SPY_GetMsgName(message
, hwnd
) );
1171 return TRUE
; /* message doesn't need any unpacking */
1174 /* default exit for most messages: check minsize and store buffer in lparam */
1175 if (size
< minsize
) return FALSE
;
1176 *lparam
= (LPARAM
)*buffer
;
1180 BOOL WINAPI
User32CallWindowProc( struct win_proc_params
*params
, ULONG size
)
1182 LRESULT result
, *result_ptr
= params
->result
;
1183 params
->result
= &result
;
1185 if (params
->needs_unpack
)
1187 char stack_buffer
[128];
1190 if (size
> sizeof(*params
))
1192 size
-= sizeof(*params
);
1193 buffer
= params
+ 1;
1197 size
= sizeof(stack_buffer
);
1198 buffer
= stack_buffer
;
1200 if (!unpack_message( params
->hwnd
, params
->msg
, ¶ms
->wparam
,
1201 ¶ms
->lparam
, &buffer
, size
))
1204 dispatch_win_proc_params( params
);
1206 NtUserMessageCall( params
->hwnd
, params
->msg
, params
->wparam
, params
->lparam
,
1207 (void *)result
, NtUserWinProcResult
, FALSE
);
1208 if (buffer
!= stack_buffer
&& buffer
!= params
+ 1)
1209 HeapFree( GetProcessHeap(), 0, buffer
);
1213 dispatch_win_proc_params( params
);
1216 *result_ptr
= result
;
1219 NtCallbackReturn( &result
, sizeof(result
), TRUE
);
1224 BOOL WINAPI
User32CallSendAsyncCallback( const struct send_async_params
*params
, ULONG size
)
1226 params
->callback( params
->hwnd
, params
->msg
, params
->data
, params
->result
);
1230 /**********************************************************************
1231 * CallWindowProcA (USER32.@)
1233 * The CallWindowProc() function invokes the windows procedure _func_,
1234 * with _hwnd_ as the target window, the message specified by _msg_, and
1235 * the message parameters _wParam_ and _lParam_.
1237 * Some kinds of argument conversion may be done, I'm not sure what.
1239 * CallWindowProc() may be used for windows subclassing. Use
1240 * SetWindowLong() to set a new windows procedure for windows of the
1241 * subclass, and handle subclassed messages in the new windows
1242 * procedure. The new windows procedure may then use CallWindowProc()
1243 * with _func_ set to the parent class's windows procedure to dispatch
1244 * the message to the superclass.
1248 * The return value is message dependent.
1254 LRESULT WINAPI
CallWindowProcA( WNDPROC func
, HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1256 struct win_proc_params params
;
1260 params
.result
= &result
;
1261 if (!NtUserMessageCall( hwnd
, msg
, wParam
, lParam
, ¶ms
, NtUserCallWindowProc
, TRUE
))
1263 dispatch_win_proc_params( ¶ms
);
1268 /**********************************************************************
1269 * CallWindowProcW (USER32.@)
1271 * See CallWindowProcA.
1273 LRESULT WINAPI
CallWindowProcW( WNDPROC func
, HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1275 struct win_proc_params params
;
1279 params
.result
= &result
;
1280 if (!NtUserMessageCall( hwnd
, msg
, wParam
, lParam
, ¶ms
, NtUserCallWindowProc
, FALSE
))
1282 dispatch_win_proc_params( ¶ms
);
1287 /**********************************************************************
1288 * WINPROC_CallDlgProcA
1290 INT_PTR
WINPROC_CallDlgProcA( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1296 proc
= (DLGPROC
)NtUserGetWindowLongPtrA( hwnd
, DWLP_DLGPROC
);
1298 proc
= (DLGPROC
)NtUserGetWindowLongA( hwnd
, DWLP_DLGPROC
);
1300 if (!proc
) return 0;
1301 if (!(func
= NtUserGetDialogProc( proc
, TRUE
)) &&
1302 !(func
= NtUserGetDialogProc( proc
, FALSE
))) return 0;
1304 if (func
== WINPROC_PROC16
)
1307 ret
= wow_handlers
.call_dialog_proc( hwnd
, msg
, wParam
, lParam
, &result
, proc
);
1308 SetWindowLongPtrW( hwnd
, DWLP_MSGRESULT
, result
);
1312 return call_dialog_proc( hwnd
, msg
, wParam
, lParam
, &result
, func
);
1316 /**********************************************************************
1317 * WINPROC_CallDlgProcW
1319 INT_PTR
WINPROC_CallDlgProcW( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1325 proc
= (DLGPROC
)NtUserGetWindowLongPtrW( hwnd
, DWLP_DLGPROC
);
1327 proc
= (DLGPROC
)NtUserGetWindowLongW( hwnd
, DWLP_DLGPROC
);
1329 if (!proc
) return 0;
1330 if (!(func
= NtUserGetDialogProc( proc
, FALSE
)) &&
1331 !(func
= NtUserGetDialogProc( proc
, TRUE
))) return 0;
1333 if (func
== WINPROC_PROC16
)
1336 ret
= WINPROC_CallProcWtoA( wow_handlers
.call_dialog_proc
,
1337 hwnd
, msg
, wParam
, lParam
, &result
, proc
);
1338 SetWindowLongPtrW( hwnd
, DWLP_MSGRESULT
, result
);
1342 return call_dialog_proc( hwnd
, msg
, wParam
, lParam
, &result
, func
);
1346 /***********************************************************************
1347 * Window procedures for builtin classes
1350 static LRESULT WINAPI
ButtonWndProcA( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1352 return wow_handlers
.button_proc( hwnd
, msg
, wParam
, lParam
, FALSE
);
1355 static LRESULT WINAPI
ButtonWndProcW( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1357 return wow_handlers
.button_proc( hwnd
, msg
, wParam
, lParam
, TRUE
);
1360 static LRESULT WINAPI
ComboWndProcA( HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1362 return wow_handlers
.combo_proc( hwnd
, message
, wParam
, lParam
, FALSE
);
1365 static LRESULT WINAPI
ComboWndProcW( HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1367 return wow_handlers
.combo_proc( hwnd
, message
, wParam
, lParam
, TRUE
);
1370 LRESULT WINAPI
EditWndProcA( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1372 return wow_handlers
.edit_proc( hwnd
, msg
, wParam
, lParam
, FALSE
);
1375 static LRESULT WINAPI
EditWndProcW( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1377 return wow_handlers
.edit_proc( hwnd
, msg
, wParam
, lParam
, TRUE
);
1380 static LRESULT WINAPI
ListBoxWndProcA( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1382 return wow_handlers
.listbox_proc( hwnd
, msg
, wParam
, lParam
, FALSE
);
1385 static LRESULT WINAPI
ListBoxWndProcW( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1387 return wow_handlers
.listbox_proc( hwnd
, msg
, wParam
, lParam
, TRUE
);
1390 static LRESULT WINAPI
MDIClientWndProcA( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1392 return wow_handlers
.mdiclient_proc( hwnd
, msg
, wParam
, lParam
, FALSE
);
1395 static LRESULT WINAPI
MDIClientWndProcW( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1397 return wow_handlers
.mdiclient_proc( hwnd
, msg
, wParam
, lParam
, TRUE
);
1400 static LRESULT WINAPI
ScrollBarWndProcA( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1402 return wow_handlers
.scrollbar_proc( hwnd
, msg
, wParam
, lParam
, FALSE
);
1405 static LRESULT WINAPI
ScrollBarWndProcW( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1407 return wow_handlers
.scrollbar_proc( hwnd
, msg
, wParam
, lParam
, TRUE
);
1410 static LRESULT WINAPI
StaticWndProcA( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1412 return wow_handlers
.static_proc( hwnd
, msg
, wParam
, lParam
, FALSE
);
1415 static LRESULT WINAPI
StaticWndProcW( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1417 return wow_handlers
.static_proc( hwnd
, msg
, wParam
, lParam
, TRUE
);
1420 /**********************************************************************
1421 * UserRegisterWowHandlers (USER32.@)
1423 * NOTE: no attempt has been made to be compatible here,
1424 * the Windows function is most likely completely different.
1426 void WINAPI
UserRegisterWowHandlers( const struct wow_handlers16
*new, struct wow_handlers32
*orig
)
1428 orig
->button_proc
= ButtonWndProc_common
;
1429 orig
->combo_proc
= ComboWndProc_common
;
1430 orig
->edit_proc
= EditWndProc_common
;
1431 orig
->listbox_proc
= ListBoxWndProc_common
;
1432 orig
->mdiclient_proc
= MDIClientWndProc_common
;
1433 orig
->scrollbar_proc
= ScrollBarWndProc_common
;
1434 orig
->static_proc
= StaticWndProc_common
;
1435 orig
->create_window
= WIN_CreateWindowEx
;
1436 orig
->get_win_handle
= WIN_GetFullHandle
;
1437 orig
->alloc_winproc
= WINPROC_AllocProc
;
1438 orig
->get_dialog_info
= DIALOG_get_info
;
1439 orig
->dialog_box_loop
= DIALOG_DoDialogBox
;
1441 wow_handlers
= *new;
1444 struct wow_handlers16 wow_handlers
=
1446 ButtonWndProc_common
,
1447 ComboWndProc_common
,
1449 ListBoxWndProc_common
,
1450 MDIClientWndProc_common
,
1451 ScrollBarWndProc_common
,
1452 StaticWndProc_common
,
1454 NULL
, /* call_window_proc */
1455 NULL
, /* call_dialog_proc */
1458 static const struct user_client_procs client_procsA
=
1460 .pButtonWndProc
= ButtonWndProcA
,
1461 .pComboWndProc
= ComboWndProcA
,
1462 .pDefWindowProc
= DefWindowProcA
,
1463 .pDefDlgProc
= DefDlgProcA
,
1464 .pEditWndProc
= EditWndProcA
,
1465 .pListBoxWndProc
= ListBoxWndProcA
,
1466 .pMDIClientWndProc
= MDIClientWndProcA
,
1467 .pScrollBarWndProc
= ScrollBarWndProcA
,
1468 .pStaticWndProc
= StaticWndProcA
,
1469 .pImeWndProc
= ImeWndProcA
,
1472 static const struct user_client_procs client_procsW
=
1474 .pButtonWndProc
= ButtonWndProcW
,
1475 .pComboWndProc
= ComboWndProcW
,
1476 .pDefWindowProc
= DefWindowProcW
,
1477 .pDefDlgProc
= DefDlgProcW
,
1478 .pEditWndProc
= EditWndProcW
,
1479 .pListBoxWndProc
= ListBoxWndProcW
,
1480 .pMDIClientWndProc
= MDIClientWndProcW
,
1481 .pScrollBarWndProc
= ScrollBarWndProcW
,
1482 .pStaticWndProc
= StaticWndProcW
,
1483 .pImeWndProc
= ImeWndProcW
,
1484 .pDesktopWndProc
= DesktopWndProc
,
1485 .pIconTitleWndProc
= IconTitleWndProc
,
1486 .pPopupMenuWndProc
= PopupMenuWndProc
,
1487 .pMessageWndProc
= MessageWndProc
,
1490 void winproc_init(void)
1492 NtUserInitializeClientPfnArrays( &client_procsA
, &client_procsW
, NULL
, user32_module
);