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"
32 #include "wine/winbase16.h"
33 #include "wine/winuser16.h"
36 #include "user_private.h"
39 #include "wine/unicode.h"
40 #include "wine/debug.h"
42 WINE_DECLARE_DEBUG_CHANNEL(msg
);
43 WINE_DECLARE_DEBUG_CHANNEL(relay
);
44 WINE_DEFAULT_DEBUG_CHANNEL(win
);
46 typedef struct tagWINDOWPROC
48 WNDPROC16 proc16
; /* 16-bit window proc */
49 WNDPROC procA
; /* ASCII window proc */
50 WNDPROC procW
; /* Unicode window proc */
53 #define WINPROC_HANDLE (~0UL >> 16)
54 #define MAX_WINPROCS 8192
55 #define BUILTIN_WINPROCS 8 /* first BUILTIN_WINPROCS entries are reserved for builtin procs */
57 static WINDOWPROC winproc_array
[MAX_WINPROCS
];
58 static UINT builtin_used
;
59 static UINT winproc_used
= BUILTIN_WINPROCS
;
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
= BUILTIN_WINPROCS
; 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
< builtin_used
; i
++)
102 /* match either proc, some apps confuse A and W */
103 if (funcA
&& winproc_array
[i
].procA
!= funcA
&& winproc_array
[i
].procW
!= funcA
) continue;
104 if (funcW
&& winproc_array
[i
].procA
!= funcW
&& winproc_array
[i
].procW
!= funcW
) continue;
105 return &winproc_array
[i
];
107 for (i
= BUILTIN_WINPROCS
; i
< winproc_used
; i
++)
109 if (funcA
&& winproc_array
[i
].procA
!= funcA
) continue;
110 if (funcW
&& winproc_array
[i
].procW
!= funcW
) continue;
111 return &winproc_array
[i
];
116 /* find an existing builtin winproc */
117 static inline WINDOWPROC
*find_builtin_proc( WNDPROC func
)
121 for (i
= 0; i
< builtin_used
; i
++)
123 if (winproc_array
[i
].procA
== func
|| winproc_array
[i
].procW
== func
)
124 return &winproc_array
[i
];
129 /* return the window proc for a given handle, or NULL for an invalid handle */
130 static inline WINDOWPROC
*handle_to_proc( WNDPROC handle
)
132 UINT index
= LOWORD(handle
);
133 if ((ULONG_PTR
)handle
>> 16 != WINPROC_HANDLE
) return NULL
;
134 if (index
>= winproc_used
) return NULL
;
135 return &winproc_array
[index
];
138 /* create a handle for a given window proc */
139 static inline WNDPROC
proc_to_handle( WINDOWPROC
*proc
)
141 return (WNDPROC
)(ULONG_PTR
)((proc
- winproc_array
) | (WINPROC_HANDLE
<< 16));
144 /* allocate and initialize a new winproc */
145 static inline WINDOWPROC
*alloc_winproc( WNDPROC funcA
, WNDPROC funcW
)
149 /* check if the function is already a win proc */
150 if (funcA
&& (proc
= handle_to_proc( funcA
))) return proc
;
151 if (funcW
&& (proc
= handle_to_proc( funcW
))) return proc
;
152 if (!funcA
&& !funcW
) return NULL
;
154 EnterCriticalSection( &winproc_cs
);
156 /* check if we already have a winproc for that function */
157 if (!(proc
= find_winproc( funcA
, funcW
)))
161 assert( builtin_used
< BUILTIN_WINPROCS
);
162 proc
= &winproc_array
[builtin_used
++];
165 TRACE( "allocated %p for builtin %p/%p (%d/%d used)\n",
166 proc_to_handle(proc
), funcA
, funcW
, builtin_used
, BUILTIN_WINPROCS
);
168 else if (winproc_used
< MAX_WINPROCS
)
170 proc
= &winproc_array
[winproc_used
++];
173 TRACE( "allocated %p for %c %p (%d/%d used)\n",
174 proc_to_handle(proc
), funcA
? 'A' : 'W', funcA
? funcA
: funcW
,
175 winproc_used
, MAX_WINPROCS
);
177 else FIXME( "too many winprocs, cannot allocate one for %p/%p\n", funcA
, funcW
);
179 else TRACE( "reusing %p for %p/%p\n", proc_to_handle(proc
), funcA
, funcW
);
181 LeaveCriticalSection( &winproc_cs
);
188 #include "pshpack1.h"
190 /* Window procedure 16-to-32-bit thunk */
193 BYTE popl_eax
; /* popl %eax (return address) */
194 BYTE pushl_func
; /* pushl $proc */
196 BYTE pushl_eax
; /* pushl %eax */
197 BYTE ljmp
; /* ljmp relay*/
198 DWORD relay_offset
; /* __wine_call_wndproc */
204 #define MAX_THUNKS (0x10000 / sizeof(WINPROC_THUNK))
206 static WINPROC_THUNK
*thunk_array
;
207 static UINT thunk_selector
;
208 static UINT thunk_used
;
210 /* return the window proc for a given handle, or NULL for an invalid handle */
211 static inline WINDOWPROC
*handle16_to_proc( WNDPROC16 handle
)
213 if (HIWORD(handle
) == thunk_selector
)
215 UINT index
= LOWORD(handle
) / sizeof(WINPROC_THUNK
);
216 /* check alignment */
217 if (index
* sizeof(WINPROC_THUNK
) != LOWORD(handle
)) return NULL
;
218 /* check array limits */
219 if (index
>= thunk_used
) return NULL
;
220 return thunk_array
[index
].proc
;
222 return handle_to_proc( (WNDPROC
)handle
);
225 /* allocate a 16-bit thunk for an existing window proc */
226 static WNDPROC16
alloc_win16_thunk( WINDOWPROC
*proc
)
228 static FARPROC16 relay
;
231 if (proc
->proc16
) return proc
->proc16
;
233 EnterCriticalSection( &winproc_cs
);
235 if (!thunk_array
) /* allocate the array and its selector */
239 if (!(thunk_selector
= wine_ldt_alloc_entries(1))) goto done
;
240 if (!(thunk_array
= VirtualAlloc( NULL
, MAX_THUNKS
* sizeof(WINPROC_THUNK
), MEM_COMMIT
,
241 PAGE_EXECUTE_READWRITE
))) goto done
;
242 wine_ldt_set_base( &entry
, thunk_array
);
243 wine_ldt_set_limit( &entry
, MAX_THUNKS
* sizeof(WINPROC_THUNK
) - 1 );
244 wine_ldt_set_flags( &entry
, WINE_LDT_FLAGS_CODE
| WINE_LDT_FLAGS_32BIT
);
245 wine_ldt_set_entry( thunk_selector
, &entry
);
246 relay
= GetProcAddress16( GetModuleHandle16("user"), "__wine_call_wndproc" );
249 /* check if it already exists */
250 for (i
= 0; i
< thunk_used
; i
++) if (thunk_array
[i
].proc
== proc
) break;
252 if (i
== thunk_used
) /* create a new one */
254 WINPROC_THUNK
*thunk
;
256 if (thunk_used
>= MAX_THUNKS
) goto done
;
257 thunk
= &thunk_array
[thunk_used
++];
258 thunk
->popl_eax
= 0x58; /* popl %eax */
259 thunk
->pushl_func
= 0x68; /* pushl $proc */
261 thunk
->pushl_eax
= 0x50; /* pushl %eax */
262 thunk
->ljmp
= 0xea; /* ljmp relay*/
263 thunk
->relay_offset
= OFFSETOF(relay
);
264 thunk
->relay_sel
= SELECTOROF(relay
);
266 proc
->proc16
= (WNDPROC16
)MAKESEGPTR( thunk_selector
, i
* sizeof(WINPROC_THUNK
) );
268 LeaveCriticalSection( &winproc_cs
);
274 static inline WINDOWPROC
*handle16_to_proc( WNDPROC16 handle
)
276 return handle_to_proc( (WNDPROC
)handle
);
279 static inline WNDPROC16
alloc_win16_thunk( WINDOWPROC
*proc
)
284 #endif /* __i386__ */
288 /* Some window procedures modify register they shouldn't, or are not
289 * properly declared stdcall; so we need a small assembly wrapper to
291 extern LRESULT
WINPROC_wrapper( WNDPROC proc
, HWND hwnd
, UINT msg
,
292 WPARAM wParam
, LPARAM lParam
);
293 __ASM_GLOBAL_FUNC( WINPROC_wrapper
,
304 "movl 8(%ebp),%eax\n\t"
306 "leal -12(%ebp),%esp\n\t"
313 static inline LRESULT
WINPROC_wrapper( WNDPROC proc
, HWND hwnd
, UINT msg
,
314 WPARAM wParam
, LPARAM lParam
)
316 return proc( hwnd
, msg
, wParam
, lParam
);
318 #endif /* __i386__ */
320 static void RECT16to32( const RECT16
*from
, RECT
*to
)
322 to
->left
= from
->left
;
324 to
->right
= from
->right
;
325 to
->bottom
= from
->bottom
;
328 static void RECT32to16( const RECT
*from
, RECT16
*to
)
330 to
->left
= from
->left
;
332 to
->right
= from
->right
;
333 to
->bottom
= from
->bottom
;
336 static void MINMAXINFO32to16( const MINMAXINFO
*from
, MINMAXINFO16
*to
)
338 to
->ptReserved
.x
= from
->ptReserved
.x
;
339 to
->ptReserved
.y
= from
->ptReserved
.y
;
340 to
->ptMaxSize
.x
= from
->ptMaxSize
.x
;
341 to
->ptMaxSize
.y
= from
->ptMaxSize
.y
;
342 to
->ptMaxPosition
.x
= from
->ptMaxPosition
.x
;
343 to
->ptMaxPosition
.y
= from
->ptMaxPosition
.y
;
344 to
->ptMinTrackSize
.x
= from
->ptMinTrackSize
.x
;
345 to
->ptMinTrackSize
.y
= from
->ptMinTrackSize
.y
;
346 to
->ptMaxTrackSize
.x
= from
->ptMaxTrackSize
.x
;
347 to
->ptMaxTrackSize
.y
= from
->ptMaxTrackSize
.y
;
350 static void MINMAXINFO16to32( const MINMAXINFO16
*from
, MINMAXINFO
*to
)
352 to
->ptReserved
.x
= from
->ptReserved
.x
;
353 to
->ptReserved
.y
= from
->ptReserved
.y
;
354 to
->ptMaxSize
.x
= from
->ptMaxSize
.x
;
355 to
->ptMaxSize
.y
= from
->ptMaxSize
.y
;
356 to
->ptMaxPosition
.x
= from
->ptMaxPosition
.x
;
357 to
->ptMaxPosition
.y
= from
->ptMaxPosition
.y
;
358 to
->ptMinTrackSize
.x
= from
->ptMinTrackSize
.x
;
359 to
->ptMinTrackSize
.y
= from
->ptMinTrackSize
.y
;
360 to
->ptMaxTrackSize
.x
= from
->ptMaxTrackSize
.x
;
361 to
->ptMaxTrackSize
.y
= from
->ptMaxTrackSize
.y
;
364 static void WINDOWPOS32to16( const WINDOWPOS
* from
, WINDOWPOS16
* to
)
366 to
->hwnd
= HWND_16(from
->hwnd
);
367 to
->hwndInsertAfter
= HWND_16(from
->hwndInsertAfter
);
372 to
->flags
= from
->flags
;
375 static void WINDOWPOS16to32( const WINDOWPOS16
* from
, WINDOWPOS
* to
)
377 to
->hwnd
= WIN_Handle32(from
->hwnd
);
378 to
->hwndInsertAfter
= (from
->hwndInsertAfter
== (HWND16
)-1) ?
379 HWND_TOPMOST
: WIN_Handle32(from
->hwndInsertAfter
);
384 to
->flags
= from
->flags
;
387 /* The strings are not copied */
388 static void CREATESTRUCT32Ato16( const CREATESTRUCTA
* from
, CREATESTRUCT16
* to
)
390 to
->lpCreateParams
= (SEGPTR
)from
->lpCreateParams
;
391 to
->hInstance
= HINSTANCE_16(from
->hInstance
);
392 to
->hMenu
= HMENU_16(from
->hMenu
);
393 to
->hwndParent
= HWND_16(from
->hwndParent
);
398 to
->style
= from
->style
;
399 to
->dwExStyle
= from
->dwExStyle
;
402 static void CREATESTRUCT16to32A( const CREATESTRUCT16
* from
, CREATESTRUCTA
*to
)
405 to
->lpCreateParams
= (LPVOID
)from
->lpCreateParams
;
406 to
->hInstance
= HINSTANCE_32(from
->hInstance
);
407 to
->hMenu
= HMENU_32(from
->hMenu
);
408 to
->hwndParent
= WIN_Handle32(from
->hwndParent
);
413 to
->style
= from
->style
;
414 to
->dwExStyle
= from
->dwExStyle
;
415 to
->lpszName
= MapSL(from
->lpszName
);
416 to
->lpszClass
= MapSL(from
->lpszClass
);
419 /* The strings are not copied */
420 static void MDICREATESTRUCT32Ato16( const MDICREATESTRUCTA
* from
, MDICREATESTRUCT16
* to
)
422 to
->hOwner
= HINSTANCE_16(from
->hOwner
);
427 to
->style
= from
->style
;
428 to
->lParam
= from
->lParam
;
431 static void MDICREATESTRUCT16to32A( const MDICREATESTRUCT16
* from
, MDICREATESTRUCTA
*to
)
433 to
->hOwner
= HINSTANCE_32(from
->hOwner
);
438 to
->style
= from
->style
;
439 to
->lParam
= from
->lParam
;
440 to
->szTitle
= MapSL(from
->szTitle
);
441 to
->szClass
= MapSL(from
->szClass
);
444 static WPARAM
map_wparam_char_WtoA( WPARAM wParam
, DWORD len
)
449 RtlUnicodeToMultiByteN( (LPSTR
)ch
, len
, &len
, &wch
, sizeof(wch
) );
451 return MAKEWPARAM( (ch
[0] << 8) | ch
[1], HIWORD(wParam
) );
453 return MAKEWPARAM( ch
[0], HIWORD(wParam
) );
456 /* call a 32-bit window procedure */
457 static LRESULT
call_window_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
, LRESULT
*result
, void *arg
)
463 hwnd
= WIN_GetFullHandle( hwnd
);
465 DPRINTF( "%04x:Call window proc %p (hwnd=%p,msg=%s,wp=%08lx,lp=%08lx)\n",
466 GetCurrentThreadId(), proc
, hwnd
, SPY_GetMsgName(msg
, hwnd
), wp
, lp
);
468 *result
= WINPROC_wrapper( proc
, hwnd
, msg
, wp
, lp
);
471 DPRINTF( "%04x:Ret window proc %p (hwnd=%p,msg=%s,wp=%08lx,lp=%08lx) retval=%08lx\n",
472 GetCurrentThreadId(), proc
, hwnd
, SPY_GetMsgName(msg
, hwnd
), wp
, lp
, *result
);
476 /* call a 32-bit dialog procedure */
477 static LRESULT
call_dialog_proc( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
, LRESULT
*result
, void *arg
)
484 hwnd
= WIN_GetFullHandle( hwnd
);
486 DPRINTF( "%04x:Call dialog proc %p (hwnd=%p,msg=%s,wp=%08lx,lp=%08lx)\n",
487 GetCurrentThreadId(), proc
, hwnd
, SPY_GetMsgName(msg
, hwnd
), wp
, lp
);
489 ret
= WINPROC_wrapper( proc
, hwnd
, msg
, wp
, lp
);
490 *result
= GetWindowLongPtrW( hwnd
, DWLP_MSGRESULT
);
493 DPRINTF( "%04x:Ret dialog proc %p (hwnd=%p,msg=%s,wp=%08lx,lp=%08lx) retval=%08lx result=%08lx\n",
494 GetCurrentThreadId(), proc
, hwnd
, SPY_GetMsgName(msg
, hwnd
), wp
, lp
, ret
, *result
);
498 /* call a 16-bit window procedure */
499 static LRESULT
call_window_proc16( HWND16 hwnd
, UINT16 msg
, WPARAM16 wParam
, LPARAM lParam
,
500 LRESULT
*result
, void *arg
)
502 WNDPROC16 proc
= arg
;
511 DRAWITEMSTRUCT16 dis16
;
512 COMPAREITEMSTRUCT16 cis16
;
518 /* Window procedures want ax = hInstance, ds = es = ss */
520 memset(&context
, 0, sizeof(context
));
521 context
.SegDs
= context
.SegEs
= SELECTOROF(NtCurrentTeb()->WOW32Reserved
);
522 context
.SegFs
= wine_get_fs();
523 context
.SegGs
= wine_get_gs();
524 if (!(context
.Eax
= GetWindowWord( HWND_32(hwnd
), GWLP_HINSTANCE
))) context
.Eax
= context
.SegDs
;
525 context
.SegCs
= SELECTOROF(proc
);
526 context
.Eip
= OFFSETOF(proc
);
527 context
.Ebp
= OFFSETOF(NtCurrentTeb()->WOW32Reserved
) + FIELD_OFFSET(STACK16FRAME
, bp
);
531 /* Some programs (eg. the "Undocumented Windows" examples, JWP) only
532 work if structures passed in lParam are placed in the stack/data
533 segment. Programmers easily make the mistake of converting lParam
534 to a near rather than a far pointer, since Windows apparently
535 allows this. We copy the structures to the 16 bit stack; this is
536 ugly but makes these programs work. */
541 size
= sizeof(CREATESTRUCT16
); break;
543 size
= sizeof(DRAWITEMSTRUCT16
); break;
545 size
= sizeof(COMPAREITEMSTRUCT16
); break;
549 memcpy( &args
.u
, MapSL(lParam
), size
);
550 lParam
= PtrToUlong(NtCurrentTeb()->WOW32Reserved
) - size
;
554 args
.params
[4] = hwnd
;
555 args
.params
[3] = msg
;
556 args
.params
[2] = wParam
;
557 args
.params
[1] = HIWORD(lParam
);
558 args
.params
[0] = LOWORD(lParam
);
559 WOWCallback16Ex( 0, WCB16_REGS
, sizeof(args
.params
) + size
, &args
, (DWORD
*)&context
);
560 *result
= MAKELONG( LOWORD(context
.Eax
), LOWORD(context
.Edx
) );
564 /* call a 16-bit dialog procedure */
565 static LRESULT
call_dialog_proc16( HWND16 hwnd
, UINT16 msg
, WPARAM16 wp
, LPARAM lp
,
566 LRESULT
*result
, void *arg
)
568 LRESULT ret
= call_window_proc16( hwnd
, msg
, wp
, lp
, result
, arg
);
569 *result
= GetWindowLongPtrW( WIN_Handle32(hwnd
), DWLP_MSGRESULT
);
573 /* helper callback for 32W->16 conversion */
574 static LRESULT
call_window_proc_Ato16( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
,
575 LRESULT
*result
, void *arg
)
577 return WINPROC_CallProc32ATo16( call_window_proc16
, hwnd
, msg
, wp
, lp
, result
, arg
);
580 /* helper callback for 32W->16 conversion */
581 static LRESULT
call_dialog_proc_Ato16( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
,
582 LRESULT
*result
, void *arg
)
584 return WINPROC_CallProc32ATo16( call_dialog_proc16
, hwnd
, msg
, wp
, lp
, result
, arg
);
587 /* helper callback for 16->32W conversion */
588 static LRESULT
call_window_proc_AtoW( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
,
589 LRESULT
*result
, void *arg
)
591 return WINPROC_CallProcAtoW( call_window_proc
, hwnd
, msg
, wp
, lp
, result
,
592 arg
, WMCHAR_MAP_CALLWINDOWPROC
);
595 /* helper callback for 16->32W conversion */
596 static LRESULT
call_dialog_proc_AtoW( HWND hwnd
, UINT msg
, WPARAM wp
, LPARAM lp
,
597 LRESULT
*result
, void *arg
)
599 return WINPROC_CallProcAtoW( call_dialog_proc
, hwnd
, msg
, wp
, lp
, result
,
600 arg
, WMCHAR_MAP_CALLWINDOWPROC
);
604 /**********************************************************************
607 * Get a window procedure pointer that can be passed to the Windows program.
609 WNDPROC16
WINPROC_GetProc16( WNDPROC proc
, BOOL unicode
)
613 if (unicode
) ptr
= alloc_winproc( NULL
, proc
);
614 else ptr
= alloc_winproc( proc
, NULL
);
617 return alloc_win16_thunk( ptr
);
621 /**********************************************************************
624 * Get a window procedure pointer that can be passed to the Windows program.
626 WNDPROC
WINPROC_GetProc( WNDPROC proc
, BOOL unicode
)
628 WINDOWPROC
*ptr
= handle_to_proc( proc
);
630 if (!ptr
) return proc
;
633 if (ptr
->procW
) return ptr
->procW
;
638 if (ptr
->procA
) return ptr
->procA
;
644 /**********************************************************************
645 * WINPROC_AllocProc16
647 * Allocate a window procedure for a window or class.
649 * Note that allocated winprocs are never freed; the idea is that even if an app creates a
650 * lot of windows, it will usually only have a limited number of window procedures, so the
651 * array won't grow too large, and this way we avoid the need to track allocations per window.
653 WNDPROC
WINPROC_AllocProc16( WNDPROC16 func
)
657 if (!func
) return NULL
;
659 /* check if the function is already a win proc */
660 if (!(proc
= handle16_to_proc( func
)))
662 EnterCriticalSection( &winproc_cs
);
664 /* then check if we already have a winproc for that function */
665 if (!(proc
= find_winproc16( func
)))
667 if (winproc_used
< MAX_WINPROCS
)
669 proc
= &winproc_array
[winproc_used
++];
671 TRACE( "allocated %p for %p/16-bit (%d/%d used)\n",
672 proc_to_handle(proc
), func
, winproc_used
, MAX_WINPROCS
);
674 else FIXME( "too many winprocs, cannot allocate one for 16-bit %p\n", func
);
676 else TRACE( "reusing %p for %p/16-bit\n", proc_to_handle(proc
), func
);
678 LeaveCriticalSection( &winproc_cs
);
680 return proc_to_handle( proc
);
684 /**********************************************************************
687 * Allocate a window procedure for a window or class.
689 * Note that allocated winprocs are never freed; the idea is that even if an app creates a
690 * lot of windows, it will usually only have a limited number of window procedures, so the
691 * array won't grow too large, and this way we avoid the need to track allocations per window.
693 WNDPROC
WINPROC_AllocProc( WNDPROC funcA
, WNDPROC funcW
)
697 if (!(proc
= alloc_winproc( funcA
, funcW
))) return NULL
;
698 return proc_to_handle( proc
);
702 /**********************************************************************
705 * Return the window procedure type, or the default value if not a winproc handle.
707 BOOL
WINPROC_IsUnicode( WNDPROC proc
, BOOL def_val
)
709 WINDOWPROC
*ptr
= handle_to_proc( proc
);
711 if (!ptr
) return def_val
;
712 if (ptr
->procA
&& ptr
->procW
) return def_val
; /* can be both */
713 return (ptr
->procW
!= NULL
);
717 /**********************************************************************
718 * WINPROC_TestLBForStr
720 * Return TRUE if the lparam is a string
722 static inline BOOL
WINPROC_TestLBForStr( HWND hwnd
, UINT msg
)
724 DWORD style
= GetWindowLongA( hwnd
, GWL_STYLE
);
725 if (msg
<= CB_MSGMAX
)
726 return (!(style
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) || (style
& CBS_HASSTRINGS
));
728 return (!(style
& (LBS_OWNERDRAWFIXED
| LBS_OWNERDRAWVARIABLE
)) || (style
& LBS_HASSTRINGS
));
733 static UINT_PTR
convert_handle_16_to_32(HANDLE16 src
, unsigned int flags
)
736 UINT sz
= GlobalSize16(src
);
739 if (!(dst
= GlobalAlloc(flags
, sz
)))
741 ptr16
= GlobalLock16(src
);
742 ptr32
= GlobalLock(dst
);
743 if (ptr16
!= NULL
&& ptr32
!= NULL
) memcpy(ptr32
, ptr16
, sz
);
747 return (UINT_PTR
)dst
;
750 static HANDLE16
convert_handle_32_to_16(UINT_PTR src
, unsigned int flags
)
753 UINT sz
= GlobalSize((HANDLE
)src
);
756 if (!(dst
= GlobalAlloc16(flags
, sz
)))
758 ptr32
= GlobalLock((HANDLE
)src
);
759 ptr16
= GlobalLock16(dst
);
760 if (ptr16
!= NULL
&& ptr32
!= NULL
) memcpy(ptr16
, ptr32
, sz
);
761 GlobalUnlock((HANDLE
)src
);
768 /**********************************************************************
769 * WINPROC_CallProcAtoW
771 * Call a window procedure, translating args from Ansi to Unicode.
773 LRESULT
WINPROC_CallProcAtoW( winproc_callback_t callback
, HWND hwnd
, UINT msg
, WPARAM wParam
,
774 LPARAM lParam
, LRESULT
*result
, void *arg
, enum wm_char_mapping mapping
)
778 TRACE_(msg
)("(hwnd=%p,msg=%s,wp=%08lx,lp=%08lx)\n",
779 hwnd
, SPY_GetMsgName(msg
, hwnd
), wParam
, lParam
);
786 WCHAR
*ptr
, buffer
[512];
787 CREATESTRUCTA
*csA
= (CREATESTRUCTA
*)lParam
;
788 CREATESTRUCTW csW
= *(CREATESTRUCTW
*)csA
;
789 MDICREATESTRUCTW mdi_cs
;
790 DWORD name_lenA
= 0, name_lenW
= 0, class_lenA
= 0, class_lenW
= 0;
792 if (HIWORD(csA
->lpszClass
))
794 class_lenA
= strlen(csA
->lpszClass
) + 1;
795 RtlMultiByteToUnicodeSize( &class_lenW
, csA
->lpszClass
, class_lenA
);
797 if (HIWORD(csA
->lpszName
))
799 name_lenA
= strlen(csA
->lpszName
) + 1;
800 RtlMultiByteToUnicodeSize( &name_lenW
, csA
->lpszName
, name_lenA
);
803 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), class_lenW
+ name_lenW
))) break;
808 RtlMultiByteToUnicodeN( ptr
, class_lenW
, NULL
, csA
->lpszClass
, class_lenA
);
812 csW
.lpszName
= ptr
+ class_lenW
/sizeof(WCHAR
);
813 RtlMultiByteToUnicodeN( ptr
+ class_lenW
/sizeof(WCHAR
), name_lenW
, NULL
,
814 csA
->lpszName
, name_lenA
);
817 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
819 mdi_cs
= *(MDICREATESTRUCTW
*)csA
->lpCreateParams
;
820 mdi_cs
.szTitle
= csW
.lpszName
;
821 mdi_cs
.szClass
= csW
.lpszClass
;
822 csW
.lpCreateParams
= &mdi_cs
;
825 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&csW
, result
, arg
);
826 free_buffer( buffer
, ptr
);
832 WCHAR
*ptr
, buffer
[512];
833 DWORD title_lenA
= 0, title_lenW
= 0, class_lenA
= 0, class_lenW
= 0;
834 MDICREATESTRUCTA
*csA
= (MDICREATESTRUCTA
*)lParam
;
835 MDICREATESTRUCTW csW
;
837 memcpy( &csW
, csA
, sizeof(csW
) );
839 if (HIWORD(csA
->szTitle
))
841 title_lenA
= strlen(csA
->szTitle
) + 1;
842 RtlMultiByteToUnicodeSize( &title_lenW
, csA
->szTitle
, title_lenA
);
844 if (HIWORD(csA
->szClass
))
846 class_lenA
= strlen(csA
->szClass
) + 1;
847 RtlMultiByteToUnicodeSize( &class_lenW
, csA
->szClass
, class_lenA
);
850 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), title_lenW
+ class_lenW
))) break;
855 RtlMultiByteToUnicodeN( ptr
, title_lenW
, NULL
, csA
->szTitle
, title_lenA
);
859 csW
.szClass
= ptr
+ title_lenW
/sizeof(WCHAR
);
860 RtlMultiByteToUnicodeN( ptr
+ title_lenW
/sizeof(WCHAR
), class_lenW
, NULL
,
861 csA
->szClass
, class_lenA
);
863 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&csW
, result
, arg
);
864 free_buffer( buffer
, ptr
);
869 case WM_ASKCBFORMATNAME
:
871 WCHAR
*ptr
, buffer
[512];
872 LPSTR str
= (LPSTR
)lParam
;
873 DWORD len
= wParam
* sizeof(WCHAR
);
875 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
))) break;
876 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
881 RtlUnicodeToMultiByteN( str
, wParam
- 1, &len
, ptr
, strlenW(ptr
) * sizeof(WCHAR
) );
885 free_buffer( buffer
, ptr
);
890 case LB_INSERTSTRING
:
892 case LB_FINDSTRINGEXACT
:
893 case LB_SELECTSTRING
:
895 case CB_INSERTSTRING
:
897 case CB_FINDSTRINGEXACT
:
898 case CB_SELECTSTRING
:
899 if (!lParam
|| !WINPROC_TestLBForStr( hwnd
, msg
))
901 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
906 case WM_WININICHANGE
:
907 case WM_DEVMODECHANGE
:
912 if (!lParam
) ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
915 WCHAR
*ptr
, buffer
[512];
916 LPCSTR strA
= (LPCSTR
)lParam
;
917 DWORD lenW
, lenA
= strlen(strA
) + 1;
919 RtlMultiByteToUnicodeSize( &lenW
, strA
, lenA
);
920 if ((ptr
= get_buffer( buffer
, sizeof(buffer
), lenW
)))
922 RtlMultiByteToUnicodeN( ptr
, lenW
, NULL
, strA
, lenA
);
923 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
924 free_buffer( buffer
, ptr
);
931 if (lParam
&& WINPROC_TestLBForStr( hwnd
, msg
))
933 WCHAR buffer
[512]; /* FIXME: fixed sized buffer */
935 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)buffer
, result
, arg
);
939 RtlUnicodeToMultiByteN( (LPSTR
)lParam
, ~0u, &len
,
940 buffer
, (strlenW(buffer
) + 1) * sizeof(WCHAR
) );
944 else ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
949 WCHAR
*ptr
, buffer
[512];
950 WORD len
= *(WORD
*)lParam
;
952 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
* sizeof(WCHAR
) ))) break;
953 *((WORD
*)ptr
) = len
; /* store the length */
954 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
958 RtlUnicodeToMultiByteN( (LPSTR
)lParam
, len
, &reslen
, ptr
, *result
* sizeof(WCHAR
) );
959 if (reslen
< len
) ((LPSTR
)lParam
)[reslen
] = 0;
962 free_buffer( buffer
, ptr
);
969 MSG newmsg
= *(MSG
*)lParam
;
970 if (map_wparam_AtoW( newmsg
.message
, &newmsg
.wParam
, WMCHAR_MAP_NOMAPPING
))
971 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&newmsg
, result
, arg
);
973 else ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
982 case EM_SETPASSWORDCHAR
:
984 if (map_wparam_AtoW( msg
, &wParam
, mapping
))
985 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
988 case WM_GETTEXTLENGTH
:
989 case CB_GETLBTEXTLEN
:
991 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
994 WCHAR
*ptr
, buffer
[512];
996 DWORD len
= *result
+ 1;
997 /* Determine respective GETTEXT message */
998 UINT msgGetText
= (msg
== WM_GETTEXTLENGTH
) ? WM_GETTEXT
:
999 ((msg
== CB_GETLBTEXTLEN
) ? CB_GETLBTEXT
: LB_GETTEXT
);
1000 /* wParam differs between the messages */
1001 WPARAM wp
= (msg
== WM_GETTEXTLENGTH
) ? len
: wParam
;
1003 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
* sizeof(WCHAR
) ))) break;
1005 if (callback
== call_window_proc
) /* FIXME: hack */
1006 callback( hwnd
, msgGetText
, wp
, (LPARAM
)ptr
, &tmp
, arg
);
1008 tmp
= SendMessageW( hwnd
, msgGetText
, wp
, (LPARAM
)ptr
);
1009 RtlUnicodeToMultiByteSize( &len
, ptr
, tmp
* sizeof(WCHAR
) );
1011 free_buffer( buffer
, ptr
);
1015 case WM_PAINTCLIPBOARD
:
1016 case WM_SIZECLIPBOARD
:
1017 FIXME_(msg
)( "message %s (0x%x) needs translation, please report\n",
1018 SPY_GetMsgName(msg
, hwnd
), msg
);
1022 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1029 /**********************************************************************
1030 * WINPROC_CallProcWtoA
1032 * Call a window procedure, translating args from Unicode to Ansi.
1034 static LRESULT
WINPROC_CallProcWtoA( winproc_callback_t callback
, HWND hwnd
, UINT msg
, WPARAM wParam
,
1035 LPARAM lParam
, LRESULT
*result
, void *arg
)
1039 TRACE_(msg
)("(hwnd=%p,msg=%s,wp=%08lx,lp=%08lx)\n",
1040 hwnd
, SPY_GetMsgName(msg
, hwnd
), wParam
, lParam
);
1046 { /* csW->lpszName and csW->lpszClass are NOT supposed to be atoms
1049 char buffer
[1024], *cls
, *name
;
1050 CREATESTRUCTW
*csW
= (CREATESTRUCTW
*)lParam
;
1051 CREATESTRUCTA csA
= *(CREATESTRUCTA
*)csW
;
1052 MDICREATESTRUCTA mdi_cs
;
1053 DWORD name_lenA
, name_lenW
, class_lenA
, class_lenW
;
1055 class_lenW
= strlenW(csW
->lpszClass
) * sizeof(WCHAR
);
1056 RtlUnicodeToMultiByteSize(&class_lenA
, csW
->lpszClass
, class_lenW
);
1060 name_lenW
= strlenW(csW
->lpszName
) * sizeof(WCHAR
);
1061 RtlUnicodeToMultiByteSize(&name_lenA
, csW
->lpszName
, name_lenW
);
1064 name_lenW
= name_lenA
= 0;
1066 if (!(cls
= get_buffer( buffer
, sizeof(buffer
), class_lenA
+ name_lenA
+ 2 ))) break;
1068 RtlUnicodeToMultiByteN(cls
, class_lenA
, NULL
, csW
->lpszClass
, class_lenW
);
1069 cls
[class_lenA
] = 0;
1070 csA
.lpszClass
= cls
;
1074 name
= cls
+ class_lenA
+ 1;
1075 RtlUnicodeToMultiByteN(name
, name_lenA
, NULL
, csW
->lpszName
, name_lenW
);
1076 name
[name_lenA
] = 0;
1077 csA
.lpszName
= name
;
1080 if (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
1082 mdi_cs
= *(MDICREATESTRUCTA
*)csW
->lpCreateParams
;
1083 mdi_cs
.szTitle
= csA
.lpszName
;
1084 mdi_cs
.szClass
= csA
.lpszClass
;
1085 csA
.lpCreateParams
= &mdi_cs
;
1088 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&csA
, result
, arg
);
1089 free_buffer( buffer
, cls
);
1094 case WM_ASKCBFORMATNAME
:
1096 char *ptr
, buffer
[512];
1097 DWORD len
= wParam
* 2;
1099 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
))) break;
1100 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
1105 RtlMultiByteToUnicodeN( (LPWSTR
)lParam
, wParam
*sizeof(WCHAR
), &len
, ptr
, strlen(ptr
)+1 );
1106 *result
= len
/sizeof(WCHAR
) - 1; /* do not count terminating null */
1108 ((LPWSTR
)lParam
)[*result
] = 0;
1110 free_buffer( buffer
, ptr
);
1115 case LB_INSERTSTRING
:
1117 case LB_FINDSTRINGEXACT
:
1118 case LB_SELECTSTRING
:
1120 case CB_INSERTSTRING
:
1122 case CB_FINDSTRINGEXACT
:
1123 case CB_SELECTSTRING
:
1124 if (!lParam
|| !WINPROC_TestLBForStr( hwnd
, msg
))
1126 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1131 case WM_WININICHANGE
:
1132 case WM_DEVMODECHANGE
:
1137 if (!lParam
) ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1140 char *ptr
, buffer
[512];
1141 LPCWSTR strW
= (LPCWSTR
)lParam
;
1142 DWORD lenA
, lenW
= (strlenW(strW
) + 1) * sizeof(WCHAR
);
1144 RtlUnicodeToMultiByteSize( &lenA
, strW
, lenW
);
1145 if ((ptr
= get_buffer( buffer
, sizeof(buffer
), lenA
)))
1147 RtlUnicodeToMultiByteN( ptr
, lenA
, NULL
, strW
, lenW
);
1148 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
1149 free_buffer( buffer
, ptr
);
1156 char *ptr
, buffer
[1024];
1157 DWORD title_lenA
= 0, title_lenW
= 0, class_lenA
= 0, class_lenW
= 0;
1158 MDICREATESTRUCTW
*csW
= (MDICREATESTRUCTW
*)lParam
;
1159 MDICREATESTRUCTA csA
;
1161 memcpy( &csA
, csW
, sizeof(csA
) );
1163 if (HIWORD(csW
->szTitle
))
1165 title_lenW
= (strlenW(csW
->szTitle
) + 1) * sizeof(WCHAR
);
1166 RtlUnicodeToMultiByteSize( &title_lenA
, csW
->szTitle
, title_lenW
);
1168 if (HIWORD(csW
->szClass
))
1170 class_lenW
= (strlenW(csW
->szClass
) + 1) * sizeof(WCHAR
);
1171 RtlUnicodeToMultiByteSize( &class_lenA
, csW
->szClass
, class_lenW
);
1174 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), title_lenA
+ class_lenA
))) break;
1178 RtlUnicodeToMultiByteN( ptr
, title_lenA
, NULL
, csW
->szTitle
, title_lenW
);
1183 RtlUnicodeToMultiByteN( ptr
+ title_lenA
, class_lenA
, NULL
, csW
->szClass
, class_lenW
);
1184 csA
.szClass
= ptr
+ title_lenA
;
1186 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&csA
, result
, arg
);
1187 free_buffer( buffer
, ptr
);
1193 if (lParam
&& WINPROC_TestLBForStr( hwnd
, msg
))
1195 char buffer
[512]; /* FIXME: fixed sized buffer */
1197 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)buffer
, result
, arg
);
1201 RtlMultiByteToUnicodeN( (LPWSTR
)lParam
, ~0u, &len
, buffer
, strlen(buffer
) + 1 );
1202 *result
= len
/ sizeof(WCHAR
) - 1;
1205 else ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1210 char *ptr
, buffer
[512];
1211 WORD len
= *(WORD
*)lParam
;
1213 if (!(ptr
= get_buffer( buffer
, sizeof(buffer
), len
* 2 ))) break;
1214 *((WORD
*)ptr
) = len
* 2; /* store the length */
1215 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)ptr
, result
, arg
);
1219 RtlMultiByteToUnicodeN( (LPWSTR
)lParam
, len
*sizeof(WCHAR
), &reslen
, ptr
, *result
);
1220 *result
= reslen
/ sizeof(WCHAR
);
1221 if (*result
< len
) ((LPWSTR
)lParam
)[*result
] = 0;
1223 free_buffer( buffer
, ptr
);
1230 MSG newmsg
= *(MSG
*)lParam
;
1231 switch(newmsg
.message
)
1236 case WM_SYSDEADCHAR
:
1237 newmsg
.wParam
= map_wparam_char_WtoA( newmsg
.wParam
, 1 );
1240 newmsg
.wParam
= map_wparam_char_WtoA( newmsg
.wParam
, 2 );
1243 ret
= callback( hwnd
, msg
, wParam
, (LPARAM
)&newmsg
, result
, arg
);
1245 else ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1254 RtlUnicodeToMultiByteN( ch
, 2, &len
, &wch
, sizeof(wch
) );
1255 ret
= callback( hwnd
, msg
, (BYTE
)ch
[0], lParam
, result
, arg
);
1256 if (len
== 2) ret
= callback( hwnd
, msg
, (BYTE
)ch
[1], lParam
, result
, arg
);
1264 case WM_SYSDEADCHAR
:
1265 case EM_SETPASSWORDCHAR
:
1266 ret
= callback( hwnd
, msg
, map_wparam_char_WtoA(wParam
,1), lParam
, result
, arg
);
1270 ret
= callback( hwnd
, msg
, map_wparam_char_WtoA(wParam
,2), lParam
, result
, arg
);
1273 case WM_PAINTCLIPBOARD
:
1274 case WM_SIZECLIPBOARD
:
1275 FIXME_(msg
)( "message %s (%04x) needs translation, please report\n",
1276 SPY_GetMsgName(msg
, hwnd
), msg
);
1280 ret
= callback( hwnd
, msg
, wParam
, lParam
, result
, arg
);
1288 /**********************************************************************
1289 * WINPROC_CallProc16To32A
1291 LRESULT
WINPROC_CallProc16To32A( winproc_callback_t callback
, HWND16 hwnd
, UINT16 msg
,
1292 WPARAM16 wParam
, LPARAM lParam
, LRESULT
*result
, void *arg
)
1295 HWND hwnd32
= WIN_Handle32( hwnd
);
1297 TRACE_(msg
)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
1298 hwnd32
, SPY_GetMsgName(msg
, hwnd32
), wParam
, lParam
);
1305 CREATESTRUCT16
*cs16
= MapSL(lParam
);
1307 MDICREATESTRUCTA mdi_cs
;
1309 CREATESTRUCT16to32A( cs16
, &cs
);
1310 if (GetWindowLongW(hwnd32
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
1312 MDICREATESTRUCT16
*mdi_cs16
= MapSL(cs16
->lpCreateParams
);
1313 MDICREATESTRUCT16to32A(mdi_cs16
, &mdi_cs
);
1314 cs
.lpCreateParams
= &mdi_cs
;
1316 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&cs
, result
, arg
);
1317 CREATESTRUCT32Ato16( &cs
, cs16
);
1322 MDICREATESTRUCT16
*cs16
= MapSL(lParam
);
1323 MDICREATESTRUCTA cs
;
1325 MDICREATESTRUCT16to32A( cs16
, &cs
);
1326 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&cs
, result
, arg
);
1327 MDICREATESTRUCT32Ato16( &cs
, cs16
);
1330 case WM_MDIACTIVATE
:
1332 ret
= callback( hwnd32
, msg
, (WPARAM
)WIN_Handle32( HIWORD(lParam
) ),
1333 (LPARAM
)WIN_Handle32( LOWORD(lParam
) ), result
, arg
);
1334 else /* message sent to MDI client */
1335 ret
= callback( hwnd32
, msg
, wParam
, lParam
, result
, arg
);
1337 case WM_MDIGETACTIVE
:
1339 BOOL maximized
= FALSE
;
1340 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&maximized
, result
, arg
);
1341 *result
= MAKELRESULT( LOWORD(*result
), maximized
);
1345 ret
= callback( hwnd32
, wParam
? WM_MDIREFRESHMENU
: WM_MDISETMENU
,
1346 (WPARAM
)HMENU_32(LOWORD(lParam
)), (LPARAM
)HMENU_32(HIWORD(lParam
)),
1349 case WM_GETMINMAXINFO
:
1351 MINMAXINFO16
*mmi16
= MapSL(lParam
);
1354 MINMAXINFO16to32( mmi16
, &mmi
);
1355 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&mmi
, result
, arg
);
1356 MINMAXINFO32to16( &mmi
, mmi16
);
1359 case WM_WINDOWPOSCHANGING
:
1360 case WM_WINDOWPOSCHANGED
:
1362 WINDOWPOS16
*winpos16
= MapSL(lParam
);
1365 WINDOWPOS16to32( winpos16
, &winpos
);
1366 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&winpos
, result
, arg
);
1367 WINDOWPOS32to16( &winpos
, winpos16
);
1372 NCCALCSIZE_PARAMS16
*nc16
= MapSL(lParam
);
1373 NCCALCSIZE_PARAMS nc
;
1376 RECT16to32( &nc16
->rgrc
[0], &nc
.rgrc
[0] );
1379 RECT16to32( &nc16
->rgrc
[1], &nc
.rgrc
[1] );
1380 RECT16to32( &nc16
->rgrc
[2], &nc
.rgrc
[2] );
1381 WINDOWPOS16to32( MapSL(nc16
->lppos
), &winpos
);
1384 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&nc
, result
, arg
);
1385 RECT32to16( &nc
.rgrc
[0], &nc16
->rgrc
[0] );
1388 RECT32to16( &nc
.rgrc
[1], &nc16
->rgrc
[1] );
1389 RECT32to16( &nc
.rgrc
[2], &nc16
->rgrc
[2] );
1390 WINDOWPOS32to16( &winpos
, MapSL(nc16
->lppos
) );
1394 case WM_COMPAREITEM
:
1396 COMPAREITEMSTRUCT16
* cis16
= MapSL(lParam
);
1397 COMPAREITEMSTRUCT cis
;
1398 cis
.CtlType
= cis16
->CtlType
;
1399 cis
.CtlID
= cis16
->CtlID
;
1400 cis
.hwndItem
= WIN_Handle32( cis16
->hwndItem
);
1401 cis
.itemID1
= cis16
->itemID1
;
1402 cis
.itemData1
= cis16
->itemData1
;
1403 cis
.itemID2
= cis16
->itemID2
;
1404 cis
.itemData2
= cis16
->itemData2
;
1405 cis
.dwLocaleId
= 0; /* FIXME */
1406 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&cis
, result
, arg
);
1411 DELETEITEMSTRUCT16
* dis16
= MapSL(lParam
);
1412 DELETEITEMSTRUCT dis
;
1413 dis
.CtlType
= dis16
->CtlType
;
1414 dis
.CtlID
= dis16
->CtlID
;
1415 dis
.hwndItem
= WIN_Handle32( dis16
->hwndItem
);
1416 dis
.itemData
= dis16
->itemData
;
1417 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&dis
, result
, arg
);
1420 case WM_MEASUREITEM
:
1422 MEASUREITEMSTRUCT16
* mis16
= MapSL(lParam
);
1423 MEASUREITEMSTRUCT mis
;
1424 mis
.CtlType
= mis16
->CtlType
;
1425 mis
.CtlID
= mis16
->CtlID
;
1426 mis
.itemID
= mis16
->itemID
;
1427 mis
.itemWidth
= mis16
->itemWidth
;
1428 mis
.itemHeight
= mis16
->itemHeight
;
1429 mis
.itemData
= mis16
->itemData
;
1430 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&mis
, result
, arg
);
1431 mis16
->itemWidth
= (UINT16
)mis
.itemWidth
;
1432 mis16
->itemHeight
= (UINT16
)mis
.itemHeight
;
1437 DRAWITEMSTRUCT16
* dis16
= MapSL(lParam
);
1439 dis
.CtlType
= dis16
->CtlType
;
1440 dis
.CtlID
= dis16
->CtlID
;
1441 dis
.itemID
= dis16
->itemID
;
1442 dis
.itemAction
= dis16
->itemAction
;
1443 dis
.itemState
= dis16
->itemState
;
1444 dis
.hwndItem
= (dis
.CtlType
== ODT_MENU
) ? (HWND
)HMENU_32(dis16
->hwndItem
)
1445 : WIN_Handle32( dis16
->hwndItem
);
1446 dis
.hDC
= HDC_32(dis16
->hDC
);
1447 dis
.itemData
= dis16
->itemData
;
1448 dis
.rcItem
.left
= dis16
->rcItem
.left
;
1449 dis
.rcItem
.top
= dis16
->rcItem
.top
;
1450 dis
.rcItem
.right
= dis16
->rcItem
.right
;
1451 dis
.rcItem
.bottom
= dis16
->rcItem
.bottom
;
1452 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&dis
, result
, arg
);
1457 COPYDATASTRUCT16
*cds16
= MapSL(lParam
);
1459 cds
.dwData
= cds16
->dwData
;
1460 cds
.cbData
= cds16
->cbData
;
1461 cds
.lpData
= MapSL(cds16
->lpData
);
1462 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&cds
, result
, arg
);
1468 MSG16
*msg16
= MapSL(lParam
);
1470 msg32
.hwnd
= WIN_Handle32( msg16
->hwnd
);
1471 msg32
.message
= msg16
->message
;
1472 msg32
.wParam
= msg16
->wParam
;
1473 msg32
.lParam
= msg16
->lParam
;
1474 msg32
.time
= msg16
->time
;
1475 msg32
.pt
.x
= msg16
->pt
.x
;
1476 msg32
.pt
.y
= msg16
->pt
.y
;
1477 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&msg32
, result
, arg
);
1480 ret
= callback( hwnd32
, msg
, wParam
, lParam
, result
, arg
);
1485 next
.hmenuIn
= (HMENU
)lParam
;
1488 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)&next
, result
, arg
);
1489 *result
= MAKELONG( HMENU_16(next
.hmenuNext
), HWND_16(next
.hwndNext
) );
1496 ret
= callback( hwnd32
, msg
, MAKEWPARAM( wParam
, HIWORD(lParam
) ),
1497 (LPARAM
)WIN_Handle32( LOWORD(lParam
) ), result
, arg
);
1501 ret
= callback( hwnd32
, msg
, MAKEWPARAM( wParam
, LOWORD(lParam
) ),
1502 (LPARAM
)WIN_Handle32( HIWORD(lParam
) ), result
, arg
);
1505 if (HIWORD(lParam
) <= CTLCOLOR_STATIC
)
1506 ret
= callback( hwnd32
, WM_CTLCOLORMSGBOX
+ HIWORD(lParam
),
1507 (WPARAM
)HDC_32(wParam
), (LPARAM
)WIN_Handle32( LOWORD(lParam
) ),
1512 case WM_WININICHANGE
:
1513 case WM_DEVMODECHANGE
:
1514 case WM_ASKCBFORMATNAME
:
1516 ret
= callback( hwnd32
, msg
, wParam
, (LPARAM
)MapSL(lParam
), result
, arg
);
1519 ret
= callback( hwnd32
, msg
, MAKEWPARAM( wParam
, LOWORD(lParam
) ),
1520 (LPARAM
)HMENU_32(HIWORD(lParam
)), result
, arg
);
1523 if((LOWORD(lParam
) & MF_POPUP
) && (LOWORD(lParam
) != 0xFFFF))
1525 HMENU hmenu
= HMENU_32(HIWORD(lParam
));
1526 UINT pos
= MENU_FindSubMenu( &hmenu
, HMENU_32(wParam
) );
1527 if (pos
== 0xffff) pos
= 0; /* NO_SELECTED_ITEM */
1530 ret
= callback( hwnd32
, msg
, MAKEWPARAM( wParam
, LOWORD(lParam
) ),
1531 (LPARAM
)HMENU_32(HIWORD(lParam
)), result
, arg
);
1533 case WM_PARENTNOTIFY
:
1534 if ((wParam
== WM_CREATE
) || (wParam
== WM_DESTROY
))
1535 ret
= callback( hwnd32
, msg
, MAKEWPARAM( wParam
, HIWORD(lParam
) ),
1536 (LPARAM
)WIN_Handle32( LOWORD(lParam
) ), result
, arg
);
1538 ret
= callback( hwnd32
, msg
, wParam
, lParam
, result
, arg
);
1540 case WM_ACTIVATEAPP
:
1541 /* We need this when SetActiveWindow sends a Sendmessage16() to
1542 * a 32bit window. Might be superflous with 32bit interprocess
1543 * message queues. */
1544 if (lParam
) lParam
= HTASK_32(lParam
);
1545 ret
= callback( hwnd32
, msg
, wParam
, lParam
, result
, arg
);
1547 case WM_DDE_INITIATE
:
1548 case WM_DDE_TERMINATE
:
1549 case WM_DDE_UNADVISE
:
1550 case WM_DDE_REQUEST
:
1551 ret
= callback( hwnd32
, msg
, (WPARAM
)WIN_Handle32(wParam
), lParam
, result
, arg
);
1557 HANDLE16 lo16
= LOWORD(lParam
);
1559 if (lo16
&& !(lo32
= convert_handle_16_to_32(lo16
, GMEM_DDESHARE
))) break;
1560 lParam
= PackDDElParam( msg
, lo32
, HIWORD(lParam
) );
1561 ret
= callback( hwnd32
, msg
, (WPARAM
)WIN_Handle32(wParam
), lParam
, result
, arg
);
1563 break; /* FIXME don't know how to free allocated memory (handle) !! */
1566 UINT_PTR lo
= LOWORD(lParam
);
1567 UINT_PTR hi
= HIWORD(lParam
);
1571 if (GlobalGetAtomNameA(hi
, buf
, 2) > 0) flag
|= 1;
1572 if (GlobalSize16(hi
) != 0) flag
|= 2;
1578 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1583 break; /* atom, nothing to do */
1585 MESSAGE("DDE_ACK: %lx both atom and handle... choosing handle\n", hi
);
1588 hi
= convert_handle_16_to_32(hi
, GMEM_DDESHARE
);
1591 lParam
= PackDDElParam( WM_DDE_ACK
, lo
, hi
);
1592 ret
= callback( hwnd32
, msg
, (WPARAM
)WIN_Handle32(wParam
), lParam
, result
, arg
);
1594 break; /* FIXME don't know how to free allocated memory (handle) !! */
1595 case WM_DDE_EXECUTE
:
1596 lParam
= convert_handle_16_to_32( lParam
, GMEM_DDESHARE
);
1597 ret
= callback( hwnd32
, msg
, wParam
, lParam
, result
, arg
);
1598 break; /* FIXME don't know how to free allocated memory (handle) !! */
1599 case WM_PAINTCLIPBOARD
:
1600 case WM_SIZECLIPBOARD
:
1601 FIXME_(msg
)( "message %04x needs translation\n", msg
);
1604 ret
= callback( hwnd32
, msg
, wParam
, lParam
, result
, arg
);
1611 /**********************************************************************
1612 * __wine_call_wndproc (USER.1010)
1614 LRESULT WINAPI
__wine_call_wndproc( HWND16 hwnd
, UINT16 msg
, WPARAM16 wParam
, LPARAM lParam
,
1620 WINPROC_CallProc16To32A( call_window_proc
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
1622 WINPROC_CallProc16To32A( call_window_proc_AtoW
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procW
);
1627 /**********************************************************************
1628 * WINPROC_CallProc32ATo16
1630 * Call a 16-bit window procedure, translating the 32-bit args.
1632 LRESULT
WINPROC_CallProc32ATo16( winproc_callback16_t callback
, HWND hwnd
, UINT msg
,
1633 WPARAM wParam
, LPARAM lParam
, LRESULT
*result
, void *arg
)
1637 TRACE_(msg
)("(hwnd=%p,msg=%s,wp=%08lx,lp=%08lx)\n",
1638 hwnd
, SPY_GetMsgName(msg
, hwnd
), wParam
, lParam
);
1645 CREATESTRUCTA
*cs32
= (CREATESTRUCTA
*)lParam
;
1647 MDICREATESTRUCT16 mdi_cs16
;
1648 BOOL mdi_child
= (GetWindowLongW(hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
);
1650 CREATESTRUCT32Ato16( cs32
, &cs
);
1651 cs
.lpszName
= MapLS( cs32
->lpszName
);
1652 cs
.lpszClass
= MapLS( cs32
->lpszClass
);
1656 MDICREATESTRUCTA
*mdi_cs
= (MDICREATESTRUCTA
*)cs32
->lpCreateParams
;
1657 MDICREATESTRUCT32Ato16( mdi_cs
, &mdi_cs16
);
1658 mdi_cs16
.szTitle
= MapLS( mdi_cs
->szTitle
);
1659 mdi_cs16
.szClass
= MapLS( mdi_cs
->szClass
);
1660 cs
.lpCreateParams
= MapLS( &mdi_cs16
);
1662 lParam
= MapLS( &cs
);
1663 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1665 UnMapLS( cs
.lpszName
);
1666 UnMapLS( cs
.lpszClass
);
1669 UnMapLS( cs
.lpCreateParams
);
1670 UnMapLS( mdi_cs16
.szTitle
);
1671 UnMapLS( mdi_cs16
.szClass
);
1677 MDICREATESTRUCTA
*cs32
= (MDICREATESTRUCTA
*)lParam
;
1678 MDICREATESTRUCT16 cs
;
1680 MDICREATESTRUCT32Ato16( cs32
, &cs
);
1681 cs
.szTitle
= MapLS( cs32
->szTitle
);
1682 cs
.szClass
= MapLS( cs32
->szClass
);
1683 lParam
= MapLS( &cs
);
1684 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1686 UnMapLS( cs
.szTitle
);
1687 UnMapLS( cs
.szClass
);
1690 case WM_MDIACTIVATE
:
1691 if (GetWindowLongW( hwnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
1692 ret
= callback( HWND_16(hwnd
), msg
, ((HWND
)lParam
== hwnd
),
1693 MAKELPARAM( LOWORD(lParam
), LOWORD(wParam
) ), result
, arg
);
1695 ret
= callback( HWND_16(hwnd
), msg
, HWND_16( (HWND
)wParam
), 0, result
, arg
);
1697 case WM_MDIGETACTIVE
:
1698 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1699 if (lParam
) *(BOOL
*)lParam
= (BOOL16
)HIWORD(*result
);
1700 *result
= (LRESULT
)WIN_Handle32( LOWORD(*result
) );
1703 ret
= callback( HWND_16(hwnd
), msg
, (lParam
== 0),
1704 MAKELPARAM( LOWORD(wParam
), LOWORD(lParam
) ), result
, arg
);
1706 case WM_GETMINMAXINFO
:
1708 MINMAXINFO
*mmi32
= (MINMAXINFO
*)lParam
;
1711 MINMAXINFO32to16( mmi32
, &mmi
);
1712 lParam
= MapLS( &mmi
);
1713 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1715 MINMAXINFO16to32( &mmi
, mmi32
);
1720 NCCALCSIZE_PARAMS
*nc32
= (NCCALCSIZE_PARAMS
*)lParam
;
1721 NCCALCSIZE_PARAMS16 nc
;
1724 RECT32to16( &nc32
->rgrc
[0], &nc
.rgrc
[0] );
1727 RECT32to16( &nc32
->rgrc
[1], &nc
.rgrc
[1] );
1728 RECT32to16( &nc32
->rgrc
[2], &nc
.rgrc
[2] );
1729 WINDOWPOS32to16( nc32
->lppos
, &winpos
);
1730 nc
.lppos
= MapLS( &winpos
);
1732 lParam
= MapLS( &nc
);
1733 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1735 RECT16to32( &nc
.rgrc
[0], &nc32
->rgrc
[0] );
1738 RECT16to32( &nc
.rgrc
[1], &nc32
->rgrc
[1] );
1739 RECT16to32( &nc
.rgrc
[2], &nc32
->rgrc
[2] );
1740 WINDOWPOS16to32( &winpos
, nc32
->lppos
);
1741 UnMapLS( nc
.lppos
);
1745 case WM_WINDOWPOSCHANGING
:
1746 case WM_WINDOWPOSCHANGED
:
1748 WINDOWPOS
*winpos32
= (WINDOWPOS
*)lParam
;
1751 WINDOWPOS32to16( winpos32
, &winpos
);
1752 lParam
= MapLS( &winpos
);
1753 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1755 WINDOWPOS16to32( &winpos
, winpos32
);
1758 case WM_COMPAREITEM
:
1760 COMPAREITEMSTRUCT
*cis32
= (COMPAREITEMSTRUCT
*)lParam
;
1761 COMPAREITEMSTRUCT16 cis
;
1762 cis
.CtlType
= cis32
->CtlType
;
1763 cis
.CtlID
= cis32
->CtlID
;
1764 cis
.hwndItem
= HWND_16( cis32
->hwndItem
);
1765 cis
.itemID1
= cis32
->itemID1
;
1766 cis
.itemData1
= cis32
->itemData1
;
1767 cis
.itemID2
= cis32
->itemID2
;
1768 cis
.itemData2
= cis32
->itemData2
;
1769 lParam
= MapLS( &cis
);
1770 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1776 DELETEITEMSTRUCT
*dis32
= (DELETEITEMSTRUCT
*)lParam
;
1777 DELETEITEMSTRUCT16 dis
;
1778 dis
.CtlType
= dis32
->CtlType
;
1779 dis
.CtlID
= dis32
->CtlID
;
1780 dis
.itemID
= dis32
->itemID
;
1781 dis
.hwndItem
= (dis
.CtlType
== ODT_MENU
) ? (HWND16
)LOWORD(dis32
->hwndItem
)
1782 : HWND_16( dis32
->hwndItem
);
1783 dis
.itemData
= dis32
->itemData
;
1784 lParam
= MapLS( &dis
);
1785 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1791 DRAWITEMSTRUCT
*dis32
= (DRAWITEMSTRUCT
*)lParam
;
1792 DRAWITEMSTRUCT16 dis
;
1793 dis
.CtlType
= dis32
->CtlType
;
1794 dis
.CtlID
= dis32
->CtlID
;
1795 dis
.itemID
= dis32
->itemID
;
1796 dis
.itemAction
= dis32
->itemAction
;
1797 dis
.itemState
= dis32
->itemState
;
1798 dis
.hwndItem
= HWND_16( dis32
->hwndItem
);
1799 dis
.hDC
= HDC_16(dis32
->hDC
);
1800 dis
.itemData
= dis32
->itemData
;
1801 dis
.rcItem
.left
= dis32
->rcItem
.left
;
1802 dis
.rcItem
.top
= dis32
->rcItem
.top
;
1803 dis
.rcItem
.right
= dis32
->rcItem
.right
;
1804 dis
.rcItem
.bottom
= dis32
->rcItem
.bottom
;
1805 lParam
= MapLS( &dis
);
1806 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1810 case WM_MEASUREITEM
:
1812 MEASUREITEMSTRUCT
*mis32
= (MEASUREITEMSTRUCT
*)lParam
;
1813 MEASUREITEMSTRUCT16 mis
;
1814 mis
.CtlType
= mis32
->CtlType
;
1815 mis
.CtlID
= mis32
->CtlID
;
1816 mis
.itemID
= mis32
->itemID
;
1817 mis
.itemWidth
= mis32
->itemWidth
;
1818 mis
.itemHeight
= mis32
->itemHeight
;
1819 mis
.itemData
= mis32
->itemData
;
1820 lParam
= MapLS( &mis
);
1821 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1823 mis32
->itemWidth
= mis
.itemWidth
;
1824 mis32
->itemHeight
= mis
.itemHeight
;
1829 COPYDATASTRUCT
*cds32
= (COPYDATASTRUCT
*)lParam
;
1830 COPYDATASTRUCT16 cds
;
1832 cds
.dwData
= cds32
->dwData
;
1833 cds
.cbData
= cds32
->cbData
;
1834 cds
.lpData
= MapLS( cds32
->lpData
);
1835 lParam
= MapLS( &cds
);
1836 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1838 UnMapLS( cds
.lpData
);
1844 MSG
*msg32
= (MSG
*)lParam
;
1847 msg16
.hwnd
= HWND_16( msg32
->hwnd
);
1848 msg16
.message
= msg32
->message
;
1849 msg16
.wParam
= msg32
->wParam
;
1850 msg16
.lParam
= msg32
->lParam
;
1851 msg16
.time
= msg32
->time
;
1852 msg16
.pt
.x
= msg32
->pt
.x
;
1853 msg16
.pt
.y
= msg32
->pt
.y
;
1854 lParam
= MapLS( &msg16
);
1855 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1859 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1863 MDINEXTMENU
*next
= (MDINEXTMENU
*)lParam
;
1864 ret
= callback( HWND_16(hwnd
), msg
, wParam
, (LPARAM
)next
->hmenuIn
, result
, arg
);
1865 next
->hmenuNext
= HMENU_32( LOWORD(*result
) );
1866 next
->hwndNext
= WIN_Handle32( HIWORD(*result
) );
1871 case WM_ASKCBFORMATNAME
:
1872 wParam
= min( wParam
, 0xff80 ); /* Must be < 64K */
1876 case WM_WININICHANGE
:
1877 case WM_DEVMODECHANGE
:
1878 lParam
= MapLS( (void *)lParam
);
1879 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1886 ret
= callback( HWND_16(hwnd
), msg
, wParam
, MAKELPARAM( (HWND16
)lParam
, HIWORD(wParam
) ),
1891 ret
= callback( HWND_16(hwnd
), msg
, wParam
, MAKELPARAM( HIWORD(wParam
), (HWND16
)lParam
),
1894 case WM_CTLCOLORMSGBOX
:
1895 case WM_CTLCOLOREDIT
:
1896 case WM_CTLCOLORLISTBOX
:
1897 case WM_CTLCOLORBTN
:
1898 case WM_CTLCOLORDLG
:
1899 case WM_CTLCOLORSCROLLBAR
:
1900 case WM_CTLCOLORSTATIC
:
1901 ret
= callback( HWND_16(hwnd
), WM_CTLCOLOR
, wParam
,
1902 MAKELPARAM( (HWND16
)lParam
, msg
- WM_CTLCOLORMSGBOX
), result
, arg
);
1905 if(HIWORD(wParam
) & MF_POPUP
)
1908 if ((HIWORD(wParam
) != 0xffff) || lParam
)
1910 if ((hmenu
= GetSubMenu( (HMENU
)lParam
, LOWORD(wParam
) )))
1912 ret
= callback( HWND_16(hwnd
), msg
, HMENU_16(hmenu
),
1913 MAKELPARAM( HIWORD(wParam
), (HMENU16
)lParam
), result
, arg
);
1920 ret
= callback( HWND_16(hwnd
), msg
, wParam
,
1921 MAKELPARAM( HIWORD(wParam
), (HMENU16
)lParam
), result
, arg
);
1923 case WM_PARENTNOTIFY
:
1924 if ((LOWORD(wParam
) == WM_CREATE
) || (LOWORD(wParam
) == WM_DESTROY
))
1925 ret
= callback( HWND_16(hwnd
), msg
, wParam
,
1926 MAKELPARAM( (HWND16
)lParam
, HIWORD(wParam
) ), result
, arg
);
1928 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1930 case WM_ACTIVATEAPP
:
1931 ret
= callback( HWND_16(hwnd
), msg
, wParam
, HTASK_16( (HANDLE
)lParam
), result
, arg
);
1934 if (IsIconic( hwnd
) && GetClassLongPtrW( hwnd
, GCLP_HICON
))
1935 ret
= callback( HWND_16(hwnd
), WM_PAINTICON
, 1, lParam
, result
, arg
);
1937 ret
= callback( HWND_16(hwnd
), WM_PAINT
, wParam
, lParam
, result
, arg
);
1940 if (IsIconic( hwnd
) && GetClassLongPtrW( hwnd
, GCLP_HICON
)) msg
= WM_ICONERASEBKGND
;
1941 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1943 case WM_DDE_INITIATE
:
1944 case WM_DDE_TERMINATE
:
1945 case WM_DDE_UNADVISE
:
1946 case WM_DDE_REQUEST
:
1947 ret
= callback( HWND_16(hwnd
), msg
, HWND_16((HWND
)wParam
), lParam
, result
, arg
);
1956 UnpackDDElParam( msg
, lParam
, &lo32
, &hi
);
1957 if (lo32
&& !(lo16
= convert_handle_32_to_16(lo32
, GMEM_DDESHARE
))) break;
1958 ret
= callback( HWND_16(hwnd
), msg
, HWND_16((HWND
)wParam
),
1959 MAKELPARAM(lo16
, hi
), result
, arg
);
1961 break; /* FIXME don't know how to free allocated memory (handle) !! */
1968 UnpackDDElParam( msg
, lParam
, &lo
, &hi
);
1970 if (GlobalGetAtomNameA((ATOM
)hi
, buf
, sizeof(buf
)) > 0) flag
|= 1;
1971 if (GlobalSize((HANDLE
)hi
) != 0) flag
|= 2;
1977 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1982 break; /* atom, nothing to do */
1984 MESSAGE("DDE_ACK: %lx both atom and handle... choosing handle\n", hi
);
1987 hi
= convert_handle_32_to_16(hi
, GMEM_DDESHARE
);
1990 ret
= callback( HWND_16(hwnd
), msg
, HWND_16((HWND
)wParam
),
1991 MAKELPARAM(lo
, hi
), result
, arg
);
1993 break; /* FIXME don't know how to free allocated memory (handle) !! */
1994 case WM_DDE_EXECUTE
:
1995 lParam
= convert_handle_32_to_16(lParam
, GMEM_DDESHARE
);
1996 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
1997 break; /* FIXME don't know how to free allocated memory (handle) !! */
1999 ret
= callback( HWND_16(hwnd
), SBM_SETRANGE16
, 0, MAKELPARAM(wParam
, lParam
), result
, arg
);
2002 ret
= callback( HWND_16(hwnd
), SBM_GETRANGE16
, wParam
, lParam
, result
, arg
);
2003 *(LPINT
)wParam
= LOWORD(*result
);
2004 *(LPINT
)lParam
= HIWORD(*result
);
2011 ret
= callback( HWND_16(hwnd
), msg
+ BM_GETCHECK16
- BM_GETCHECK
, wParam
, lParam
, result
, arg
);
2019 case EM_SCROLLCARET
:
2022 case EM_GETLINECOUNT
:
2034 case EM_LINEFROMCHAR
:
2035 case EM_SETTABSTOPS
:
2036 case EM_SETPASSWORDCHAR
:
2037 case EM_EMPTYUNDOBUFFER
:
2038 case EM_GETFIRSTVISIBLELINE
:
2039 case EM_SETREADONLY
:
2040 case EM_SETWORDBREAKPROC
:
2041 case EM_GETWORDBREAKPROC
:
2042 case EM_GETPASSWORDCHAR
:
2043 ret
= callback( HWND_16(hwnd
), msg
+ EM_GETSEL16
- EM_GETSEL
, wParam
, lParam
, result
, arg
);
2046 ret
= callback( HWND_16(hwnd
), EM_SETSEL16
, 0, MAKELPARAM( wParam
, lParam
), result
, arg
);
2050 case LB_DELETESTRING
:
2051 case LB_GETANCHORINDEX
:
2052 case LB_GETCARETINDEX
:
2055 case LB_GETHORIZONTALEXTENT
:
2056 case LB_GETITEMDATA
:
2057 case LB_GETITEMHEIGHT
:
2059 case LB_GETSELCOUNT
:
2061 case LB_GETTOPINDEX
:
2062 case LB_RESETCONTENT
:
2063 case LB_SELITEMRANGE
:
2064 case LB_SELITEMRANGEEX
:
2065 case LB_SETANCHORINDEX
:
2066 case LB_SETCARETINDEX
:
2067 case LB_SETCOLUMNWIDTH
:
2069 case LB_SETHORIZONTALEXTENT
:
2070 case LB_SETITEMDATA
:
2071 case LB_SETITEMHEIGHT
:
2073 case LB_SETTOPINDEX
:
2074 ret
= callback( HWND_16(hwnd
), msg
+ LB_ADDSTRING16
- LB_ADDSTRING
, wParam
, lParam
, result
, arg
);
2078 case LB_FINDSTRINGEXACT
:
2079 case LB_INSERTSTRING
:
2080 case LB_SELECTSTRING
:
2084 lParam
= MapLS( (LPSTR
)lParam
);
2085 ret
= callback( HWND_16(hwnd
), msg
+ LB_ADDSTRING16
- LB_ADDSTRING
, wParam
, lParam
, result
, arg
);
2088 case LB_GETSELITEMS
:
2090 INT
*items32
= (INT
*)lParam
;
2091 INT16
*items
, buffer
[512];
2094 wParam
= min( wParam
, 0x7f80 ); /* Must be < 64K */
2095 if (!(items
= get_buffer( buffer
, sizeof(buffer
), wParam
* sizeof(INT16
) ))) break;
2096 lParam
= MapLS( items
);
2097 ret
= callback( HWND_16(hwnd
), LB_GETSELITEMS16
, wParam
, lParam
, result
, arg
);
2099 for (i
= 0; i
< wParam
; i
++) items32
[i
] = items
[i
];
2100 free_buffer( buffer
, items
);
2103 case LB_SETTABSTOPS
:
2106 INT
*stops32
= (INT
*)lParam
;
2107 INT16
*stops
, buffer
[512];
2110 wParam
= min( wParam
, 0x7f80 ); /* Must be < 64K */
2111 if (!(stops
= get_buffer( buffer
, sizeof(buffer
), wParam
* sizeof(INT16
) ))) break;
2112 for (i
= 0; i
< wParam
; i
++) stops
[i
] = stops32
[i
];
2113 lParam
= MapLS( stops
);
2114 ret
= callback( HWND_16(hwnd
), LB_SETTABSTOPS16
, wParam
, lParam
, result
, arg
);
2116 free_buffer( buffer
, stops
);
2118 else ret
= callback( HWND_16(hwnd
), LB_SETTABSTOPS16
, wParam
, lParam
, result
, arg
);
2120 case CB_DELETESTRING
:
2122 case CB_GETLBTEXTLEN
:
2124 case CB_RESETCONTENT
:
2128 case CB_SHOWDROPDOWN
:
2129 case CB_SETITEMDATA
:
2130 case CB_SETITEMHEIGHT
:
2131 case CB_GETITEMHEIGHT
:
2132 case CB_SETEXTENDEDUI
:
2133 case CB_GETEXTENDEDUI
:
2134 case CB_GETDROPPEDSTATE
:
2135 ret
= callback( HWND_16(hwnd
), msg
+ CB_GETEDITSEL16
- CB_GETEDITSEL
, wParam
, lParam
, result
, arg
);
2138 ret
= callback( HWND_16(hwnd
), CB_GETEDITSEL16
, wParam
, lParam
, result
, arg
);
2139 if (wParam
) *((PUINT
)(wParam
)) = LOWORD(*result
);
2140 if (lParam
) *((PUINT
)(lParam
)) = HIWORD(*result
); /* FIXME: substract 1? */
2144 case CB_FINDSTRINGEXACT
:
2145 case CB_INSERTSTRING
:
2146 case CB_SELECTSTRING
:
2149 lParam
= MapLS( (LPSTR
)lParam
);
2150 ret
= callback( HWND_16(hwnd
), msg
+ CB_GETEDITSEL16
- CB_GETEDITSEL
, wParam
, lParam
, result
, arg
);
2153 case LB_GETITEMRECT
:
2154 case CB_GETDROPPEDCONTROLRECT
:
2156 RECT
*r32
= (RECT
*)lParam
;
2158 lParam
= MapLS( &rect
);
2159 ret
= callback( HWND_16(hwnd
),
2160 (msg
== LB_GETITEMRECT
) ? LB_GETITEMRECT16
: CB_GETDROPPEDCONTROLRECT16
,
2161 wParam
, lParam
, result
, arg
);
2163 RECT16to32( &rect
, r32
);
2166 case WM_PAINTCLIPBOARD
:
2167 case WM_SIZECLIPBOARD
:
2168 FIXME_(msg
)( "message %04x needs translation\n", msg
);
2170 /* the following messages should not be sent to 16-bit apps */
2173 case WM_CAPTURECHANGED
:
2174 case WM_STYLECHANGING
:
2175 case WM_STYLECHANGED
:
2178 ret
= callback( HWND_16(hwnd
), msg
, wParam
, lParam
, result
, arg
);
2185 /**********************************************************************
2186 * WINPROC_call_window
2188 * Call the window procedure of the specified window.
2190 BOOL
WINPROC_call_window( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
,
2191 LRESULT
*result
, BOOL unicode
, enum wm_char_mapping mapping
)
2196 if (!(wndPtr
= WIN_GetPtr( hwnd
))) return FALSE
;
2197 if (wndPtr
== WND_OTHER_PROCESS
|| wndPtr
== WND_DESKTOP
) return FALSE
;
2198 if (wndPtr
->tid
!= GetCurrentThreadId())
2200 WIN_ReleasePtr( wndPtr
);
2203 proc
= handle_to_proc( wndPtr
->winproc
);
2204 WIN_ReleasePtr( wndPtr
);
2206 if (!proc
) return TRUE
;
2211 call_window_proc( hwnd
, msg
, wParam
, lParam
, result
, proc
->procW
);
2212 else if (proc
->procA
)
2213 WINPROC_CallProcWtoA( call_window_proc
, hwnd
, msg
, wParam
, lParam
, result
, proc
->procA
);
2215 WINPROC_CallProcWtoA( call_window_proc_Ato16
, hwnd
, msg
, wParam
, lParam
, result
, proc
->proc16
);
2220 call_window_proc( hwnd
, msg
, wParam
, lParam
, result
, proc
->procA
);
2221 else if (proc
->procW
)
2222 WINPROC_CallProcAtoW( call_window_proc
, hwnd
, msg
, wParam
, lParam
, result
, proc
->procW
, mapping
);
2224 WINPROC_CallProc32ATo16( call_window_proc16
, hwnd
, msg
, wParam
, lParam
, result
, proc
->proc16
);
2230 /**********************************************************************
2231 * CallWindowProc (USER.122)
2233 LRESULT WINAPI
CallWindowProc16( WNDPROC16 func
, HWND16 hwnd
, UINT16 msg
,
2234 WPARAM16 wParam
, LPARAM lParam
)
2239 if (!func
) return 0;
2241 if (!(proc
= handle16_to_proc( func
)))
2242 call_window_proc16( hwnd
, msg
, wParam
, lParam
, &result
, func
);
2243 else if (proc
->procA
)
2244 WINPROC_CallProc16To32A( call_window_proc
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
2245 else if (proc
->procW
)
2246 WINPROC_CallProc16To32A( call_window_proc_AtoW
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procW
);
2248 call_window_proc16( hwnd
, msg
, wParam
, lParam
, &result
, proc
->proc16
);
2254 /**********************************************************************
2255 * CallWindowProcA (USER32.@)
2257 * The CallWindowProc() function invokes the windows procedure _func_,
2258 * with _hwnd_ as the target window, the message specified by _msg_, and
2259 * the message parameters _wParam_ and _lParam_.
2261 * Some kinds of argument conversion may be done, I'm not sure what.
2263 * CallWindowProc() may be used for windows subclassing. Use
2264 * SetWindowLong() to set a new windows procedure for windows of the
2265 * subclass, and handle subclassed messages in the new windows
2266 * procedure. The new windows procedure may then use CallWindowProc()
2267 * with _func_ set to the parent class's windows procedure to dispatch
2268 * the message to the superclass.
2272 * The return value is message dependent.
2278 LRESULT WINAPI
CallWindowProcA(
2279 WNDPROC func
, /* [in] window procedure */
2280 HWND hwnd
, /* [in] target window */
2281 UINT msg
, /* [in] message */
2282 WPARAM wParam
, /* [in] message dependent parameter */
2283 LPARAM lParam
/* [in] message dependent parameter */
2288 if (!func
) return 0;
2290 if (!(proc
= handle_to_proc( func
)))
2292 if ((proc
= find_builtin_proc( func
)) && !IsWindowUnicode( hwnd
))
2293 call_window_proc( hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
2295 call_window_proc( hwnd
, msg
, wParam
, lParam
, &result
, func
);
2297 else if (proc
->procA
)
2298 call_window_proc( hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
2299 else if (proc
->procW
)
2300 WINPROC_CallProcAtoW( call_window_proc
, hwnd
, msg
, wParam
, lParam
, &result
,
2301 proc
->procW
, WMCHAR_MAP_CALLWINDOWPROC
);
2303 WINPROC_CallProc32ATo16( call_window_proc16
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->proc16
);
2308 /**********************************************************************
2309 * CallWindowProcW (USER32.@)
2311 * See CallWindowProcA.
2313 LRESULT WINAPI
CallWindowProcW( WNDPROC func
, HWND hwnd
, UINT msg
,
2314 WPARAM wParam
, LPARAM lParam
)
2319 if (!func
) return 0;
2321 if (!(proc
= handle_to_proc( func
)))
2323 if ((proc
= find_builtin_proc( func
)) && IsWindowUnicode( hwnd
))
2324 call_window_proc( hwnd
, msg
, wParam
, lParam
, &result
, proc
->procW
);
2326 call_window_proc( hwnd
, msg
, wParam
, lParam
, &result
, func
);
2328 else if (proc
->procW
)
2329 call_window_proc( hwnd
, msg
, wParam
, lParam
, &result
, proc
->procW
);
2330 else if (proc
->procA
)
2331 WINPROC_CallProcWtoA( call_window_proc
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
2333 WINPROC_CallProcWtoA( call_window_proc_Ato16
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->proc16
);
2338 /**********************************************************************
2339 * WINPROC_CallDlgProc16
2341 INT_PTR
WINPROC_CallDlgProc16( DLGPROC16 func
, HWND16 hwnd
, UINT16 msg
, WPARAM16 wParam
, LPARAM lParam
)
2347 if (!func
) return 0;
2349 if (!(proc
= handle16_to_proc( (WNDPROC16
)func
)))
2351 ret
= call_dialog_proc16( hwnd
, msg
, wParam
, lParam
, &result
, func
);
2353 else if (proc
->procA
)
2355 ret
= WINPROC_CallProc16To32A( call_dialog_proc
, hwnd
, msg
, wParam
, lParam
,
2356 &result
, proc
->procA
);
2357 SetWindowLongPtrW( WIN_Handle32(hwnd
), DWLP_MSGRESULT
, result
);
2359 else if (proc
->procW
)
2361 ret
= WINPROC_CallProc16To32A( call_dialog_proc_AtoW
, hwnd
, msg
, wParam
, lParam
,
2362 &result
, proc
->procW
);
2363 SetWindowLongPtrW( WIN_Handle32(hwnd
), DWLP_MSGRESULT
, result
);
2367 ret
= call_dialog_proc16( hwnd
, msg
, wParam
, lParam
, &result
, proc
->proc16
);
2373 /**********************************************************************
2374 * WINPROC_CallDlgProcA
2376 INT_PTR
WINPROC_CallDlgProcA( DLGPROC func
, HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2382 if (!func
) return 0;
2384 if (!(proc
= handle_to_proc( func
)))
2386 if ((proc
= find_builtin_proc( func
)) && !IsWindowUnicode( hwnd
))
2387 ret
= call_dialog_proc( hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
2389 ret
= call_dialog_proc( hwnd
, msg
, wParam
, lParam
, &result
, func
);
2391 else if (proc
->procA
)
2392 ret
= call_dialog_proc( hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
2393 else if (proc
->procW
)
2395 ret
= WINPROC_CallProcAtoW( call_dialog_proc
, hwnd
, msg
, wParam
, lParam
, &result
,
2396 proc
->procW
, WMCHAR_MAP_CALLWINDOWPROC
);
2397 SetWindowLongPtrW( hwnd
, DWLP_MSGRESULT
, result
);
2401 ret
= WINPROC_CallProc32ATo16( call_dialog_proc16
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->proc16
);
2402 SetWindowLongPtrW( hwnd
, DWLP_MSGRESULT
, result
);
2408 /**********************************************************************
2409 * WINPROC_CallDlgProcW
2411 INT_PTR
WINPROC_CallDlgProcW( DLGPROC func
, HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2417 if (!func
) return 0;
2419 if (!(proc
= handle_to_proc( func
)))
2421 if ((proc
= find_builtin_proc( func
)) && IsWindowUnicode( hwnd
))
2422 ret
= call_dialog_proc( hwnd
, msg
, wParam
, lParam
, &result
, proc
->procW
);
2424 ret
= call_dialog_proc( hwnd
, msg
, wParam
, lParam
, &result
, func
);
2426 else if (proc
->procW
)
2427 ret
= call_dialog_proc( hwnd
, msg
, wParam
, lParam
, &result
, proc
->procW
);
2428 else if (proc
->procA
)
2430 ret
= WINPROC_CallProcWtoA( call_dialog_proc
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->procA
);
2431 SetWindowLongPtrW( hwnd
, DWLP_MSGRESULT
, result
);
2435 ret
= WINPROC_CallProcWtoA( call_dialog_proc_Ato16
, hwnd
, msg
, wParam
, lParam
, &result
, proc
->proc16
);
2436 SetWindowLongPtrW( hwnd
, DWLP_MSGRESULT
, result
);