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
23 #include "wine/port.h"
33 #include "wine/winbase16.h"
34 #include "wine/winuser16.h"
38 #include "user_private.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
44 WINE_DECLARE_DEBUG_CHANNEL(msg
);
45 WINE_DECLARE_DEBUG_CHANNEL(relay
);
46 WINE_DEFAULT_DEBUG_CHANNEL(win
);
48 typedef struct tagWINDOWPROC
50 WNDPROC16 proc16
; /* 16-bit window proc */
51 WNDPROC procA
; /* ASCII window proc */
52 WNDPROC procW
; /* Unicode window proc */
55 #define WINPROC_HANDLE (~0UL >> 16)
56 #define MAX_WINPROCS 8192
58 static WINDOWPROC winproc_array
[MAX_WINPROCS
];
59 static UINT winproc_used
;
61 static CRITICAL_SECTION winproc_cs
;
62 static CRITICAL_SECTION_DEBUG critsect_debug
=
65 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
66 0, 0, { (DWORD_PTR
)(__FILE__
": winproc_cs") }
68 static CRITICAL_SECTION winproc_cs
= { &critsect_debug
, -1, 0, 0, 0, 0 };
70 static inline void *get_buffer( void *static_buffer
, size_t size
, size_t need
)
72 if (size
>= need
) return static_buffer
;
73 return HeapAlloc( GetProcessHeap(), 0, need
);
76 static inline void free_buffer( void *static_buffer
, void *buffer
)
78 if (buffer
!= static_buffer
) HeapFree( GetProcessHeap(), 0, buffer
);
81 /* find an existing winproc for a given 16-bit function and type */
82 /* FIXME: probably should do something more clever than a linear search */
83 static inline WINDOWPROC
*find_winproc16( WNDPROC16 func
)
87 for (i
= 0; i
< winproc_used
; i
++)
89 if (winproc_array
[i
].proc16
== func
) return &winproc_array
[i
];
94 /* find an existing winproc for a given function and type */
95 /* FIXME: probably should do something more clever than a linear search */
96 static inline WINDOWPROC
*find_winproc( WNDPROC funcA
, WNDPROC funcW
)
100 for (i
= 0; i
< winproc_used
; i
++)
102 if (funcA
&& winproc_array
[i
].procA
!= funcA
) continue;
103 if (funcW
&& winproc_array
[i
].procW
!= funcW
) continue;
104 return &winproc_array
[i
];
109 /* return the window proc for a given handle, or NULL for an invalid handle */
110 static inline WINDOWPROC
*handle_to_proc( WNDPROC handle
)
112 UINT index
= LOWORD(handle
);
113 if ((ULONG_PTR
)handle
>> 16 != WINPROC_HANDLE
) return NULL
;
114 if (index
>= winproc_used
) return NULL
;
115 return &winproc_array
[index
];
118 /* create a handle for a given window proc */
119 static inline WNDPROC
proc_to_handle( WINDOWPROC
*proc
)
121 return (WNDPROC
)(ULONG_PTR
)((proc
- winproc_array
) | (WINPROC_HANDLE
<< 16));
124 /* allocate and initialize a new winproc */
125 static inline WINDOWPROC
*alloc_winproc( WNDPROC funcA
, WNDPROC funcW
)
129 /* check if the function is already a win proc */
130 if (funcA
&& (proc
= handle_to_proc( funcA
))) return proc
;
131 if (funcW
&& (proc
= handle_to_proc( funcW
))) return proc
;
132 if (!funcA
&& !funcW
) return NULL
;
134 EnterCriticalSection( &winproc_cs
);
136 /* check if we already have a winproc for that function */
137 if (!(proc
= find_winproc( funcA
, funcW
)))
139 if (winproc_used
< MAX_WINPROCS
)
141 proc
= &winproc_array
[winproc_used
++];
144 TRACE( "allocated %p for %p/%p (%d/%d used)\n",
145 proc_to_handle(proc
), funcA
, funcW
, winproc_used
, MAX_WINPROCS
);
147 else FIXME( "too many winprocs, cannot allocate one for %p/%p\n", funcA
, funcW
);
149 else TRACE( "reusing %p for %p/%p\n", proc_to_handle(proc
), funcA
, funcW
);
151 LeaveCriticalSection( &winproc_cs
);
158 #include "pshpack1.h"
160 /* Window procedure 16-to-32-bit thunk */
163 BYTE popl_eax
; /* popl %eax (return address) */
164 BYTE pushl_func
; /* pushl $proc */
166 BYTE pushl_eax
; /* pushl %eax */
167 BYTE ljmp
; /* ljmp relay*/
168 DWORD relay_offset
; /* __wine_call_wndproc */
174 #define MAX_THUNKS (0x10000 / sizeof(WINPROC_THUNK))
176 static WINPROC_THUNK
*thunk_array
;
177 static UINT thunk_selector
;
178 static UINT thunk_used
;
180 /* return the window proc for a given handle, or NULL for an invalid handle */
181 static inline WINDOWPROC
*handle16_to_proc( WNDPROC16 handle
)
183 if (HIWORD(handle
) == thunk_selector
)
185 UINT index
= LOWORD(handle
) / sizeof(WINPROC_THUNK
);
186 /* check alignment */
187 if (index
* sizeof(WINPROC_THUNK
) != LOWORD(handle
)) return NULL
;
188 /* check array limits */
189 if (index
>= thunk_used
) return NULL
;
190 return thunk_array
[index
].proc
;
192 return handle_to_proc( (WNDPROC
)handle
);
195 /* allocate a 16-bit thunk for an existing window proc */
196 static WNDPROC16
alloc_win16_thunk( WINDOWPROC
*proc
)
198 static FARPROC16 relay
;
201 if (proc
->proc16
) return proc
->proc16
;
203 EnterCriticalSection( &winproc_cs
);
205 if (!thunk_array
) /* allocate the array and its selector */
209 if (!(thunk_selector
= wine_ldt_alloc_entries(1))) goto done
;
210 if (!(thunk_array
= VirtualAlloc( NULL
, MAX_THUNKS
* sizeof(WINPROC_THUNK
), MEM_COMMIT
,
211 PAGE_EXECUTE_READWRITE
))) goto done
;
212 wine_ldt_set_base( &entry
, thunk_array
);
213 wine_ldt_set_limit( &entry
, MAX_THUNKS
* sizeof(WINPROC_THUNK
) - 1 );
214 wine_ldt_set_flags( &entry
, WINE_LDT_FLAGS_CODE
| WINE_LDT_FLAGS_32BIT
);
215 wine_ldt_set_entry( thunk_selector
, &entry
);
216 relay
= GetProcAddress16( GetModuleHandle16("user"), "__wine_call_wndproc" );
219 /* check if it already exists */
220 for (i
= 0; i
< thunk_used
; i
++) if (thunk_array
[i
].proc
== proc
) break;
222 if (i
== thunk_used
) /* create a new one */
224 WINPROC_THUNK
*thunk
;
226 if (thunk_used
>= MAX_THUNKS
) goto done
;
227 thunk
= &thunk_array
[thunk_used
++];
228 thunk
->popl_eax
= 0x58; /* popl %eax */
229 thunk
->pushl_func
= 0x68; /* pushl $proc */
231 thunk
->pushl_eax
= 0x50; /* pushl %eax */
232 thunk
->ljmp
= 0xea; /* ljmp relay*/
233 thunk
->relay_offset
= OFFSETOF(relay
);
234 thunk
->relay_sel
= SELECTOROF(relay
);
236 proc
->proc16
= (WNDPROC16
)MAKESEGPTR( thunk_selector
, i
* sizeof(WINPROC_THUNK
) );
238 LeaveCriticalSection( &winproc_cs
);
244 static inline WINDOWPROC
*handle16_to_proc( WNDPROC16 handle
)
246 return handle_to_proc( (WNDPROC
)handle
);
249 static inline WNDPROC16
alloc_win16_thunk( WINDOWPROC
*proc
)
254 #endif /* __i386__ */
258 /* Some window procedures modify register they shouldn't, or are not
259 * properly declared stdcall; so we need a small assembly wrapper to
261 extern LRESULT
WINPROC_wrapper( WNDPROC proc
, HWND hwnd
, UINT msg
,
262 WPARAM wParam
, LPARAM lParam
);
263 __ASM_GLOBAL_FUNC( WINPROC_wrapper
,
274 "movl 8(%ebp),%eax\n\t"
276 "leal -12(%ebp),%esp\n\t"
283 static inline LRESULT
WINPROC_wrapper( WNDPROC proc
, HWND hwnd
, UINT msg
,
284 WPARAM wParam
, LPARAM lParam
)
286 return proc( hwnd
, msg
, wParam
, lParam
);
288 #endif /* __i386__ */
290 static void RECT16to32( const RECT16
*from
, RECT
*to
)
292 to
->left
= from
->left
;
294 to
->right
= from
->right
;
295 to
->bottom
= from
->bottom
;
298 static void RECT32to16( const RECT
*from
, RECT16
*to
)
300 to
->left
= from
->left
;
302 to
->right
= from
->right
;
303 to
->bottom
= from
->bottom
;
306 static void MINMAXINFO32to16( const MINMAXINFO
*from
, MINMAXINFO16
*to
)
308 to
->ptReserved
.x
= from
->ptReserved
.x
;
309 to
->ptReserved
.y
= from
->ptReserved
.y
;
310 to
->ptMaxSize
.x
= from
->ptMaxSize
.x
;
311 to
->ptMaxSize
.y
= from
->ptMaxSize
.y
;
312 to
->ptMaxPosition
.x
= from
->ptMaxPosition
.x
;
313 to
->ptMaxPosition
.y
= from
->ptMaxPosition
.y
;
314 to
->ptMinTrackSize
.x
= from
->ptMinTrackSize
.x
;
315 to
->ptMinTrackSize
.y
= from
->ptMinTrackSize
.y
;
316 to
->ptMaxTrackSize
.x
= from
->ptMaxTrackSize
.x
;
317 to
->ptMaxTrackSize
.y
= from
->ptMaxTrackSize
.y
;
320 static void MINMAXINFO16to32( const MINMAXINFO16
*from
, MINMAXINFO
*to
)
322 to
->ptReserved
.x
= from
->ptReserved
.x
;
323 to
->ptReserved
.y
= from
->ptReserved
.y
;
324 to
->ptMaxSize
.x
= from
->ptMaxSize
.x
;
325 to
->ptMaxSize
.y
= from
->ptMaxSize
.y
;
326 to
->ptMaxPosition
.x
= from
->ptMaxPosition
.x
;
327 to
->ptMaxPosition
.y
= from
->ptMaxPosition
.y
;
328 to
->ptMinTrackSize
.x
= from
->ptMinTrackSize
.x
;
329 to
->ptMinTrackSize
.y
= from
->ptMinTrackSize
.y
;
330 to
->ptMaxTrackSize
.x
= from
->ptMaxTrackSize
.x
;
331 to
->ptMaxTrackSize
.y
= from
->ptMaxTrackSize
.y
;
334 static void WINDOWPOS32to16( const WINDOWPOS
* from
, WINDOWPOS16
* to
)
336 to
->hwnd
= HWND_16(from
->hwnd
);
337 to
->hwndInsertAfter
= HWND_16(from
->hwndInsertAfter
);
342 to
->flags
= from
->flags
;
345 static void WINDOWPOS16to32( const WINDOWPOS16
* from
, WINDOWPOS
* to
)
347 to
->hwnd
= WIN_Handle32(from
->hwnd
);
348 to
->hwndInsertAfter
= (from
->hwndInsertAfter
== (HWND16
)-1) ?
349 HWND_TOPMOST
: WIN_Handle32(from
->hwndInsertAfter
);
354 to
->flags
= from
->flags
;
357 /* The strings are not copied */
358 static void CREATESTRUCT32Ato16( const CREATESTRUCTA
* from
, CREATESTRUCT16
* to
)
360 to
->lpCreateParams
= (SEGPTR
)from
->lpCreateParams
;
361 to
->hInstance
= HINSTANCE_16(from
->hInstance
);
362 to
->hMenu
= HMENU_16(from
->hMenu
);
363 to
->hwndParent
= HWND_16(from
->hwndParent
);
368 to
->style
= from
->style
;
369 to
->dwExStyle
= from
->dwExStyle
;
372 static void CREATESTRUCT16to32A( const CREATESTRUCT16
* from
, CREATESTRUCTA
*to
)
375 to
->lpCreateParams
= (LPVOID
)from
->lpCreateParams
;
376 to
->hInstance
= HINSTANCE_32(from
->hInstance
);
377 to
->hMenu
= HMENU_32(from
->hMenu
);
378 to
->hwndParent
= WIN_Handle32(from
->hwndParent
);
383 to
->style
= from
->style
;
384 to
->dwExStyle
= from
->dwExStyle
;
385 to
->lpszName
= MapSL(from
->lpszName
);
386 to
->lpszClass
= MapSL(from
->lpszClass
);
389 /* The strings are not copied */
390 static void MDICREATESTRUCT32Ato16( const MDICREATESTRUCTA
* from
, MDICREATESTRUCT16
* to
)
392 to
->hOwner
= HINSTANCE_16(from
->hOwner
);
397 to
->style
= from
->style
;
398 to
->lParam
= from
->lParam
;
401 static void MDICREATESTRUCT16to32A( const MDICREATESTRUCT16
* from
, MDICREATESTRUCTA
*to
)
403 to
->hOwner
= HINSTANCE_32(from
->hOwner
);
408 to
->style
= from
->style
;
409 to
->lParam
= from
->lParam
;
410 to
->szTitle
= MapSL(from
->szTitle
);
411 to
->szClass
= MapSL(from
->szClass
);
414 static WPARAM
map_wparam_char_AtoW( WPARAM wParam
, DWORD len
)
419 ch
[0] = (wParam
>> 8);
420 ch
[1] = wParam
& 0xff;
421 if (len
> 1 && ch
[0])
422 RtlMultiByteToUnicodeN( &wch
, sizeof(wch
), NULL
, ch
, 2 );
424 RtlMultiByteToUnicodeN( &wch
, sizeof(wch
), NULL
, ch
+ 1, 1 );
425 return MAKEWPARAM( wch
, HIWORD(wParam
) );
428 static WPARAM
map_wparam_char_WtoA( WPARAM wParam
, DWORD len
)
433 RtlUnicodeToMultiByteN( (LPSTR
)ch
, len
, &len
, &wch
, sizeof(wch
) );
435 return MAKEWPARAM( (ch
[0] << 8) | ch
[1], HIWORD(wParam
) );
437 return MAKEWPARAM( ch
[0], HIWORD(wParam
) );
440 /* call a 32-bit window procedure */
441 static LRESULT
call_window_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
, LRESULT
*result
, void *arg
)
447 hwnd
= WIN_GetFullHandle( hwnd
);
449 DPRINTF( "%04lx:Call window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
450 GetCurrentThreadId(), proc
, hwnd
, SPY_GetMsgName(msg
, hwnd
), wp
, lp
);
452 *result
= WINPROC_wrapper( proc
, hwnd
, msg
, wp
, lp
);
455 DPRINTF( "%04lx:Ret window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx\n",
456 GetCurrentThreadId(), proc
, hwnd
, SPY_GetMsgName(msg
, hwnd
), wp
, lp
, *result
);
460 /* call a 32-bit dialog procedure */
461 static LRESULT
call_dialog_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
, LRESULT
*result
, void *arg
)
468 hwnd
= WIN_GetFullHandle( hwnd
);
470 DPRINTF( "%04lx:Call dialog proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
471 GetCurrentThreadId(), proc
, hwnd
, SPY_GetMsgName(msg
, hwnd
), wp
, lp
);
473 ret
= WINPROC_wrapper( proc
, hwnd
, msg
, wp
, lp
);
474 *result
= GetWindowLongPtrW( hwnd
, DWLP_MSGRESULT
);
477 DPRINTF( "%04lx:Ret dialog proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx result=%08lx\n",
478 GetCurrentThreadId(), proc
, hwnd
, SPY_GetMsgName(msg
, hwnd
), wp
, lp
, ret
, *result
);
482 /* call a 16-bit window procedure */
483 static LRESULT
call_window_proc16( HWND16 hwnd
, UINT16 msg
, WPARAM16 wParam
, LPARAM lParam
,
484 LRESULT
*result
, void *arg
)
486 WNDPROC16 proc
= arg
;
495 DRAWITEMSTRUCT16 dis16
;
496 COMPAREITEMSTRUCT16 cis16
;
502 /* Window procedures want ax = hInstance, ds = es = ss */
504 memset(&context
, 0, sizeof(context
));
505 context
.SegDs
= context
.SegEs
= SELECTOROF(NtCurrentTeb()->WOW32Reserved
);
506 context
.SegFs
= wine_get_fs();
507 context
.SegGs
= wine_get_gs();
508 if (!(context
.Eax
= GetWindowWord( HWND_32(hwnd
), GWLP_HINSTANCE
))) context
.Eax
= context
.SegDs
;
509 context
.SegCs
= SELECTOROF(proc
);
510 context
.Eip
= OFFSETOF(proc
);
511 context
.Ebp
= OFFSETOF(NtCurrentTeb()->WOW32Reserved
) + (WORD
)&((STACK16FRAME
*)0)->bp
;
515 /* Some programs (eg. the "Undocumented Windows" examples, JWP) only
516 work if structures passed in lParam are placed in the stack/data
517 segment. Programmers easily make the mistake of converting lParam
518 to a near rather than a far pointer, since Windows apparently
519 allows this. We copy the structures to the 16 bit stack; this is
520 ugly but makes these programs work. */
525 size
= sizeof(CREATESTRUCT16
); break;
527 size
= sizeof(DRAWITEMSTRUCT16
); break;
529 size
= sizeof(COMPAREITEMSTRUCT16
); break;
533 memcpy( &args
.u
, MapSL(lParam
), size
);
534 lParam
= (SEGPTR
)NtCurrentTeb()->WOW32Reserved
- size
;
538 args
.params
[4] = hwnd
;
539 args
.params
[3] = msg
;
540 args
.params
[2] = wParam
;
541 args
.params
[1] = HIWORD(lParam
);
542 args
.params
[0] = LOWORD(lParam
);
543 WOWCallback16Ex( 0, WCB16_REGS
, sizeof(args
.params
) + size
, &args
, (DWORD
*)&context
);
544 *result
= MAKELONG( LOWORD(context
.Eax
), LOWORD(context
.Edx
) );
548 /* call a 16-bit dialog procedure */
549 static LRESULT
call_dialog_proc16( HWND16 hwnd
, UINT16 msg
, WPARAM16 wp
, LPARAM lp
,
550 LRESULT
*result
, void *arg
)
552 LRESULT ret
= call_window_proc16( hwnd
, msg
, wp
, lp
, result
, arg
);
553 *result
= GetWindowLongPtrW( WIN_Handle32(hwnd
), DWLP_MSGRESULT
);
557 /* helper callback for 32W->16 conversion */
558 static LRESULT
call_window_proc_Ato16( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
,
559 LRESULT
*result
, void *arg
)
561 return WINPROC_CallProc32ATo16( call_window_proc16
, hwnd
, msg
, wp
, lp
, result
, arg
);
564 /* helper callback for 32W->16 conversion */
565 static LRESULT
call_dialog_proc_Ato16( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
,
566 LRESULT
*result
, void *arg
)
568 return WINPROC_CallProc32ATo16( call_dialog_proc16
, hwnd
, msg
, wp
, lp
, result
, arg
);
571 /* helper callback for 16->32W conversion */
572 static LRESULT
call_window_proc_AtoW( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
,
573 LRESULT
*result
, void *arg
)
575 return WINPROC_CallProcAtoW( call_window_proc
, hwnd
, msg
, wp
, lp
, result
, arg
);
578 /* helper callback for 16->32W conversion */
579 static LRESULT
call_dialog_proc_AtoW( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
,
580 LRESULT
*result
, void *arg
)
582 return WINPROC_CallProcAtoW( call_dialog_proc
, hwnd
, msg
, wp
, lp
, result
, arg
);
586 /**********************************************************************
589 * Get a window procedure pointer that can be passed to the Windows program.
591 WNDPROC16
WINPROC_GetProc16( WNDPROC proc
, BOOL unicode
)
595 if (unicode
) ptr
= alloc_winproc( NULL
, proc
);
596 else ptr
= alloc_winproc( proc
, NULL
);
599 return alloc_win16_thunk( ptr
);
603 /**********************************************************************
606 * Get a window procedure pointer that can be passed to the Windows program.
608 WNDPROC
WINPROC_GetProc( WNDPROC proc
, BOOL unicode
)
610 WINDOWPROC
*ptr
= handle_to_proc( proc
);
612 if (!ptr
) return proc
;
615 if (ptr
->procW
) return ptr
->procW
;
620 if (ptr
->procA
) return ptr
->procA
;
626 /**********************************************************************
627 * WINPROC_AllocProc16
629 * Allocate a window procedure for a window or class.
631 * Note that allocated winprocs are never freed; the idea is that even if an app creates a
632 * lot of windows, it will usually only have a limited number of window procedures, so the
633 * array won't grow too large, and this way we avoid the need to track allocations per window.
635 WNDPROC
WINPROC_AllocProc16( WNDPROC16 func
)
639 if (!func
) return NULL
;
641 /* check if the function is already a win proc */
642 if (!(proc
= handle16_to_proc( func
)))
644 EnterCriticalSection( &winproc_cs
);
646 /* then check if we already have a winproc for that function */
647 if (!(proc
= find_winproc16( func
)))
649 if (winproc_used
< MAX_WINPROCS
)
651 proc
= &winproc_array
[winproc_used
++];
653 TRACE( "allocated %p for %p/16-bit (%d/%d used)\n",
654 proc_to_handle(proc
), func
, winproc_used
, MAX_WINPROCS
);
656 else FIXME( "too many winprocs, cannot allocate one for 16-bit %p\n", func
);
658 else TRACE( "reusing %p for %p/16-bit\n", proc_to_handle(proc
), func
);
660 LeaveCriticalSection( &winproc_cs
);
662 return proc_to_handle( proc
);
666 /**********************************************************************
669 * Allocate a window procedure for a window or class.
671 * Note that allocated winprocs are never freed; the idea is that even if an app creates a
672 * lot of windows, it will usually only have a limited number of window procedures, so the
673 * array won't grow too large, and this way we avoid the need to track allocations per window.
675 WNDPROC
WINPROC_AllocProc( WNDPROC funcA
, WNDPROC funcW
)
679 if (!(proc
= alloc_winproc( funcA
, funcW
))) return NULL
;
680 return proc_to_handle( proc
);
684 /**********************************************************************
687 * Return the window procedure type, or the default value if not a winproc handle.
689 BOOL
WINPROC_IsUnicode( WNDPROC proc
, BOOL def_val
)
691 WINDOWPROC
*ptr
= handle_to_proc( proc
);
693 if (!ptr
) return def_val
;
694 if (ptr
->procA
&& ptr
->procW
) return def_val
; /* can be both */
695 return (ptr
->procW
!= NULL
);
699 /**********************************************************************
700 * WINPROC_TestLBForStr
702 * Return TRUE if the lparam is a string
704 inline static BOOL
WINPROC_TestLBForStr( HWND hwnd
, UINT msg
)
706 DWORD style
= GetWindowLongA( hwnd
, GWL_STYLE
);
707 if (msg
<= CB_MSGMAX
)
708 return (!(style
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) || (style
& CBS_HASSTRINGS
));
710 return (!(style
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) || (style
& LBS_HASSTRINGS
));
715 static UINT
convert_handle_16_to_32(HANDLE16 src
, unsigned int flags
)
718 UINT sz
= GlobalSize16(src
);
721 if (!(dst
= GlobalAlloc(flags
, sz
)))
723 ptr16
= GlobalLock16(src
);
724 ptr32
= GlobalLock(dst
);
725 if (ptr16
!= NULL
&& ptr32
!= NULL
) memcpy(ptr32
, ptr16
, sz
);
732 static HANDLE16
convert_handle_32_to_16(UINT src
, unsigned int flags
)
735 UINT sz
= GlobalSize((HANDLE
)src
);
738 if (!(dst
= GlobalAlloc16(flags
, sz
)))
740 ptr32
= GlobalLock((HANDLE
)src
);
741 ptr16
= GlobalLock16(dst
);
742 if (ptr16
!= NULL
&& ptr32
!= NULL
) memcpy(ptr16
, ptr32
, sz
);
743 GlobalUnlock((HANDLE
)src
);
750 /**********************************************************************
751 * WINPROC_MapMsg32ATo16
753 * Map a message from 32-bit Ansi to 16-bit.
754 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
756 static INT
WINPROC_MapMsg32ATo16( HWND hwnd
, UINT msg32
, WPARAM wParam32
,
757 UINT16
*pmsg16
, WPARAM16
*pwparam16
, LPARAM
*plparam
)
759 *pmsg16
= (UINT16
)msg32
;
760 *pwparam16
= (WPARAM16
)LOWORD(wParam32
);
764 *pmsg16
= SBM_SETRANGE16
;
765 *plparam
= MAKELPARAM(wParam32
, *plparam
);
770 *pmsg16
= SBM_GETRANGE16
;
778 *pmsg16
= (UINT16
)msg32
+ (BM_GETCHECK16
- BM_GETCHECK
);
790 case EM_GETLINECOUNT
:
802 case EM_LINEFROMCHAR
:
804 case EM_SETPASSWORDCHAR
:
805 case EM_EMPTYUNDOBUFFER
:
806 case EM_GETFIRSTVISIBLELINE
:
808 case EM_SETWORDBREAKPROC
:
809 case EM_GETWORDBREAKPROC
:
810 case EM_GETPASSWORDCHAR
:
811 *pmsg16
= (UINT16
)msg32
+ (EM_GETSEL16
- EM_GETSEL
);
816 case LB_DELETESTRING
:
817 case LB_GETANCHORINDEX
:
818 case LB_GETCARETINDEX
:
821 case LB_GETHORIZONTALEXTENT
:
823 case LB_GETITEMHEIGHT
:
828 case LB_RESETCONTENT
:
829 case LB_SELITEMRANGE
:
830 case LB_SELITEMRANGEEX
:
831 case LB_SETANCHORINDEX
:
832 case LB_SETCARETINDEX
:
833 case LB_SETCOLUMNWIDTH
:
835 case LB_SETHORIZONTALEXTENT
:
837 case LB_SETITEMHEIGHT
:
840 *pmsg16
= (UINT16
)msg32
+ (LB_ADDSTRING16
- LB_ADDSTRING
);
842 case CB_DELETESTRING
:
844 case CB_GETLBTEXTLEN
:
846 case CB_RESETCONTENT
:
850 case CB_SHOWDROPDOWN
:
852 case CB_SETITEMHEIGHT
:
853 case CB_GETITEMHEIGHT
:
854 case CB_SETEXTENDEDUI
:
855 case CB_GETEXTENDEDUI
:
856 case CB_GETDROPPEDSTATE
:
857 *pmsg16
= (UINT16
)msg32
+ (CB_GETEDITSEL16
- CB_GETEDITSEL
);
860 *pmsg16
= CB_GETEDITSEL16
;
865 case LB_FINDSTRINGEXACT
:
866 case LB_INSERTSTRING
:
867 case LB_SELECTSTRING
:
870 *plparam
= (LPARAM
)MapLS( (LPSTR
)*plparam
);
871 *pmsg16
= (UINT16
)msg32
+ (LB_ADDSTRING16
- LB_ADDSTRING
);
876 case CB_FINDSTRINGEXACT
:
877 case CB_INSERTSTRING
:
878 case CB_SELECTSTRING
:
880 *plparam
= (LPARAM
)MapLS( (LPSTR
)*plparam
);
881 *pmsg16
= (UINT16
)msg32
+ (CB_GETEDITSEL16
- CB_GETEDITSEL
);
886 RECT16
*rect
= HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16
) + sizeof(LPARAM
) );
887 if (!rect
) return -1;
888 *(LPARAM
*)(rect
+ 1) = *plparam
; /* Store the previous lParam */
889 *plparam
= MapLS( rect
);
891 *pmsg16
= LB_GETITEMRECT16
;
895 LPARAM
*items
; /* old LPARAM first, then *pwparam16 x INT16 entries */
897 *pwparam16
= (WPARAM16
)min( wParam32
, 0x7f80 ); /* Must be < 64K */
898 if (!(items
= HeapAlloc( GetProcessHeap(), 0,
899 *pwparam16
* sizeof(INT16
) + sizeof(LPARAM
)))) return -1;
900 *items
++ = *plparam
; /* Store the previous lParam */
901 *plparam
= MapLS( items
);
903 *pmsg16
= LB_GETSELITEMS16
;
910 *pwparam16
= (WPARAM16
)min( wParam32
, 0x7f80 ); /* Must be < 64K */
911 if (!(stops
= HeapAlloc( GetProcessHeap(), 0,
912 *pwparam16
* sizeof(INT16
) + sizeof(LPARAM
)))) return -1;
913 for (i
= 0; i
< *pwparam16
; i
++) stops
[i
] = *((LPINT
)*plparam
+i
);
914 *plparam
= MapLS( stops
);
917 *pmsg16
= LB_SETTABSTOPS16
;
920 case CB_GETDROPPEDCONTROLRECT
:
922 RECT16
*rect
= HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16
) + sizeof(LPARAM
) );
923 if (!rect
) return -1;
924 *(LPARAM
*)(rect
+ 1) = *plparam
; /* Store the previous lParam */
925 *plparam
= (LPARAM
)MapLS(rect
);
927 *pmsg16
= CB_GETDROPPEDCONTROLRECT16
;
931 *plparam
= (LPARAM
)MapLS( (LPVOID
)(*plparam
) );
932 *pmsg16
= LB_GETTEXT16
;
936 *plparam
= (LPARAM
)MapLS( (LPVOID
)(*plparam
) );
937 *pmsg16
= CB_GETLBTEXT16
;
942 *plparam
= MAKELONG( (INT16
)(INT
)wParam32
, (INT16
)*plparam
);
943 *pmsg16
= EM_SETSEL16
;
950 *plparam
= MAKELPARAM( (HWND16
)*plparam
, HIWORD(wParam32
) );
954 *plparam
= MAKELPARAM( HIWORD(wParam32
), (HWND16
)*plparam
);
956 case WM_CTLCOLORMSGBOX
:
957 case WM_CTLCOLOREDIT
:
958 case WM_CTLCOLORLISTBOX
:
961 case WM_CTLCOLORSCROLLBAR
:
962 case WM_CTLCOLORSTATIC
:
963 *pmsg16
= WM_CTLCOLOR
;
964 *plparam
= MAKELPARAM( (HWND16
)*plparam
,
965 (WORD
)msg32
- WM_CTLCOLORMSGBOX
);
968 case WM_ASKCBFORMATNAME
:
970 LPARAM
*str
; /* store LPARAM, then *pwparam16 char space */
971 *pwparam16
= (WPARAM16
)min( wParam32
, 0xff80 ); /* Must be < 64K */
972 if (!(str
= HeapAlloc( GetProcessHeap(), 0, *pwparam16
+ sizeof(LPARAM
)))) return -1;
973 *str
++ = *plparam
; /* Store the previous lParam */
974 *plparam
= MapLS( str
);
977 case WM_MDIGETACTIVE
:
980 *plparam
= MAKELPARAM( (HMENU16
)LOWORD(wParam32
),
981 (HMENU16
)LOWORD(*plparam
) );
982 *pwparam16
= (*plparam
== 0);
985 if(HIWORD(wParam32
) & MF_POPUP
)
988 if (((UINT
)HIWORD(wParam32
) != 0xFFFF) || (*plparam
))
990 if((hmenu
= GetSubMenu((HMENU
)*plparam
, *pwparam16
)))
991 *pwparam16
=HMENU_16(hmenu
);
996 *plparam
= MAKELPARAM( HIWORD(wParam32
), (HMENU16
)*plparam
);
999 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
1001 *pwparam16
= ((HWND
)*plparam
== hwnd
);
1002 *plparam
= MAKELPARAM( (HWND16
)LOWORD(*plparam
),
1003 (HWND16
)LOWORD(wParam32
) );
1007 *pwparam16
= HWND_16( (HWND
)wParam32
);
1011 case WM_PARENTNOTIFY
:
1012 if ((LOWORD(wParam32
)==WM_CREATE
) || (LOWORD(wParam32
)==WM_DESTROY
))
1013 *plparam
= MAKELPARAM( (HWND16
)*plparam
, HIWORD(wParam32
));
1014 /* else nothing to do */
1017 *plparam
= MapLS( (NMHDR
*)*plparam
); /* NMHDR is already 32-bit */
1020 case WM_WININICHANGE
:
1021 case WM_DEVMODECHANGE
:
1022 *plparam
= MapLS( (LPSTR
)*plparam
);
1024 case WM_ACTIVATEAPP
:
1025 if (*plparam
) *plparam
= HTASK_16( (HANDLE
)*plparam
);
1028 if (IsIconic( hwnd
) && GetClassLongPtrW( hwnd
, GCLP_HICON
))
1030 *pmsg16
= WM_PAINTICON
;
1035 if (IsIconic( hwnd
) && GetClassLongPtrW( hwnd
, GCLP_HICON
))
1036 *pmsg16
= WM_ICONERASEBKGND
;
1038 case WM_PAINTCLIPBOARD
:
1039 case WM_SIZECLIPBOARD
:
1040 FIXME_(msg
)("message %04x needs translation\n", msg32
);
1042 /* following messages should not be sent to 16-bit apps */
1045 case WM_CAPTURECHANGED
:
1046 case WM_STYLECHANGING
:
1047 case WM_STYLECHANGED
:
1049 case WM_DDE_INITIATE
:
1050 case WM_DDE_TERMINATE
:
1051 case WM_DDE_UNADVISE
:
1052 case WM_DDE_REQUEST
:
1053 *pwparam16
= HWND_16((HWND
)wParam32
);
1062 *pwparam16
= HWND_16((HWND
)wParam32
);
1063 UnpackDDElParam(msg32
, *plparam
, &lo32
, &hi
);
1064 if (lo32
&& !(lo16
= convert_handle_32_to_16(lo32
, GMEM_DDESHARE
)))
1066 *plparam
= MAKELPARAM(lo16
, hi
);
1068 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1075 *pwparam16
= HWND_16((HWND
)wParam32
);
1077 UnpackDDElParam(msg32
, *plparam
, &lo
, &hi
);
1079 if (GlobalGetAtomNameA((ATOM
)hi
, buf
, sizeof(buf
)) > 0) flag
|= 1;
1080 if (GlobalSize((HANDLE
)hi
) != 0) flag
|= 2;
1086 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1091 break; /* atom, nothing to do */
1093 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi
);
1096 hi
= convert_handle_32_to_16(hi
, GMEM_DDESHARE
);
1099 *plparam
= MAKELPARAM(lo
, hi
);
1101 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1102 case WM_DDE_EXECUTE
:
1103 *plparam
= convert_handle_32_to_16(*plparam
, GMEM_DDESHARE
);
1104 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1105 default: /* No translation needed */
1111 /**********************************************************************
1112 * WINPROC_UnmapMsg32ATo16
1114 * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
1116 static void WINPROC_UnmapMsg32ATo16( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
,
1117 WPARAM16 wParam16
, LPARAM lParam16
, LRESULT
*result
)
1122 *(LPINT
)wParam
= LOWORD(*result
);
1123 *(LPINT
)lParam
= HIWORD(*result
);
1130 case LB_FINDSTRINGEXACT
:
1131 case LB_INSERTSTRING
:
1132 case LB_SELECTSTRING
:
1136 case CB_FINDSTRINGEXACT
:
1137 case CB_INSERTSTRING
:
1138 case CB_SELECTSTRING
:
1142 case WM_WININICHANGE
:
1143 case WM_DEVMODECHANGE
:
1144 UnMapLS( (SEGPTR
)lParam16
);
1146 case LB_SETTABSTOPS
:
1148 void *ptr
= MapSL( lParam16
);
1149 UnMapLS( lParam16
);
1150 HeapFree( GetProcessHeap(), 0, ptr
);
1153 case CB_GETDROPPEDCONTROLRECT
:
1154 case LB_GETITEMRECT
:
1157 RECT16
*rect
= MapSL(lParam16
);
1158 UnMapLS( lParam16
);
1159 lParam16
= *(LPARAM
*)(rect
+ 1);
1160 r32
= (RECT
*)lParam16
;
1161 r32
->left
= rect
->left
;
1162 r32
->top
= rect
->top
;
1163 r32
->right
= rect
->right
;
1164 r32
->bottom
= rect
->bottom
;
1165 HeapFree( GetProcessHeap(), 0, rect
);
1168 case LB_GETSELITEMS
:
1171 LPINT16 items
= MapSL(lParam16
);
1172 UnMapLS( lParam16
);
1173 lParam16
= *((LPARAM
*)items
- 1);
1174 for (i
= 0; i
< wParam16
; i
++) *((LPINT
)lParam16
+ i
) = items
[i
];
1175 HeapFree( GetProcessHeap(), 0, (LPARAM
*)items
- 1 );
1181 *((PUINT
)(wParam
)) = LOWORD(*result
);
1183 *((PUINT
)(lParam
)) = HIWORD(*result
); /* FIXME: substract 1? */
1187 case WM_ASKCBFORMATNAME
:
1189 LPSTR str
= MapSL(lParam16
);
1190 UnMapLS( lParam16
);
1191 lParam16
= *((LPARAM
*)str
- 1);
1192 lstrcpynA( (LPSTR
)lParam16
, str
, wParam16
);
1193 HeapFree( GetProcessHeap(), 0, (LPARAM
*)str
- 1 );
1196 case WM_MDIGETACTIVE
:
1197 if (lParam
) *(BOOL
*)lParam
= (BOOL16
)HIWORD(*result
);
1198 *result
= (LRESULT
)WIN_Handle32( LOWORD(*result
) );
1207 /**********************************************************************
1208 * WINPROC_CallProcAtoW
1210 * Call a window procedure, translating args from Ansi to Unicode.
1212 LRESULT
WINPROC_CallProcAtoW( winproc_callback_t callback
, HWND hwnd
, UINT msg
, WPARAM wParam
,
1213 LPARAM lParam
, LRESULT
*result
, void *arg
)
1217 TRACE_(msg
)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
1218 hwnd
, SPY_GetMsgName(msg
, hwnd
), wParam
, lParam
);
1225 WCHAR
*ptr
, buffer
[512];
1226 CREATESTRUCTA
*csA
= (CREATESTRUCTA
*)lParam
;
1227 CREATESTRUCTW csW
= *(CREATESTRUCTW
*)csA
;
1228 MDICREATESTRUCTW mdi_cs
;
1229 DWORD name_lenA
= 0, name_lenW
= 0, class_lenA
= 0, class_lenW
= 0;
1231 if (HIWORD(csA
->lpszClass
))
1233 class_lenA
= strlen(csA
->lpszClass
) + 1;
1234 RtlMultiByteToUnicodeSize( &class_lenW
, csA
->lpszClass
, class_lenA
);
1236 if (HIWORD(csA
->lpszName
))
1238 name_lenA
= strlen(csA
->lpszName
) + 1;
1239 RtlMultiByteToUnicodeSize( &name_lenW
, csA
->lpszName
, name_lenA
);
1242 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), class_lenW
+ name_lenW
))) break;
1246 csW
.lpszClass
= ptr
;
1247 RtlMultiByteToUnicodeN( ptr
, class_lenW
, NULL
, csA
->lpszClass
, class_lenA
);
1251 csW
.lpszName
= ptr
+ class_lenW
/sizeof(WCHAR
);
1252 RtlMultiByteToUnicodeN( ptr
+ class_lenW
/sizeof(WCHAR
), name_lenW
, NULL
,
1253 csA
->lpszName
, name_lenA
);
1256 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
1258 mdi_cs
= *(MDICREATESTRUCTW
*)csA
->lpCreateParams
;
1259 mdi_cs
.szTitle
= csW
.lpszName
;
1260 mdi_cs
.szClass
= csW
.lpszClass
;
1261 csW
.lpCreateParams
= &mdi_cs
;
1264 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&csW
, result
, arg
);
1265 free_buffer( buffer
, ptr
);
1271 WCHAR
*ptr
, buffer
[512];
1272 DWORD title_lenA
= 0, title_lenW
= 0, class_lenA
= 0, class_lenW
= 0;
1273 MDICREATESTRUCTA
*csA
= (MDICREATESTRUCTA
*)lParam
;
1274 MDICREATESTRUCTW csW
;
1276 memcpy( &csW
, csA
, sizeof(csW
) );
1278 if (HIWORD(csA
->szTitle
))
1280 title_lenA
= strlen(csA
->szTitle
) + 1;
1281 RtlMultiByteToUnicodeSize( &title_lenW
, csA
->szTitle
, title_lenA
);
1283 if (HIWORD(csA
->szClass
))
1285 class_lenA
= strlen(csA
->szClass
) + 1;
1286 RtlMultiByteToUnicodeSize( &class_lenW
, csA
->szClass
, class_lenA
);
1289 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), title_lenW
+ class_lenW
))) break;
1294 RtlMultiByteToUnicodeN( ptr
, title_lenW
, NULL
, csA
->szTitle
, title_lenA
);
1298 csW
.szClass
= ptr
+ title_lenW
/sizeof(WCHAR
);
1299 RtlMultiByteToUnicodeN( ptr
+ title_lenW
/sizeof(WCHAR
), class_lenW
, NULL
,
1300 csA
->szClass
, class_lenA
);
1302 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&csW
, result
, arg
);
1303 free_buffer( buffer
, ptr
);
1308 case WM_ASKCBFORMATNAME
:
1310 WCHAR
*ptr
, buffer
[512];
1311 LPSTR str
= (LPSTR
)lParam
;
1312 DWORD len
= wParam
* sizeof(WCHAR
);
1314 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
))) break;
1315 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
1316 if (*result
&& wParam
)
1318 RtlUnicodeToMultiByteN( str
, wParam
- 1, &len
, ptr
, strlenW(ptr
) * sizeof(WCHAR
) );
1322 free_buffer( buffer
, ptr
);
1327 case LB_INSERTSTRING
:
1329 case LB_FINDSTRINGEXACT
:
1330 case LB_SELECTSTRING
:
1332 case CB_INSERTSTRING
:
1334 case CB_FINDSTRINGEXACT
:
1335 case CB_SELECTSTRING
:
1336 if (!lParam
|| !WINPROC_TestLBForStr( hwnd
, msg
))
1338 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1343 case WM_WININICHANGE
:
1344 case WM_DEVMODECHANGE
:
1349 if (!lParam
) ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1352 WCHAR
*ptr
, buffer
[512];
1353 LPCSTR strA
= (LPCSTR
)lParam
;
1354 DWORD lenW
, lenA
= strlen(strA
) + 1;
1356 RtlMultiByteToUnicodeSize( &lenW
, strA
, lenA
);
1357 if ((ptr
= get_buffer( buffer
, sizeof(buffer
), lenW
)))
1359 RtlMultiByteToUnicodeN( ptr
, lenW
, NULL
, strA
, lenA
);
1360 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
1361 free_buffer( buffer
, ptr
);
1368 if (lParam
&& WINPROC_TestLBForStr( hwnd
, msg
))
1370 WCHAR buffer
[512]; /* FIXME: fixed sized buffer */
1372 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)buffer
, result
, arg
);
1376 RtlUnicodeToMultiByteN( (LPSTR
)lParam
, ~0u, &len
,
1377 buffer
, (strlenW(buffer
) + 1) * sizeof(WCHAR
) );
1381 else ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1386 WCHAR
*ptr
, buffer
[512];
1387 WORD len
= *(WORD
*)lParam
;
1389 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
* sizeof(WCHAR
) ))) break;
1390 *((WORD
*)ptr
) = len
; /* store the length */
1391 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
1395 RtlUnicodeToMultiByteN( (LPSTR
)lParam
, len
, &reslen
, ptr
, *result
* sizeof(WCHAR
) );
1396 if (reslen
< len
) ((LPSTR
)lParam
)[reslen
] = 0;
1399 free_buffer( buffer
, ptr
);
1406 MSG newmsg
= *(MSG
*)lParam
;
1407 switch(newmsg
.message
)
1412 case WM_SYSDEADCHAR
:
1413 newmsg
.wParam
= map_wparam_char_AtoW( newmsg
.wParam
, 1 );
1416 newmsg
.wParam
= map_wparam_char_AtoW( newmsg
.wParam
, 2 );
1419 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&newmsg
, result
, arg
);
1421 else ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1429 case WM_SYSDEADCHAR
:
1430 case EM_SETPASSWORDCHAR
:
1431 ret
= callback( hwnd
, msg
, map_wparam_char_AtoW(wParam
,1), lParam
, result
, arg
);
1435 ret
= callback( hwnd
, msg
, map_wparam_char_AtoW(wParam
,2), lParam
, result
, arg
);
1438 case WM_GETTEXTLENGTH
:
1439 case CB_GETLBTEXTLEN
:
1441 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1444 WCHAR
*ptr
, buffer
[512];
1446 DWORD len
= *result
+ 1;
1447 /* Determine respective GETTEXT message */
1448 UINT msgGetText
= (msg
== WM_GETTEXTLENGTH
) ? WM_GETTEXT
:
1449 ((msg
== CB_GETLBTEXTLEN
) ? CB_GETLBTEXT
: LB_GETTEXT
);
1450 /* wParam differs between the messages */
1451 WPARAM wp
= (msg
== WM_GETTEXTLENGTH
) ? len
: wParam
;
1453 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
* sizeof(WCHAR
) ))) break;
1455 if (callback
== call_window_proc
) /* FIXME: hack */
1456 callback( hwnd
, msgGetText
, wp
, (LPARAM
)ptr
, &tmp
, arg
);
1458 tmp
= SendMessageW( hwnd
, msgGetText
, wp
, (LPARAM
)ptr
);
1459 RtlUnicodeToMultiByteSize( &len
, ptr
, tmp
* sizeof(WCHAR
) );
1461 free_buffer( buffer
, ptr
);
1465 case WM_PAINTCLIPBOARD
:
1466 case WM_SIZECLIPBOARD
:
1467 FIXME_(msg
)( "message %s (0x%x) needs translation, please report\n",
1468 SPY_GetMsgName(msg
, hwnd
), msg
);
1472 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1479 /**********************************************************************
1480 * WINPROC_CallProcWtoA
1482 * Call a window procedure, translating args from Unicode to Ansi.
1484 static LRESULT
WINPROC_CallProcWtoA( winproc_callback_t callback
, HWND hwnd
, UINT msg
, WPARAM wParam
,
1485 LPARAM lParam
, LRESULT
*result
, void *arg
)
1489 TRACE_(msg
)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
1490 hwnd
, SPY_GetMsgName(msg
, hwnd
), wParam
, lParam
);
1496 { /* csW->lpszName and csW->lpszClass are NOT supposed to be atoms
1499 char buffer
[1024], *cls
, *name
;
1500 CREATESTRUCTW
*csW
= (CREATESTRUCTW
*)lParam
;
1501 CREATESTRUCTA csA
= *(CREATESTRUCTA
*)csW
;
1502 MDICREATESTRUCTA mdi_cs
;
1503 DWORD name_lenA
, name_lenW
, class_lenA
, class_lenW
;
1505 class_lenW
= strlenW(csW
->lpszClass
) * sizeof(WCHAR
);
1506 RtlUnicodeToMultiByteSize(&class_lenA
, csW
->lpszClass
, class_lenW
);
1510 name_lenW
= strlenW(csW
->lpszName
) * sizeof(WCHAR
);
1511 RtlUnicodeToMultiByteSize(&name_lenA
, csW
->lpszName
, name_lenW
);
1514 name_lenW
= name_lenA
= 0;
1516 if (!(cls
= get_buffer( buffer
, sizeof(buffer
), class_lenA
+ name_lenA
+ 2 ))) break;
1518 RtlUnicodeToMultiByteN(cls
, class_lenA
, NULL
, csW
->lpszClass
, class_lenW
);
1519 cls
[class_lenA
] = 0;
1520 csA
.lpszClass
= cls
;
1524 name
= cls
+ class_lenA
+ 1;
1525 RtlUnicodeToMultiByteN(name
, name_lenA
, NULL
, csW
->lpszName
, name_lenW
);
1526 name
[name_lenA
] = 0;
1527 csA
.lpszName
= name
;
1530 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
1532 mdi_cs
= *(MDICREATESTRUCTA
*)csW
->lpCreateParams
;
1533 mdi_cs
.szTitle
= csA
.lpszName
;
1534 mdi_cs
.szClass
= csA
.lpszClass
;
1535 csA
.lpCreateParams
= &mdi_cs
;
1538 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&csA
, result
, arg
);
1539 free_buffer( buffer
, cls
);
1544 case WM_ASKCBFORMATNAME
:
1546 char *ptr
, buffer
[512];
1547 DWORD len
= wParam
* 2;
1549 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
))) break;
1550 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
1553 RtlMultiByteToUnicodeN( (LPWSTR
)lParam
, wParam
*sizeof(WCHAR
), &len
, ptr
, strlen(ptr
)+1 );
1554 *result
= len
/sizeof(WCHAR
) - 1; /* do not count terminating null */
1555 ((LPWSTR
)lParam
)[*result
] = 0;
1557 free_buffer( buffer
, ptr
);
1562 case LB_INSERTSTRING
:
1564 case LB_FINDSTRINGEXACT
:
1565 case LB_SELECTSTRING
:
1567 case CB_INSERTSTRING
:
1569 case CB_FINDSTRINGEXACT
:
1570 case CB_SELECTSTRING
:
1571 if (!lParam
|| !WINPROC_TestLBForStr( hwnd
, msg
))
1573 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1578 case WM_WININICHANGE
:
1579 case WM_DEVMODECHANGE
:
1584 if (!lParam
) ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1587 char *ptr
, buffer
[512];
1588 LPCWSTR strW
= (LPCWSTR
)lParam
;
1589 DWORD lenA
, lenW
= (strlenW(strW
) + 1) * sizeof(WCHAR
);
1591 RtlUnicodeToMultiByteSize( &lenA
, strW
, lenW
);
1592 if ((ptr
= get_buffer( buffer
, sizeof(buffer
), lenA
)))
1594 RtlUnicodeToMultiByteN( ptr
, lenA
, NULL
, strW
, lenW
);
1595 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
1596 free_buffer( buffer
, ptr
);
1603 char *ptr
, buffer
[1024];
1604 DWORD title_lenA
= 0, title_lenW
= 0, class_lenA
= 0, class_lenW
= 0;
1605 MDICREATESTRUCTW
*csW
= (MDICREATESTRUCTW
*)lParam
;
1606 MDICREATESTRUCTA csA
;
1608 memcpy( &csA
, csW
, sizeof(csA
) );
1610 if (HIWORD(csW
->szTitle
))
1612 title_lenW
= (strlenW(csW
->szTitle
) + 1) * sizeof(WCHAR
);
1613 RtlUnicodeToMultiByteSize( &title_lenA
, csW
->szTitle
, title_lenW
);
1615 if (HIWORD(csW
->szClass
))
1617 class_lenW
= (strlenW(csW
->szClass
) + 1) * sizeof(WCHAR
);
1618 RtlUnicodeToMultiByteSize( &class_lenA
, csW
->szClass
, class_lenW
);
1621 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), title_lenA
+ class_lenA
))) break;
1625 RtlUnicodeToMultiByteN( ptr
, title_lenA
, NULL
, csW
->szTitle
, title_lenW
);
1630 RtlUnicodeToMultiByteN( ptr
+ title_lenA
, class_lenA
, NULL
, csW
->szClass
, class_lenW
);
1631 csA
.szClass
= ptr
+ title_lenA
;
1633 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&csA
, result
, arg
);
1634 free_buffer( buffer
, ptr
);
1640 if (lParam
&& WINPROC_TestLBForStr( hwnd
, msg
))
1642 char buffer
[512]; /* FIXME: fixed sized buffer */
1644 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)buffer
, result
, arg
);
1648 RtlMultiByteToUnicodeN( (LPWSTR
)lParam
, ~0u, &len
, buffer
, strlen(buffer
) + 1 );
1649 *result
= len
/ sizeof(WCHAR
) - 1;
1652 else ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1657 char *ptr
, buffer
[512];
1658 WORD len
= *(WORD
*)lParam
;
1660 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
* 2 ))) break;
1661 *((WORD
*)ptr
) = len
* 2; /* store the length */
1662 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
1666 RtlMultiByteToUnicodeN( (LPWSTR
)lParam
, len
*sizeof(WCHAR
), &reslen
, ptr
, *result
);
1667 *result
= reslen
/ sizeof(WCHAR
);
1668 if (*result
< len
) ((LPWSTR
)lParam
)[*result
] = 0;
1670 free_buffer( buffer
, ptr
);
1677 MSG newmsg
= *(MSG
*)lParam
;
1678 switch(newmsg
.message
)
1683 case WM_SYSDEADCHAR
:
1684 newmsg
.wParam
= map_wparam_char_WtoA( newmsg
.wParam
, 1 );
1687 newmsg
.wParam
= map_wparam_char_WtoA( newmsg
.wParam
, 2 );
1690 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&newmsg
, result
, arg
);
1692 else ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1700 case WM_SYSDEADCHAR
:
1701 case EM_SETPASSWORDCHAR
:
1702 ret
= callback( hwnd
, msg
, map_wparam_char_WtoA(wParam
,1), lParam
, result
, arg
);
1706 ret
= callback( hwnd
, msg
, map_wparam_char_WtoA(wParam
,2), lParam
, result
, arg
);
1709 case WM_PAINTCLIPBOARD
:
1710 case WM_SIZECLIPBOARD
:
1711 FIXME_(msg
)( "message %s (%04x) needs translation, please report\n",
1712 SPY_GetMsgName(msg
, hwnd
), msg
);
1716 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1724 /**********************************************************************
1725 * WINPROC_CallProc16To32A
1727 LRESULT
WINPROC_CallProc16To32A( winproc_callback_t callback
, HWND16 hwnd
, UINT16 msg
,
1728 WPARAM16 wParam
, LPARAM lParam
, LRESULT
*result
, void *arg
)
1731 HWND hwnd32
= WIN_Handle32( hwnd
);
1733 TRACE_(msg
)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
1734 hwnd32
, SPY_GetMsgName(msg
, hwnd32
), wParam
, lParam
);
1741 CREATESTRUCT16
*cs16
= MapSL(lParam
);
1743 MDICREATESTRUCTA mdi_cs
;
1745 CREATESTRUCT16to32A( cs16
, &cs
);
1746 if (GetWindowLongW(hwnd32
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
1748 MDICREATESTRUCT16
*mdi_cs16
= MapSL(cs16
->lpCreateParams
);
1749 MDICREATESTRUCT16to32A(mdi_cs16
, &mdi_cs
);
1750 cs
.lpCreateParams
= &mdi_cs
;
1752 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&cs
, result
, arg
);
1753 CREATESTRUCT32Ato16( &cs
, cs16
);
1758 MDICREATESTRUCT16
*cs16
= MapSL(lParam
);
1759 MDICREATESTRUCTA cs
;
1761 MDICREATESTRUCT16to32A( cs16
, &cs
);
1762 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&cs
, result
, arg
);
1763 MDICREATESTRUCT32Ato16( &cs
, cs16
);
1766 case WM_MDIACTIVATE
:
1768 ret
= callback( hwnd32
, msg
, (WPARAM
)WIN_Handle32( HIWORD(lParam
) ),
1769 (LPARAM
)WIN_Handle32( LOWORD(lParam
) ), result
, arg
);
1770 else /* message sent to MDI client */
1771 ret
= callback( hwnd32
, msg
, wParam
, lParam
, result
, arg
);
1773 case WM_MDIGETACTIVE
:
1775 BOOL maximized
= FALSE
;
1776 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&maximized
, result
, arg
);
1777 *result
= MAKELRESULT( LOWORD(*result
), maximized
);
1781 ret
= callback( hwnd32
, wParam
? WM_MDIREFRESHMENU
: WM_MDISETMENU
,
1782 (WPARAM
)HMENU_32(LOWORD(lParam
)), (LPARAM
)HMENU_32(HIWORD(lParam
)),
1785 case WM_GETMINMAXINFO
:
1787 MINMAXINFO16
*mmi16
= MapSL(lParam
);
1790 MINMAXINFO16to32( mmi16
, &mmi
);
1791 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&mmi
, result
, arg
);
1792 MINMAXINFO32to16( &mmi
, mmi16
);
1795 case WM_WINDOWPOSCHANGING
:
1796 case WM_WINDOWPOSCHANGED
:
1798 WINDOWPOS16
*winpos16
= MapSL(lParam
);
1801 WINDOWPOS16to32( winpos16
, &winpos
);
1802 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&winpos
, result
, arg
);
1803 WINDOWPOS32to16( &winpos
, winpos16
);
1808 NCCALCSIZE_PARAMS16
*nc16
= MapSL(lParam
);
1809 NCCALCSIZE_PARAMS nc
;
1812 RECT16to32( &nc16
->rgrc
[0], &nc
.rgrc
[0] );
1815 RECT16to32( &nc16
->rgrc
[1], &nc
.rgrc
[1] );
1816 RECT16to32( &nc16
->rgrc
[2], &nc
.rgrc
[2] );
1817 WINDOWPOS16to32( MapSL(nc16
->lppos
), &winpos
);
1820 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&nc
, result
, arg
);
1821 RECT32to16( &nc
.rgrc
[0], &nc16
->rgrc
[0] );
1824 RECT32to16( &nc
.rgrc
[1], &nc16
->rgrc
[1] );
1825 RECT32to16( &nc
.rgrc
[2], &nc16
->rgrc
[2] );
1826 WINDOWPOS32to16( &winpos
, MapSL(nc16
->lppos
) );
1830 case WM_COMPAREITEM
:
1832 COMPAREITEMSTRUCT16
* cis16
= MapSL(lParam
);
1833 COMPAREITEMSTRUCT cis
;
1834 cis
.CtlType
= cis16
->CtlType
;
1835 cis
.CtlID
= cis16
->CtlID
;
1836 cis
.hwndItem
= WIN_Handle32( cis16
->hwndItem
);
1837 cis
.itemID1
= cis16
->itemID1
;
1838 cis
.itemData1
= cis16
->itemData1
;
1839 cis
.itemID2
= cis16
->itemID2
;
1840 cis
.itemData2
= cis16
->itemData2
;
1841 cis
.dwLocaleId
= 0; /* FIXME */
1842 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&cis
, result
, arg
);
1847 DELETEITEMSTRUCT16
* dis16
= MapSL(lParam
);
1848 DELETEITEMSTRUCT dis
;
1849 dis
.CtlType
= dis16
->CtlType
;
1850 dis
.CtlID
= dis16
->CtlID
;
1851 dis
.hwndItem
= WIN_Handle32( dis16
->hwndItem
);
1852 dis
.itemData
= dis16
->itemData
;
1853 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&dis
, result
, arg
);
1856 case WM_MEASUREITEM
:
1858 MEASUREITEMSTRUCT16
* mis16
= MapSL(lParam
);
1859 MEASUREITEMSTRUCT mis
;
1860 mis
.CtlType
= mis16
->CtlType
;
1861 mis
.CtlID
= mis16
->CtlID
;
1862 mis
.itemID
= mis16
->itemID
;
1863 mis
.itemWidth
= mis16
->itemWidth
;
1864 mis
.itemHeight
= mis16
->itemHeight
;
1865 mis
.itemData
= mis16
->itemData
;
1866 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&mis
, result
, arg
);
1867 mis16
->itemWidth
= (UINT16
)mis
.itemWidth
;
1868 mis16
->itemHeight
= (UINT16
)mis
.itemHeight
;
1873 DRAWITEMSTRUCT16
* dis16
= MapSL(lParam
);
1875 dis
.CtlType
= dis16
->CtlType
;
1876 dis
.CtlID
= dis16
->CtlID
;
1877 dis
.itemID
= dis16
->itemID
;
1878 dis
.itemAction
= dis16
->itemAction
;
1879 dis
.itemState
= dis16
->itemState
;
1880 dis
.hwndItem
= (dis
.CtlType
== ODT_MENU
) ? (HWND
)HMENU_32(dis16
->hwndItem
)
1881 : WIN_Handle32( dis16
->hwndItem
);
1882 dis
.hDC
= HDC_32(dis16
->hDC
);
1883 dis
.itemData
= dis16
->itemData
;
1884 dis
.rcItem
.left
= dis16
->rcItem
.left
;
1885 dis
.rcItem
.top
= dis16
->rcItem
.top
;
1886 dis
.rcItem
.right
= dis16
->rcItem
.right
;
1887 dis
.rcItem
.bottom
= dis16
->rcItem
.bottom
;
1888 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&dis
, result
, arg
);
1893 COPYDATASTRUCT16
*cds16
= MapSL(lParam
);
1895 cds
.dwData
= cds16
->dwData
;
1896 cds
.cbData
= cds16
->cbData
;
1897 cds
.lpData
= MapSL(cds16
->lpData
);
1898 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&cds
, result
, arg
);
1904 MSG16
*msg16
= MapSL(lParam
);
1906 msg32
.hwnd
= WIN_Handle32( msg16
->hwnd
);
1907 msg32
.message
= msg16
->message
;
1908 msg32
.wParam
= msg16
->wParam
;
1909 msg32
.lParam
= msg16
->lParam
;
1910 msg32
.time
= msg16
->time
;
1911 msg32
.pt
.x
= msg16
->pt
.x
;
1912 msg32
.pt
.y
= msg16
->pt
.y
;
1913 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&msg32
, result
, arg
);
1916 ret
= callback( hwnd32
, msg
, wParam
, lParam
, result
, arg
);
1921 next
.hmenuIn
= (HMENU
)lParam
;
1924 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&next
, result
, arg
);
1925 *result
= MAKELONG( HMENU_16(next
.hmenuNext
), HWND_16(next
.hwndNext
) );
1932 ret
= callback( hwnd32
, msg
, MAKEWPARAM( wParam
, HIWORD(lParam
) ),
1933 (LPARAM
)WIN_Handle32( LOWORD(lParam
) ), result
, arg
);
1937 ret
= callback( hwnd32
, msg
, MAKEWPARAM( wParam
, LOWORD(lParam
) ),
1938 (LPARAM
)WIN_Handle32( HIWORD(lParam
) ), result
, arg
);
1941 if (HIWORD(lParam
) <= CTLCOLOR_STATIC
)
1942 ret
= callback( hwnd32
, WM_CTLCOLORMSGBOX
+ HIWORD(lParam
),
1943 (WPARAM
)HDC_32(wParam
), (LPARAM
)WIN_Handle32( LOWORD(lParam
) ),
1948 case WM_WININICHANGE
:
1949 case WM_DEVMODECHANGE
:
1950 case WM_ASKCBFORMATNAME
:
1952 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)MapSL(lParam
), result
, arg
);
1955 ret
= callback( hwnd32
, msg
, MAKEWPARAM( wParam
, LOWORD(lParam
) ),
1956 (LPARAM
)HMENU_32(HIWORD(lParam
)), result
, arg
);
1959 if((LOWORD(lParam
) & MF_POPUP
) && (LOWORD(lParam
) != 0xFFFF))
1961 HMENU hmenu
= HMENU_32(HIWORD(lParam
));
1962 UINT pos
= MENU_FindSubMenu( &hmenu
, HMENU_32(wParam
) );
1963 if (pos
== 0xffff) pos
= 0; /* NO_SELECTED_ITEM */
1966 ret
= callback( hwnd32
, msg
, MAKEWPARAM( wParam
, LOWORD(lParam
) ),
1967 (LPARAM
)HMENU_32(HIWORD(lParam
)), result
, arg
);
1969 case WM_PARENTNOTIFY
:
1970 if ((wParam
== WM_CREATE
) || (wParam
== WM_DESTROY
))
1971 ret
= callback( hwnd32
, msg
, MAKEWPARAM( wParam
, HIWORD(lParam
) ),
1972 (LPARAM
)WIN_Handle32( LOWORD(lParam
) ), result
, arg
);
1974 ret
= callback( hwnd32
, msg
, wParam
, lParam
, result
, arg
);
1976 case WM_ACTIVATEAPP
:
1977 /* We need this when SetActiveWindow sends a Sendmessage16() to
1978 * a 32bit window. Might be superflous with 32bit interprocess
1979 * message queues. */
1980 ret
= callback( hwnd32
, msg
, wParam
, HTASK_32(lParam
), result
, arg
);
1982 case WM_DDE_INITIATE
:
1983 case WM_DDE_TERMINATE
:
1984 case WM_DDE_UNADVISE
:
1985 case WM_DDE_REQUEST
:
1986 ret
= callback( hwnd32
, msg
, (WPARAM
)WIN_Handle32(wParam
), lParam
, result
, arg
);
1992 HANDLE16 lo16
= LOWORD(lParam
);
1994 if (lo16
&& !(lo32
= convert_handle_16_to_32(lo16
, GMEM_DDESHARE
))) break;
1995 lParam
= PackDDElParam( msg
, lo32
, HIWORD(lParam
) );
1996 ret
= callback( hwnd32
, msg
, (WPARAM
)WIN_Handle32(wParam
), lParam
, result
, arg
);
1998 break; /* FIXME don't know how to free allocated memory (handle) !! */
2001 UINT lo
= LOWORD(lParam
);
2002 UINT hi
= HIWORD(lParam
);
2006 if (GlobalGetAtomNameA(hi
, buf
, 2) > 0) flag
|= 1;
2007 if (GlobalSize16(hi
) != 0) flag
|= 2;
2013 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
2018 break; /* atom, nothing to do */
2020 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi
);
2023 hi
= convert_handle_16_to_32(hi
, GMEM_DDESHARE
);
2026 lParam
= PackDDElParam( WM_DDE_ACK
, lo
, hi
);
2027 ret
= callback( hwnd32
, msg
, (WPARAM
)WIN_Handle32(wParam
), lParam
, result
, arg
);
2029 break; /* FIXME don't know how to free allocated memory (handle) !! */
2030 case WM_DDE_EXECUTE
:
2031 lParam
= convert_handle_16_to_32( lParam
, GMEM_DDESHARE
);
2032 ret
= callback( hwnd32
, msg
, wParam
, lParam
, result
, arg
);
2033 break; /* FIXME don't know how to free allocated memory (handle) !! */
2034 case WM_PAINTCLIPBOARD
:
2035 case WM_SIZECLIPBOARD
:
2036 FIXME_(msg
)( "message %04x needs translation\n", msg
);
2039 ret
= callback( hwnd32
, msg
, wParam
, lParam
, result
, arg
);
2046 /**********************************************************************
2047 * __wine_call_wndproc (USER.1010)
2049 LRESULT WINAPI
__wine_call_wndproc( HWND16 hwnd
, UINT16 msg
, WPARAM16 wParam
, LPARAM lParam
,
2055 WINPROC_CallProc16To32A( call_window_proc
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
2057 WINPROC_CallProc16To32A( call_window_proc_AtoW
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procW
);
2062 /**********************************************************************
2063 * WINPROC_CallProc32ATo16
2065 * Call a 16-bit window procedure, translating the 32-bit args.
2067 LRESULT
WINPROC_CallProc32ATo16( winproc_callback16_t callback
, HWND hwnd
, UINT msg
,
2068 WPARAM wParam
, LPARAM lParam
, LRESULT
*result
, void *arg
)
2072 TRACE_(msg
)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2073 hwnd
, SPY_GetMsgName(msg
, hwnd
), wParam
, lParam
);
2080 CREATESTRUCTA
*cs32
= (CREATESTRUCTA
*)lParam
;
2082 MDICREATESTRUCT16 mdi_cs16
;
2083 BOOL mdi_child
= (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
);
2085 CREATESTRUCT32Ato16( cs32
, &cs
);
2086 cs
.lpszName
= MapLS( cs32
->lpszName
);
2087 cs
.lpszClass
= MapLS( cs32
->lpszClass
);
2091 MDICREATESTRUCTA
*mdi_cs
= (MDICREATESTRUCTA
*)cs32
->lpCreateParams
;
2092 MDICREATESTRUCT32Ato16( mdi_cs
, &mdi_cs16
);
2093 mdi_cs16
.szTitle
= MapLS( mdi_cs
->szTitle
);
2094 mdi_cs16
.szClass
= MapLS( mdi_cs
->szClass
);
2095 cs
.lpCreateParams
= MapLS( &mdi_cs16
);
2097 lParam
= MapLS( &cs
);
2098 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
2100 UnMapLS( cs
.lpszName
);
2101 UnMapLS( cs
.lpszClass
);
2104 UnMapLS( cs
.lpCreateParams
);
2105 UnMapLS( mdi_cs16
.szTitle
);
2106 UnMapLS( mdi_cs16
.szClass
);
2112 MDICREATESTRUCTA
*cs32
= (MDICREATESTRUCTA
*)lParam
;
2113 MDICREATESTRUCT16 cs
;
2115 MDICREATESTRUCT32Ato16( cs32
, &cs
);
2116 cs
.szTitle
= MapLS( cs32
->szTitle
);
2117 cs
.szClass
= MapLS( cs32
->szClass
);
2118 lParam
= MapLS( &cs
);
2119 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
2121 UnMapLS( cs
.szTitle
);
2122 UnMapLS( cs
.szClass
);
2125 case WM_GETMINMAXINFO
:
2127 MINMAXINFO
*mmi32
= (MINMAXINFO
*)lParam
;
2130 MINMAXINFO32to16( mmi32
, &mmi
);
2131 lParam
= MapLS( &mmi
);
2132 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
2134 MINMAXINFO16to32( &mmi
, mmi32
);
2139 NCCALCSIZE_PARAMS
*nc32
= (NCCALCSIZE_PARAMS
*)lParam
;
2140 NCCALCSIZE_PARAMS16 nc
;
2143 RECT32to16( &nc32
->rgrc
[0], &nc
.rgrc
[0] );
2146 RECT32to16( &nc32
->rgrc
[1], &nc
.rgrc
[1] );
2147 RECT32to16( &nc32
->rgrc
[2], &nc
.rgrc
[2] );
2148 WINDOWPOS32to16( nc32
->lppos
, &winpos
);
2149 nc
.lppos
= MapLS( &winpos
);
2151 lParam
= MapLS( &nc
);
2152 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
2154 RECT16to32( &nc
.rgrc
[0], &nc32
->rgrc
[0] );
2157 RECT16to32( &nc
.rgrc
[1], &nc32
->rgrc
[1] );
2158 RECT16to32( &nc
.rgrc
[2], &nc32
->rgrc
[2] );
2159 WINDOWPOS16to32( &winpos
, nc32
->lppos
);
2160 UnMapLS( nc
.lppos
);
2164 case WM_WINDOWPOSCHANGING
:
2165 case WM_WINDOWPOSCHANGED
:
2167 WINDOWPOS
*winpos32
= (WINDOWPOS
*)lParam
;
2170 WINDOWPOS32to16( winpos32
, &winpos
);
2171 lParam
= MapLS( &winpos
);
2172 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
2174 WINDOWPOS16to32( &winpos
, winpos32
);
2177 case WM_COMPAREITEM
:
2179 COMPAREITEMSTRUCT
*cis32
= (COMPAREITEMSTRUCT
*)lParam
;
2180 COMPAREITEMSTRUCT16 cis
;
2181 cis
.CtlType
= cis32
->CtlType
;
2182 cis
.CtlID
= cis32
->CtlID
;
2183 cis
.hwndItem
= HWND_16( cis32
->hwndItem
);
2184 cis
.itemID1
= cis32
->itemID1
;
2185 cis
.itemData1
= cis32
->itemData1
;
2186 cis
.itemID2
= cis32
->itemID2
;
2187 cis
.itemData2
= cis32
->itemData2
;
2188 lParam
= MapLS( &cis
);
2189 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
2195 DELETEITEMSTRUCT
*dis32
= (DELETEITEMSTRUCT
*)lParam
;
2196 DELETEITEMSTRUCT16 dis
;
2197 dis
.CtlType
= dis32
->CtlType
;
2198 dis
.CtlID
= dis32
->CtlID
;
2199 dis
.itemID
= dis32
->itemID
;
2200 dis
.hwndItem
= (dis
.CtlType
== ODT_MENU
) ? (HWND16
)LOWORD(dis32
->hwndItem
)
2201 : HWND_16( dis32
->hwndItem
);
2202 dis
.itemData
= dis32
->itemData
;
2203 lParam
= MapLS( &dis
);
2204 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
2210 DRAWITEMSTRUCT
*dis32
= (DRAWITEMSTRUCT
*)lParam
;
2211 DRAWITEMSTRUCT16 dis
;
2212 dis
.CtlType
= dis32
->CtlType
;
2213 dis
.CtlID
= dis32
->CtlID
;
2214 dis
.itemID
= dis32
->itemID
;
2215 dis
.itemAction
= dis32
->itemAction
;
2216 dis
.itemState
= dis32
->itemState
;
2217 dis
.hwndItem
= HWND_16( dis32
->hwndItem
);
2218 dis
.hDC
= HDC_16(dis32
->hDC
);
2219 dis
.itemData
= dis32
->itemData
;
2220 dis
.rcItem
.left
= dis32
->rcItem
.left
;
2221 dis
.rcItem
.top
= dis32
->rcItem
.top
;
2222 dis
.rcItem
.right
= dis32
->rcItem
.right
;
2223 dis
.rcItem
.bottom
= dis32
->rcItem
.bottom
;
2224 lParam
= MapLS( &dis
);
2225 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
2229 case WM_MEASUREITEM
:
2231 MEASUREITEMSTRUCT
*mis32
= (MEASUREITEMSTRUCT
*)lParam
;
2232 MEASUREITEMSTRUCT16 mis
;
2233 mis
.CtlType
= mis32
->CtlType
;
2234 mis
.CtlID
= mis32
->CtlID
;
2235 mis
.itemID
= mis32
->itemID
;
2236 mis
.itemWidth
= mis32
->itemWidth
;
2237 mis
.itemHeight
= mis32
->itemHeight
;
2238 mis
.itemData
= mis32
->itemData
;
2239 lParam
= MapLS( &mis
);
2240 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
2242 mis32
->itemWidth
= mis
.itemWidth
;
2243 mis32
->itemHeight
= mis
.itemHeight
;
2248 COPYDATASTRUCT
*cds32
= (COPYDATASTRUCT
*)lParam
;
2249 COPYDATASTRUCT16 cds
;
2251 cds
.dwData
= cds32
->dwData
;
2252 cds
.cbData
= cds32
->cbData
;
2253 cds
.lpData
= MapLS( cds32
->lpData
);
2254 lParam
= MapLS( &cds
);
2255 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
2257 UnMapLS( cds
.lpData
);
2263 MSG
*msg32
= (MSG
*)lParam
;
2266 msg16
.hwnd
= HWND_16( msg32
->hwnd
);
2267 msg16
.message
= msg32
->message
;
2268 msg16
.wParam
= msg32
->wParam
;
2269 msg16
.lParam
= msg32
->lParam
;
2270 msg16
.time
= msg32
->time
;
2271 msg16
.pt
.x
= msg32
->pt
.x
;
2272 msg16
.pt
.y
= msg32
->pt
.y
;
2273 lParam
= MapLS( &msg16
);
2274 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
2278 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
2282 MDINEXTMENU
*next
= (MDINEXTMENU
*)lParam
;
2283 ret
= callback( HWND_16(hwnd
), msg
, wParam
, (LPARAM
)next
->hmenuIn
, result
, arg
);
2284 next
->hmenuNext
= HMENU_32( LOWORD(*result
) );
2285 next
->hwndNext
= WIN_Handle32( HIWORD(*result
) );
2293 LPARAM lParam16
= lParam
;
2294 if (WINPROC_MapMsg32ATo16( hwnd
, msg
, wParam
, &msg16
, &wParam16
, &lParam16
) != -1)
2296 ret
= callback( HWND_16(hwnd
), msg16
, wParam16
, lParam16
, result
, arg
);
2297 WINPROC_UnmapMsg32ATo16( hwnd
, msg
, wParam
, lParam
, wParam16
, lParam16
, result
);
2306 /**********************************************************************
2307 * CallWindowProc (USER.122)
2309 LRESULT WINAPI
CallWindowProc16( WNDPROC16 func
, HWND16 hwnd
, UINT16 msg
,
2310 WPARAM16 wParam
, LPARAM lParam
)
2315 if (!func
) return 0;
2317 if (!(proc
= handle16_to_proc( func
)))
2318 call_window_proc16( hwnd
, msg
, wParam
, lParam
, &result
, func
);
2319 else if (proc
->procA
)
2320 WINPROC_CallProc16To32A( call_window_proc
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
2321 else if (proc
->procW
)
2322 WINPROC_CallProc16To32A( call_window_proc_AtoW
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procW
);
2324 call_window_proc16( hwnd
, msg
, wParam
, lParam
, &result
, proc
->proc16
);
2330 /**********************************************************************
2331 * CallWindowProcA (USER32.@)
2333 * The CallWindowProc() function invokes the windows procedure _func_,
2334 * with _hwnd_ as the target window, the message specified by _msg_, and
2335 * the message parameters _wParam_ and _lParam_.
2337 * Some kinds of argument conversion may be done, I'm not sure what.
2339 * CallWindowProc() may be used for windows subclassing. Use
2340 * SetWindowLong() to set a new windows procedure for windows of the
2341 * subclass, and handle subclassed messages in the new windows
2342 * procedure. The new windows procedure may then use CallWindowProc()
2343 * with _func_ set to the parent class's windows procedure to dispatch
2344 * the message to the superclass.
2348 * The return value is message dependent.
2354 LRESULT WINAPI
CallWindowProcA(
2355 WNDPROC func
, /* [in] window procedure */
2356 HWND hwnd
, /* [in] target window */
2357 UINT msg
, /* [in] message */
2358 WPARAM wParam
, /* [in] message dependent parameter */
2359 LPARAM lParam
/* [in] message dependent parameter */
2364 if (!func
) return 0;
2366 if (!(proc
= handle_to_proc( func
)))
2367 call_window_proc( hwnd
, msg
, wParam
, lParam
, &result
, func
);
2368 else if (proc
->procA
)
2369 call_window_proc( hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
2370 else if (proc
->procW
)
2371 WINPROC_CallProcAtoW( call_window_proc
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procW
);
2373 WINPROC_CallProc32ATo16( call_window_proc16
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->proc16
);
2378 /**********************************************************************
2379 * CallWindowProcW (USER32.@)
2381 * See CallWindowProcA.
2383 LRESULT WINAPI
CallWindowProcW( WNDPROC func
, HWND hwnd
, UINT msg
,
2384 WPARAM wParam
, LPARAM lParam
)
2389 if (!func
) return 0;
2391 if (!(proc
= handle_to_proc( func
)))
2392 call_window_proc( hwnd
, msg
, wParam
, lParam
, &result
, func
);
2393 else if (proc
->procW
)
2394 call_window_proc( hwnd
, msg
, wParam
, lParam
, &result
, proc
->procW
);
2395 else if (proc
->procA
)
2396 WINPROC_CallProcWtoA( call_window_proc
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
2398 WINPROC_CallProcWtoA( call_window_proc_Ato16
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->proc16
);
2403 /**********************************************************************
2404 * WINPROC_CallDlgProc16
2406 INT_PTR
WINPROC_CallDlgProc16( DLGPROC16 func
, HWND16 hwnd
, UINT16 msg
, WPARAM16 wParam
, LPARAM lParam
)
2412 if (!func
) return 0;
2414 if (!(proc
= handle16_to_proc( (WNDPROC16
)func
)))
2416 ret
= call_dialog_proc16( hwnd
, msg
, wParam
, lParam
, &result
, func
);
2418 else if (proc
->procA
)
2420 ret
= WINPROC_CallProc16To32A( call_dialog_proc
, hwnd
, msg
, wParam
, lParam
,
2421 &result
, proc
->procA
);
2422 SetWindowLongPtrW( WIN_Handle32(hwnd
), DWLP_MSGRESULT
, result
);
2424 else if (proc
->procW
)
2426 ret
= WINPROC_CallProc16To32A( call_dialog_proc_AtoW
, hwnd
, msg
, wParam
, lParam
,
2427 &result
, proc
->procW
);
2428 SetWindowLongPtrW( WIN_Handle32(hwnd
), DWLP_MSGRESULT
, result
);
2432 ret
= call_dialog_proc16( hwnd
, msg
, wParam
, lParam
, &result
, proc
->proc16
);
2438 /**********************************************************************
2439 * WINPROC_CallDlgProcA
2441 INT_PTR
WINPROC_CallDlgProcA( DLGPROC func
, HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2447 if (!func
) return 0;
2449 if (!(proc
= handle_to_proc( (WNDPROC
)func
)))
2450 ret
= call_dialog_proc( hwnd
, msg
, wParam
, lParam
, &result
, func
);
2451 else if (proc
->procA
)
2452 ret
= call_dialog_proc( hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
2453 else if (proc
->procW
)
2455 ret
= WINPROC_CallProcAtoW( call_dialog_proc
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procW
);
2456 SetWindowLongPtrW( hwnd
, DWLP_MSGRESULT
, result
);
2460 ret
= WINPROC_CallProc32ATo16( call_dialog_proc16
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->proc16
);
2461 SetWindowLongPtrW( hwnd
, DWLP_MSGRESULT
, result
);
2467 /**********************************************************************
2468 * WINPROC_CallDlgProcW
2470 INT_PTR
WINPROC_CallDlgProcW( DLGPROC func
, HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2476 if (!func
) return 0;
2478 if (!(proc
= handle_to_proc( (WNDPROC
)func
)))
2479 ret
= call_dialog_proc( hwnd
, msg
, wParam
, lParam
, &result
, func
);
2480 else if (proc
->procW
)
2481 ret
= call_dialog_proc( hwnd
, msg
, wParam
, lParam
, &result
, proc
->procW
);
2482 else if (proc
->procA
)
2484 ret
= WINPROC_CallProcWtoA( call_dialog_proc
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
2485 SetWindowLongPtrW( hwnd
, DWLP_MSGRESULT
, result
);
2489 ret
= WINPROC_CallProcWtoA( call_dialog_proc_Ato16
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->proc16
);
2490 SetWindowLongPtrW( hwnd
, DWLP_MSGRESULT
, result
);