user: Use winproc callbacks for the remaining 16-bit messaging functions.
[wine/gsoc_dplay.git] / dlls / user / winproc.c
blob382c0bdf84269dadb4f50b74e4f8821f8a2a812b
1 /*
2 * Window procedure callbacks
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1996 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <string.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "wownt32.h"
33 #include "wine/winbase16.h"
34 #include "wine/winuser16.h"
35 #include "controls.h"
36 #include "win.h"
37 #include "winproc.h"
38 #include "user_private.h"
39 #include "dde.h"
40 #include "winternl.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 */
53 } WINDOWPROC;
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 =
64 0, 0, &winproc_cs,
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 /* map a Unicode string to a 16-bit pointer */
82 inline static SEGPTR map_str_32W_to_16( LPCWSTR str )
84 LPSTR ret;
85 INT len;
87 if (!HIWORD(str)) return (SEGPTR)LOWORD(str);
88 len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
89 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
90 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
91 return MapLS(ret);
94 /* unmap a Unicode string that was converted to a 16-bit pointer */
95 inline static void unmap_str_32W_to_16( SEGPTR str )
97 if (!HIWORD(str)) return;
98 HeapFree( GetProcessHeap(), 0, MapSL(str) );
99 UnMapLS( str );
102 /* map a 16-bit pointer to a Unicode string */
103 inline static LPWSTR map_str_16_to_32W( SEGPTR str )
105 LPWSTR ret;
106 INT len;
108 if (!HIWORD(str)) return (LPWSTR)(ULONG_PTR)LOWORD(str);
109 len = MultiByteToWideChar( CP_ACP, 0, MapSL(str), -1, NULL, 0 );
110 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
111 MultiByteToWideChar( CP_ACP, 0, MapSL(str), -1, ret, len );
112 return ret;
115 /* unmap a 16-bit pointer that was converted to a Unicode string */
116 inline static void unmap_str_16_to_32W( LPCWSTR str )
118 if (HIWORD(str)) HeapFree( GetProcessHeap(), 0, (void *)str );
121 /* find an existing winproc for a given 16-bit function and type */
122 /* FIXME: probably should do something more clever than a linear search */
123 static inline WINDOWPROC *find_winproc16( WNDPROC16 func )
125 unsigned int i;
127 for (i = 0; i < winproc_used; i++)
129 if (winproc_array[i].proc16 == func) return &winproc_array[i];
131 return NULL;
134 /* find an existing winproc for a given function and type */
135 /* FIXME: probably should do something more clever than a linear search */
136 static inline WINDOWPROC *find_winproc( WNDPROC funcA, WNDPROC funcW )
138 unsigned int i;
140 for (i = 0; i < winproc_used; i++)
142 if (funcA && winproc_array[i].procA != funcA) continue;
143 if (funcW && winproc_array[i].procW != funcW) continue;
144 return &winproc_array[i];
146 return NULL;
149 /* return the window proc for a given handle, or NULL for an invalid handle */
150 static inline WINDOWPROC *handle_to_proc( WNDPROC handle )
152 UINT index = LOWORD(handle);
153 if ((ULONG_PTR)handle >> 16 != WINPROC_HANDLE) return NULL;
154 if (index >= winproc_used) return NULL;
155 return &winproc_array[index];
158 /* create a handle for a given window proc */
159 static inline WNDPROC proc_to_handle( WINDOWPROC *proc )
161 return (WNDPROC)(ULONG_PTR)((proc - winproc_array) | (WINPROC_HANDLE << 16));
164 /* allocate and initialize a new winproc */
165 static inline WINDOWPROC *alloc_winproc( WNDPROC funcA, WNDPROC funcW )
167 WINDOWPROC *proc;
169 /* check if the function is already a win proc */
170 if (funcA && (proc = handle_to_proc( funcA ))) return proc;
171 if (funcW && (proc = handle_to_proc( funcW ))) return proc;
172 if (!funcA && !funcW) return NULL;
174 EnterCriticalSection( &winproc_cs );
176 /* check if we already have a winproc for that function */
177 if (!(proc = find_winproc( funcA, funcW )))
179 if (winproc_used < MAX_WINPROCS)
181 proc = &winproc_array[winproc_used++];
182 proc->procA = funcA;
183 proc->procW = funcW;
184 TRACE( "allocated %p for %p/%p (%d/%d used)\n",
185 proc_to_handle(proc), funcA, funcW, winproc_used, MAX_WINPROCS );
187 else FIXME( "too many winprocs, cannot allocate one for %p/%p\n", funcA, funcW );
189 else TRACE( "reusing %p for %p/%p\n", proc_to_handle(proc), funcA, funcW );
191 LeaveCriticalSection( &winproc_cs );
192 return proc;
196 #ifdef __i386__
198 #include "pshpack1.h"
200 /* Window procedure 16-to-32-bit thunk */
201 typedef struct
203 BYTE popl_eax; /* popl %eax (return address) */
204 BYTE pushl_func; /* pushl $proc */
205 WINDOWPROC *proc;
206 BYTE pushl_eax; /* pushl %eax */
207 BYTE ljmp; /* ljmp relay*/
208 DWORD relay_offset; /* __wine_call_wndproc */
209 WORD relay_sel;
210 } WINPROC_THUNK;
212 #include "poppack.h"
214 #define MAX_THUNKS (0x10000 / sizeof(WINPROC_THUNK))
216 static WINPROC_THUNK *thunk_array;
217 static UINT thunk_selector;
218 static UINT thunk_used;
220 /* return the window proc for a given handle, or NULL for an invalid handle */
221 static inline WINDOWPROC *handle16_to_proc( WNDPROC16 handle )
223 if (HIWORD(handle) == thunk_selector)
225 UINT index = LOWORD(handle) / sizeof(WINPROC_THUNK);
226 /* check alignment */
227 if (index * sizeof(WINPROC_THUNK) != LOWORD(handle)) return NULL;
228 /* check array limits */
229 if (index >= thunk_used) return NULL;
230 return thunk_array[index].proc;
232 return handle_to_proc( (WNDPROC)handle );
235 /* allocate a 16-bit thunk for an existing window proc */
236 static WNDPROC16 alloc_win16_thunk( WINDOWPROC *proc )
238 static FARPROC16 relay;
239 UINT i;
241 if (proc->proc16) return proc->proc16;
243 EnterCriticalSection( &winproc_cs );
245 if (!thunk_array) /* allocate the array and its selector */
247 LDT_ENTRY entry;
249 if (!(thunk_selector = wine_ldt_alloc_entries(1))) goto done;
250 if (!(thunk_array = VirtualAlloc( NULL, MAX_THUNKS * sizeof(WINPROC_THUNK), MEM_COMMIT,
251 PAGE_EXECUTE_READWRITE ))) goto done;
252 wine_ldt_set_base( &entry, thunk_array );
253 wine_ldt_set_limit( &entry, MAX_THUNKS * sizeof(WINPROC_THUNK) - 1 );
254 wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_CODE | WINE_LDT_FLAGS_32BIT );
255 wine_ldt_set_entry( thunk_selector, &entry );
256 relay = GetProcAddress16( GetModuleHandle16("user"), "__wine_call_wndproc" );
259 /* check if it already exists */
260 for (i = 0; i < thunk_used; i++) if (thunk_array[i].proc == proc) break;
262 if (i == thunk_used) /* create a new one */
264 WINPROC_THUNK *thunk;
266 if (thunk_used >= MAX_THUNKS) goto done;
267 thunk = &thunk_array[thunk_used++];
268 thunk->popl_eax = 0x58; /* popl %eax */
269 thunk->pushl_func = 0x68; /* pushl $proc */
270 thunk->proc = proc;
271 thunk->pushl_eax = 0x50; /* pushl %eax */
272 thunk->ljmp = 0xea; /* ljmp relay*/
273 thunk->relay_offset = OFFSETOF(relay);
274 thunk->relay_sel = SELECTOROF(relay);
276 proc->proc16 = (WNDPROC16)MAKESEGPTR( thunk_selector, i * sizeof(WINPROC_THUNK) );
277 done:
278 LeaveCriticalSection( &winproc_cs );
279 return proc->proc16;
282 #else /* __i386__ */
284 static inline WINDOWPROC *handle16_to_proc( WNDPROC16 handle )
286 return handle_to_proc( (WNDPROC)handle );
289 static inline WNDPROC16 alloc_win16_thunk( WINDOWPROC *proc )
291 return 0;
294 #endif /* __i386__ */
297 #ifdef __i386__
298 /* Some window procedures modify register they shouldn't, or are not
299 * properly declared stdcall; so we need a small assembly wrapper to
300 * call them. */
301 extern LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
302 WPARAM wParam, LPARAM lParam );
303 __ASM_GLOBAL_FUNC( WINPROC_wrapper,
304 "pushl %ebp\n\t"
305 "movl %esp,%ebp\n\t"
306 "pushl %edi\n\t"
307 "pushl %esi\n\t"
308 "pushl %ebx\n\t"
309 "subl $12,%esp\n\t"
310 "pushl 24(%ebp)\n\t"
311 "pushl 20(%ebp)\n\t"
312 "pushl 16(%ebp)\n\t"
313 "pushl 12(%ebp)\n\t"
314 "movl 8(%ebp),%eax\n\t"
315 "call *%eax\n\t"
316 "leal -12(%ebp),%esp\n\t"
317 "popl %ebx\n\t"
318 "popl %esi\n\t"
319 "popl %edi\n\t"
320 "leave\n\t"
321 "ret" );
322 #else
323 static inline LRESULT WINPROC_wrapper( WNDPROC proc, HWND hwnd, UINT msg,
324 WPARAM wParam, LPARAM lParam )
326 return proc( hwnd, msg, wParam, lParam );
328 #endif /* __i386__ */
331 static void MINMAXINFO32to16( const MINMAXINFO *from, MINMAXINFO16 *to )
333 to->ptReserved.x = from->ptReserved.x;
334 to->ptReserved.y = from->ptReserved.y;
335 to->ptMaxSize.x = from->ptMaxSize.x;
336 to->ptMaxSize.y = from->ptMaxSize.y;
337 to->ptMaxPosition.x = from->ptMaxPosition.x;
338 to->ptMaxPosition.y = from->ptMaxPosition.y;
339 to->ptMinTrackSize.x = from->ptMinTrackSize.x;
340 to->ptMinTrackSize.y = from->ptMinTrackSize.y;
341 to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
342 to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
345 static void MINMAXINFO16to32( const MINMAXINFO16 *from, MINMAXINFO *to )
347 to->ptReserved.x = from->ptReserved.x;
348 to->ptReserved.y = from->ptReserved.y;
349 to->ptMaxSize.x = from->ptMaxSize.x;
350 to->ptMaxSize.y = from->ptMaxSize.y;
351 to->ptMaxPosition.x = from->ptMaxPosition.x;
352 to->ptMaxPosition.y = from->ptMaxPosition.y;
353 to->ptMinTrackSize.x = from->ptMinTrackSize.x;
354 to->ptMinTrackSize.y = from->ptMinTrackSize.y;
355 to->ptMaxTrackSize.x = from->ptMaxTrackSize.x;
356 to->ptMaxTrackSize.y = from->ptMaxTrackSize.y;
359 static void WINDOWPOS32to16( const WINDOWPOS* from, WINDOWPOS16* to )
361 to->hwnd = HWND_16(from->hwnd);
362 to->hwndInsertAfter = HWND_16(from->hwndInsertAfter);
363 to->x = from->x;
364 to->y = from->y;
365 to->cx = from->cx;
366 to->cy = from->cy;
367 to->flags = from->flags;
370 static void WINDOWPOS16to32( const WINDOWPOS16* from, WINDOWPOS* to )
372 to->hwnd = WIN_Handle32(from->hwnd);
373 to->hwndInsertAfter = (from->hwndInsertAfter == (HWND16)-1) ?
374 HWND_TOPMOST : WIN_Handle32(from->hwndInsertAfter);
375 to->x = from->x;
376 to->y = from->y;
377 to->cx = from->cx;
378 to->cy = from->cy;
379 to->flags = from->flags;
382 /* The strings are not copied */
383 static void CREATESTRUCT32Ato16( const CREATESTRUCTA* from, CREATESTRUCT16* to )
385 to->lpCreateParams = (SEGPTR)from->lpCreateParams;
386 to->hInstance = HINSTANCE_16(from->hInstance);
387 to->hMenu = HMENU_16(from->hMenu);
388 to->hwndParent = HWND_16(from->hwndParent);
389 to->cy = from->cy;
390 to->cx = from->cx;
391 to->y = from->y;
392 to->x = from->x;
393 to->style = from->style;
394 to->dwExStyle = from->dwExStyle;
397 static void CREATESTRUCT16to32A( const CREATESTRUCT16* from, CREATESTRUCTA *to )
400 to->lpCreateParams = (LPVOID)from->lpCreateParams;
401 to->hInstance = HINSTANCE_32(from->hInstance);
402 to->hMenu = HMENU_32(from->hMenu);
403 to->hwndParent = WIN_Handle32(from->hwndParent);
404 to->cy = from->cy;
405 to->cx = from->cx;
406 to->y = from->y;
407 to->x = from->x;
408 to->style = from->style;
409 to->dwExStyle = from->dwExStyle;
412 /* The strings are not copied */
413 static void MDICREATESTRUCT32Ato16( const MDICREATESTRUCTA* from, MDICREATESTRUCT16* to )
415 to->hOwner = HINSTANCE_16(from->hOwner);
416 to->x = from->x;
417 to->y = from->y;
418 to->cx = from->cx;
419 to->cy = from->cy;
420 to->style = from->style;
421 to->lParam = from->lParam;
424 static void MDICREATESTRUCT16to32A( const MDICREATESTRUCT16* from, MDICREATESTRUCTA *to )
426 to->hOwner = HINSTANCE_32(from->hOwner);
427 to->x = from->x;
428 to->y = from->y;
429 to->cx = from->cx;
430 to->cy = from->cy;
431 to->style = from->style;
432 to->lParam = from->lParam;
435 static WPARAM map_wparam_char_AtoW( WPARAM wParam, DWORD len )
437 CHAR ch[2];
438 WCHAR wch;
440 ch[0] = (wParam >> 8);
441 ch[1] = wParam & 0xff;
442 if (len > 1 && ch[0])
443 RtlMultiByteToUnicodeN( &wch, sizeof(wch), NULL, ch, 2 );
444 else
445 RtlMultiByteToUnicodeN( &wch, sizeof(wch), NULL, ch + 1, 1 );
446 return MAKEWPARAM( wch, HIWORD(wParam) );
449 static WPARAM map_wparam_char_WtoA( WPARAM wParam, DWORD len )
451 WCHAR wch = wParam;
452 BYTE ch[2];
454 RtlUnicodeToMultiByteN( (LPSTR)ch, len, &len, &wch, sizeof(wch) );
455 if (len == 2)
456 return MAKEWPARAM( (ch[0] << 8) | ch[1], HIWORD(wParam) );
457 else
458 return MAKEWPARAM( ch[0], HIWORD(wParam) );
461 /* call a 32-bit window procedure */
462 static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result, void *arg )
464 WNDPROC proc = arg;
466 USER_CheckNotLock();
468 hwnd = WIN_GetFullHandle( hwnd );
469 if (TRACE_ON(relay))
470 DPRINTF( "%04lx:Call window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
471 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp );
473 *result = WINPROC_wrapper( proc, hwnd, msg, wp, lp );
475 if (TRACE_ON(relay))
476 DPRINTF( "%04lx:Ret window proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx\n",
477 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp, *result );
478 return *result;
481 /* call a 32-bit dialog procedure */
482 static LRESULT call_dialog_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result, void *arg )
484 WNDPROC proc = arg;
485 LRESULT ret;
487 USER_CheckNotLock();
489 hwnd = WIN_GetFullHandle( hwnd );
490 if (TRACE_ON(relay))
491 DPRINTF( "%04lx:Call dialog proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
492 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp );
494 ret = WINPROC_wrapper( proc, hwnd, msg, wp, lp );
495 *result = GetWindowLongPtrW( hwnd, DWLP_MSGRESULT );
497 if (TRACE_ON(relay))
498 DPRINTF( "%04lx:Ret dialog proc %p (hwnd=%p,msg=%s,wp=%08x,lp=%08lx) retval=%08lx result=%08lx\n",
499 GetCurrentThreadId(), proc, hwnd, SPY_GetMsgName(msg, hwnd), wp, lp, ret, *result );
500 return ret;
503 /* call a 16-bit window procedure */
504 static LRESULT call_window_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
505 LRESULT *result, void *arg )
507 WNDPROC16 proc = arg;
508 CONTEXT86 context;
509 size_t size = 0;
510 struct
512 WORD params[5];
513 union
515 CREATESTRUCT16 cs16;
516 DRAWITEMSTRUCT16 dis16;
517 COMPAREITEMSTRUCT16 cis16;
518 } u;
519 } args;
521 USER_CheckNotLock();
523 /* Window procedures want ax = hInstance, ds = es = ss */
525 memset(&context, 0, sizeof(context));
526 context.SegDs = context.SegEs = SELECTOROF(NtCurrentTeb()->WOW32Reserved);
527 context.SegFs = wine_get_fs();
528 context.SegGs = wine_get_gs();
529 if (!(context.Eax = GetWindowWord( HWND_32(hwnd), GWLP_HINSTANCE ))) context.Eax = context.SegDs;
530 context.SegCs = SELECTOROF(proc);
531 context.Eip = OFFSETOF(proc);
532 context.Ebp = OFFSETOF(NtCurrentTeb()->WOW32Reserved) + (WORD)&((STACK16FRAME*)0)->bp;
534 if (lParam)
536 /* Some programs (eg. the "Undocumented Windows" examples, JWP) only
537 work if structures passed in lParam are placed in the stack/data
538 segment. Programmers easily make the mistake of converting lParam
539 to a near rather than a far pointer, since Windows apparently
540 allows this. We copy the structures to the 16 bit stack; this is
541 ugly but makes these programs work. */
542 switch (msg)
544 case WM_CREATE:
545 case WM_NCCREATE:
546 size = sizeof(CREATESTRUCT16); break;
547 case WM_DRAWITEM:
548 size = sizeof(DRAWITEMSTRUCT16); break;
549 case WM_COMPAREITEM:
550 size = sizeof(COMPAREITEMSTRUCT16); break;
552 if (size)
554 memcpy( &args.u, MapSL(lParam), size );
555 lParam = (SEGPTR)NtCurrentTeb()->WOW32Reserved - size;
559 args.params[4] = hwnd;
560 args.params[3] = msg;
561 args.params[2] = wParam;
562 args.params[1] = HIWORD(lParam);
563 args.params[0] = LOWORD(lParam);
564 WOWCallback16Ex( 0, WCB16_REGS, sizeof(args.params) + size, &args, (DWORD *)&context );
565 *result = MAKELONG( LOWORD(context.Eax), LOWORD(context.Edx) );
566 return *result;
569 /* call a 16-bit dialog procedure */
570 static LRESULT call_dialog_proc16( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp,
571 LRESULT *result, void *arg )
573 LRESULT ret = call_window_proc16( hwnd, msg, wp, lp, result, arg );
574 *result = GetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT );
575 return LOWORD(ret);
579 /**********************************************************************
580 * WINPROC_GetProc16
582 * Get a window procedure pointer that can be passed to the Windows program.
584 WNDPROC16 WINPROC_GetProc16( WNDPROC proc, BOOL unicode )
586 WINDOWPROC *ptr;
588 if (unicode) ptr = alloc_winproc( NULL, proc );
589 else ptr = alloc_winproc( proc, NULL );
591 if (!ptr) return 0;
592 return alloc_win16_thunk( ptr );
596 /**********************************************************************
597 * WINPROC_GetProc
599 * Get a window procedure pointer that can be passed to the Windows program.
601 WNDPROC WINPROC_GetProc( WNDPROC proc, BOOL unicode )
603 WINDOWPROC *ptr = handle_to_proc( proc );
605 if (!ptr) return proc;
606 if (unicode)
608 if (ptr->procW) return ptr->procW;
609 return proc;
611 else
613 if (ptr->procA) return ptr->procA;
614 return proc;
619 /**********************************************************************
620 * WINPROC_AllocProc16
622 * Allocate a window procedure for a window or class.
624 * Note that allocated winprocs are never freed; the idea is that even if an app creates a
625 * lot of windows, it will usually only have a limited number of window procedures, so the
626 * array won't grow too large, and this way we avoid the need to track allocations per window.
628 WNDPROC WINPROC_AllocProc16( WNDPROC16 func )
630 WINDOWPROC *proc;
632 if (!func) return NULL;
634 /* check if the function is already a win proc */
635 if (!(proc = handle16_to_proc( func )))
637 EnterCriticalSection( &winproc_cs );
639 /* then check if we already have a winproc for that function */
640 if (!(proc = find_winproc16( func )))
642 if (winproc_used < MAX_WINPROCS)
644 proc = &winproc_array[winproc_used++];
645 proc->proc16 = func;
646 TRACE( "allocated %p for %p/16-bit (%d/%d used)\n",
647 proc_to_handle(proc), func, winproc_used, MAX_WINPROCS );
649 else FIXME( "too many winprocs, cannot allocate one for 16-bit %p\n", func );
651 else TRACE( "reusing %p for %p/16-bit\n", proc_to_handle(proc), func );
653 LeaveCriticalSection( &winproc_cs );
655 return proc_to_handle( proc );
659 /**********************************************************************
660 * WINPROC_AllocProc
662 * Allocate a window procedure for a window or class.
664 * Note that allocated winprocs are never freed; the idea is that even if an app creates a
665 * lot of windows, it will usually only have a limited number of window procedures, so the
666 * array won't grow too large, and this way we avoid the need to track allocations per window.
668 WNDPROC WINPROC_AllocProc( WNDPROC funcA, WNDPROC funcW )
670 WINDOWPROC *proc;
672 if (!(proc = alloc_winproc( funcA, funcW ))) return NULL;
673 return proc_to_handle( proc );
677 /**********************************************************************
678 * WINPROC_IsUnicode
680 * Return the window procedure type, or the default value if not a winproc handle.
682 BOOL WINPROC_IsUnicode( WNDPROC proc, BOOL def_val )
684 WINDOWPROC *ptr = handle_to_proc( proc );
686 if (!ptr) return def_val;
687 if (ptr->procA && ptr->procW) return def_val; /* can be both */
688 return (ptr->procW != NULL);
692 /**********************************************************************
693 * WINPROC_TestLBForStr
695 * Return TRUE if the lparam is a string
697 inline static BOOL WINPROC_TestLBForStr( HWND hwnd, UINT msg )
699 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
700 if (msg <= CB_MSGMAX)
701 return (!(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) || (style & CBS_HASSTRINGS));
702 else
703 return (!(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || (style & LBS_HASSTRINGS));
708 static UINT convert_handle_16_to_32(HANDLE16 src, unsigned int flags)
710 HANDLE dst;
711 UINT sz = GlobalSize16(src);
712 LPSTR ptr16, ptr32;
714 if (!(dst = GlobalAlloc(flags, sz)))
715 return 0;
716 ptr16 = GlobalLock16(src);
717 ptr32 = GlobalLock(dst);
718 if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr32, ptr16, sz);
719 GlobalUnlock16(src);
720 GlobalUnlock(dst);
722 return (UINT)dst;
725 /**********************************************************************
726 * WINPROC_MapMsg16To32A
728 * Map a message from 16- to 32-bit Ansi.
729 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
731 static INT WINPROC_MapMsg16To32A( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
732 WPARAM *pwparam32, LPARAM *plparam )
734 *pmsg32 = (UINT)msg16;
735 *pwparam32 = (WPARAM)wParam16;
736 switch(msg16)
738 case WM_ACTIVATE:
739 case WM_CHARTOITEM:
740 case WM_COMMAND:
741 case WM_VKEYTOITEM:
742 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
743 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
744 return 0;
745 case WM_HSCROLL:
746 case WM_VSCROLL:
747 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
748 *plparam = (LPARAM)WIN_Handle32( HIWORD(*plparam) );
749 return 0;
750 case WM_CTLCOLOR:
751 if ( HIWORD(*plparam) > CTLCOLOR_STATIC ) return -1;
752 *pmsg32 = WM_CTLCOLORMSGBOX + HIWORD(*plparam);
753 *pwparam32 = (WPARAM)HDC_32(wParam16);
754 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
755 return 0;
756 case WM_COMPAREITEM:
758 COMPAREITEMSTRUCT16* cis16 = MapSL(*plparam);
759 COMPAREITEMSTRUCT *cis = HeapAlloc(GetProcessHeap(), 0, sizeof(*cis));
760 if (!cis) return -1;
761 cis->CtlType = cis16->CtlType;
762 cis->CtlID = cis16->CtlID;
763 cis->hwndItem = WIN_Handle32( cis16->hwndItem );
764 cis->itemID1 = cis16->itemID1;
765 cis->itemData1 = cis16->itemData1;
766 cis->itemID2 = cis16->itemID2;
767 cis->itemData2 = cis16->itemData2;
768 cis->dwLocaleId = 0; /* FIXME */
769 *plparam = (LPARAM)cis;
771 return 1;
772 case WM_COPYDATA:
774 PCOPYDATASTRUCT16 pcds16 = MapSL(*plparam);
775 PCOPYDATASTRUCT pcds = HeapAlloc ( GetProcessHeap(), 0, sizeof(*pcds));
776 pcds->dwData = pcds16->dwData;
777 pcds->cbData = pcds16->cbData;
778 pcds->lpData = MapSL( pcds16->lpData);
779 *plparam = (LPARAM)pcds;
781 return 1;
782 case WM_DELETEITEM:
784 DELETEITEMSTRUCT16* dis16 = MapSL(*plparam);
785 DELETEITEMSTRUCT *dis = HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
786 if (!dis) return -1;
787 dis->CtlType = dis16->CtlType;
788 dis->CtlID = dis16->CtlID;
789 dis->hwndItem = WIN_Handle32( dis16->hwndItem );
790 dis->itemData = dis16->itemData;
791 *plparam = (LPARAM)dis;
793 return 1;
794 case WM_MEASUREITEM:
796 MEASUREITEMSTRUCT16* mis16 = MapSL(*plparam);
797 MEASUREITEMSTRUCT *mis = HeapAlloc(GetProcessHeap(), 0,
798 sizeof(*mis) + sizeof(LPARAM));
799 if (!mis) return -1;
800 mis->CtlType = mis16->CtlType;
801 mis->CtlID = mis16->CtlID;
802 mis->itemID = mis16->itemID;
803 mis->itemWidth = mis16->itemWidth;
804 mis->itemHeight = mis16->itemHeight;
805 mis->itemData = mis16->itemData;
806 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
807 *plparam = (LPARAM)mis;
809 return 1;
810 case WM_DRAWITEM:
812 DRAWITEMSTRUCT16* dis16 = MapSL(*plparam);
813 DRAWITEMSTRUCT *dis = HeapAlloc(GetProcessHeap(), 0, sizeof(*dis));
814 if (!dis) return -1;
815 dis->CtlType = dis16->CtlType;
816 dis->CtlID = dis16->CtlID;
817 dis->itemID = dis16->itemID;
818 dis->itemAction = dis16->itemAction;
819 dis->itemState = dis16->itemState;
820 dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND)HMENU_32(dis16->hwndItem)
821 : WIN_Handle32( dis16->hwndItem );
822 dis->hDC = HDC_32(dis16->hDC);
823 dis->itemData = dis16->itemData;
824 dis->rcItem.left = dis16->rcItem.left;
825 dis->rcItem.top = dis16->rcItem.top;
826 dis->rcItem.right = dis16->rcItem.right;
827 dis->rcItem.bottom = dis16->rcItem.bottom;
828 *plparam = (LPARAM)dis;
830 return 1;
831 case WM_GETMINMAXINFO:
833 MINMAXINFO *mmi = HeapAlloc( GetProcessHeap(), 0, sizeof(*mmi) + sizeof(LPARAM));
834 if (!mmi) return -1;
835 MINMAXINFO16to32( MapSL(*plparam), mmi );
836 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
837 *plparam = (LPARAM)mmi;
839 return 1;
840 case WM_GETTEXT:
841 case WM_SETTEXT:
842 case WM_WININICHANGE:
843 case WM_DEVMODECHANGE:
844 case WM_ASKCBFORMATNAME:
845 *plparam = (LPARAM)MapSL(*plparam);
846 return 0;
847 case WM_MDICREATE:
849 MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
850 MDICREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
851 if (!cs) return -1;
852 MDICREATESTRUCT16to32A( cs16, cs );
853 cs->szTitle = MapSL(cs16->szTitle);
854 cs->szClass = MapSL(cs16->szClass);
855 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
856 *plparam = (LPARAM)cs;
858 return 1;
859 case WM_MDIGETACTIVE:
860 *plparam = (LPARAM)HeapAlloc( GetProcessHeap(), 0, sizeof(BOOL) );
861 *(BOOL*)(*plparam) = 0;
862 return 1;
863 case WM_MDISETMENU:
864 if(wParam16) *pmsg32=WM_MDIREFRESHMENU;
865 *pwparam32 = (WPARAM)HMENU_32(LOWORD(*plparam));
866 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
867 return 0;
868 case WM_MENUCHAR:
869 *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
870 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
871 return 0;
872 case WM_MENUSELECT:
873 if((LOWORD(*plparam) & MF_POPUP) && (LOWORD(*plparam) != 0xFFFF))
875 HMENU hmenu=HMENU_32(HIWORD(*plparam));
876 UINT Pos=MENU_FindSubMenu( &hmenu, HMENU_32(wParam16));
877 if(Pos==0xFFFF) Pos=0; /* NO_SELECTED_ITEM */
878 *pwparam32 = MAKEWPARAM( Pos, LOWORD(*plparam) );
880 else *pwparam32 = MAKEWPARAM( wParam16, LOWORD(*plparam) );
881 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
882 return 0;
883 case WM_MDIACTIVATE:
884 if( *plparam )
886 *pwparam32 = (WPARAM)WIN_Handle32( HIWORD(*plparam) );
887 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
889 else /* message sent to MDI client */
890 *pwparam32 = wParam16;
891 return 0;
892 case WM_NCCALCSIZE:
894 NCCALCSIZE_PARAMS16 *nc16;
895 NCCALCSIZE_PARAMS *nc;
897 nc = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc) + sizeof(LPARAM) );
898 if (!nc) return -1;
899 nc16 = MapSL(*plparam);
900 nc->rgrc[0].left = nc16->rgrc[0].left;
901 nc->rgrc[0].top = nc16->rgrc[0].top;
902 nc->rgrc[0].right = nc16->rgrc[0].right;
903 nc->rgrc[0].bottom = nc16->rgrc[0].bottom;
904 if (wParam16)
906 nc->lppos = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc->lppos) );
907 nc->rgrc[1].left = nc16->rgrc[1].left;
908 nc->rgrc[1].top = nc16->rgrc[1].top;
909 nc->rgrc[1].right = nc16->rgrc[1].right;
910 nc->rgrc[1].bottom = nc16->rgrc[1].bottom;
911 nc->rgrc[2].left = nc16->rgrc[2].left;
912 nc->rgrc[2].top = nc16->rgrc[2].top;
913 nc->rgrc[2].right = nc16->rgrc[2].right;
914 nc->rgrc[2].bottom = nc16->rgrc[2].bottom;
915 if (nc->lppos) WINDOWPOS16to32( MapSL(nc16->lppos), nc->lppos );
917 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
918 *plparam = (LPARAM)nc;
920 return 1;
921 case WM_NCCREATE:
922 case WM_CREATE:
924 CREATESTRUCT16 *cs16 = MapSL(*plparam);
925 CREATESTRUCTA *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
926 if (!cs) return -1;
927 CREATESTRUCT16to32A( cs16, cs );
928 cs->lpszName = MapSL(cs16->lpszName);
929 cs->lpszClass = MapSL(cs16->lpszClass);
931 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
933 MDICREATESTRUCT16 *mdi_cs16;
934 MDICREATESTRUCTA *mdi_cs = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs));
935 if (!mdi_cs)
937 HeapFree(GetProcessHeap(), 0, cs);
938 return -1;
940 mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs16->lpCreateParams);
941 MDICREATESTRUCT16to32A(mdi_cs16, mdi_cs);
942 mdi_cs->szTitle = MapSL(mdi_cs16->szTitle);
943 mdi_cs->szClass = MapSL(mdi_cs16->szClass);
945 cs->lpCreateParams = mdi_cs;
947 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
948 *plparam = (LPARAM)cs;
950 return 1;
951 case WM_PARENTNOTIFY:
952 if ((wParam16 == WM_CREATE) || (wParam16 == WM_DESTROY))
954 *pwparam32 = MAKEWPARAM( wParam16, HIWORD(*plparam) );
955 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
957 return 0;
958 case WM_WINDOWPOSCHANGING:
959 case WM_WINDOWPOSCHANGED:
961 WINDOWPOS *wp = HeapAlloc( GetProcessHeap(), 0, sizeof(*wp) + sizeof(LPARAM) );
962 if (!wp) return -1;
963 WINDOWPOS16to32( MapSL(*plparam), wp );
964 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
965 *plparam = (LPARAM)wp;
967 return 1;
968 case WM_GETDLGCODE:
969 if (*plparam)
971 LPMSG16 msg16 = MapSL(*plparam);
972 LPMSG msg32 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
974 if (!msg32) return -1;
975 msg32->hwnd = WIN_Handle32( msg16->hwnd );
976 msg32->message = msg16->message;
977 msg32->wParam = msg16->wParam;
978 msg32->lParam = msg16->lParam;
979 msg32->time = msg16->time;
980 msg32->pt.x = msg16->pt.x;
981 msg32->pt.y = msg16->pt.y;
982 *plparam = (LPARAM)msg32;
983 return 1;
985 else return 0;
986 case WM_NOTIFY:
987 *plparam = (LPARAM)MapSL(*plparam);
988 return 0;
989 case WM_ACTIVATEAPP:
990 /* We need this when SetActiveWindow sends a Sendmessage16() to
991 * a 32bit window. Might be superflous with 32bit interprocess
992 * message queues. */
993 if (*plparam) *plparam = HTASK_32( *plparam );
994 return 0;
995 case WM_NEXTMENU:
997 MDINEXTMENU *next = HeapAlloc( GetProcessHeap(), 0, sizeof(*next) );
998 if (!next) return -1;
999 next->hmenuIn = (HMENU)*plparam;
1000 next->hmenuNext = 0;
1001 next->hwndNext = 0;
1002 *plparam = (LPARAM)next;
1003 return 1;
1005 case WM_PAINTCLIPBOARD:
1006 case WM_SIZECLIPBOARD:
1007 FIXME_(msg)("message %04x needs translation\n",msg16 );
1008 return -1;
1009 case WM_DDE_INITIATE:
1010 case WM_DDE_TERMINATE:
1011 case WM_DDE_UNADVISE:
1012 case WM_DDE_REQUEST:
1013 *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1014 return 0;
1015 case WM_DDE_ADVISE:
1016 case WM_DDE_DATA:
1017 case WM_DDE_POKE:
1019 HANDLE16 lo16;
1020 ATOM hi;
1021 UINT lo32 = 0;
1023 *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1024 lo16 = LOWORD(*plparam);
1025 hi = HIWORD(*plparam);
1026 if (lo16 && !(lo32 = convert_handle_16_to_32(lo16, GMEM_DDESHARE)))
1027 return -1;
1028 *plparam = PackDDElParam(msg16, lo32, hi);
1030 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1031 case WM_DDE_ACK:
1033 UINT lo, hi;
1034 int flag = 0;
1035 char buf[2];
1037 *pwparam32 = (WPARAM)WIN_Handle32(wParam16);
1039 lo = LOWORD(*plparam);
1040 hi = HIWORD(*plparam);
1042 if (GlobalGetAtomNameA(hi, buf, 2) > 0) flag |= 1;
1043 if (GlobalSize16(hi) != 0) flag |= 2;
1044 switch (flag)
1046 case 0:
1047 if (hi)
1049 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1050 hi = 0;
1052 break;
1053 case 1:
1054 break; /* atom, nothing to do */
1055 case 3:
1056 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
1057 /* fall thru */
1058 case 2:
1059 hi = convert_handle_16_to_32(hi, GMEM_DDESHARE);
1060 break;
1062 *plparam = PackDDElParam(WM_DDE_ACK, lo, hi);
1064 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1065 case WM_DDE_EXECUTE:
1066 *plparam = convert_handle_16_to_32(*plparam, GMEM_DDESHARE);
1067 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1068 default: /* No translation needed */
1069 return 0;
1074 /**********************************************************************
1075 * WINPROC_UnmapMsg16To32A
1077 * Unmap a message that was mapped from 16- to 32-bit Ansi.
1079 static LRESULT WINPROC_UnmapMsg16To32A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1080 LRESULT result )
1082 switch(msg)
1084 case WM_COMPAREITEM:
1085 case WM_DELETEITEM:
1086 case WM_DRAWITEM:
1087 case WM_COPYDATA:
1088 HeapFree( GetProcessHeap(), 0, (LPVOID)lParam );
1089 break;
1090 case WM_MEASUREITEM:
1092 MEASUREITEMSTRUCT16 *mis16;
1093 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam;
1094 lParam = *(LPARAM *)(mis + 1);
1095 mis16 = MapSL(lParam);
1096 mis16->itemWidth = (UINT16)mis->itemWidth;
1097 mis16->itemHeight = (UINT16)mis->itemHeight;
1098 HeapFree( GetProcessHeap(), 0, mis );
1100 break;
1101 case WM_GETMINMAXINFO:
1103 MINMAXINFO *mmi = (MINMAXINFO *)lParam;
1104 lParam = *(LPARAM *)(mmi + 1);
1105 MINMAXINFO32to16( mmi, MapSL(lParam));
1106 HeapFree( GetProcessHeap(), 0, mmi );
1108 break;
1109 case WM_MDICREATE:
1111 MDICREATESTRUCTA *cs = (MDICREATESTRUCTA *)lParam;
1112 lParam = *(LPARAM *)(cs + 1);
1113 MDICREATESTRUCT32Ato16( cs, MapSL(lParam) );
1114 HeapFree( GetProcessHeap(), 0, cs );
1116 break;
1117 case WM_MDIGETACTIVE:
1118 result = MAKELONG( LOWORD(result), (BOOL16)(*(BOOL *)lParam) );
1119 HeapFree( GetProcessHeap(), 0, (BOOL *)lParam );
1120 break;
1121 case WM_NCCALCSIZE:
1123 NCCALCSIZE_PARAMS16 *nc16;
1124 NCCALCSIZE_PARAMS *nc = (NCCALCSIZE_PARAMS *)lParam;
1125 lParam = *(LPARAM *)(nc + 1);
1126 nc16 = MapSL(lParam);
1127 nc16->rgrc[0].left = nc->rgrc[0].left;
1128 nc16->rgrc[0].top = nc->rgrc[0].top;
1129 nc16->rgrc[0].right = nc->rgrc[0].right;
1130 nc16->rgrc[0].bottom = nc->rgrc[0].bottom;
1131 if (wParam)
1133 nc16->rgrc[1].left = nc->rgrc[1].left;
1134 nc16->rgrc[1].top = nc->rgrc[1].top;
1135 nc16->rgrc[1].right = nc->rgrc[1].right;
1136 nc16->rgrc[1].bottom = nc->rgrc[1].bottom;
1137 nc16->rgrc[2].left = nc->rgrc[2].left;
1138 nc16->rgrc[2].top = nc->rgrc[2].top;
1139 nc16->rgrc[2].right = nc->rgrc[2].right;
1140 nc16->rgrc[2].bottom = nc->rgrc[2].bottom;
1141 if (nc->lppos)
1143 WINDOWPOS32to16( nc->lppos, MapSL(nc16->lppos));
1144 HeapFree( GetProcessHeap(), 0, nc->lppos );
1147 HeapFree( GetProcessHeap(), 0, nc );
1149 break;
1150 case WM_NCCREATE:
1151 case WM_CREATE:
1153 CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
1154 lParam = *(LPARAM *)(cs + 1);
1155 CREATESTRUCT32Ato16( cs, MapSL(lParam) );
1157 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1158 HeapFree(GetProcessHeap(), 0, cs->lpCreateParams);
1160 HeapFree( GetProcessHeap(), 0, cs );
1162 break;
1163 case WM_WINDOWPOSCHANGING:
1164 case WM_WINDOWPOSCHANGED:
1166 WINDOWPOS *wp = (WINDOWPOS *)lParam;
1167 lParam = *(LPARAM *)(wp + 1);
1168 WINDOWPOS32to16(wp, MapSL(lParam));
1169 HeapFree( GetProcessHeap(), 0, wp );
1171 break;
1172 case WM_GETDLGCODE:
1173 if (lParam)
1175 LPMSG msg32 = (LPMSG)lParam;
1176 HeapFree( GetProcessHeap(), 0, msg32 );
1178 break;
1179 case WM_NEXTMENU:
1181 MDINEXTMENU *next = (MDINEXTMENU *)lParam;
1182 result = MAKELONG( HMENU_16(next->hmenuNext), HWND_16(next->hwndNext) );
1183 HeapFree( GetProcessHeap(), 0, next );
1185 break;
1187 return result;
1191 /**********************************************************************
1192 * WINPROC_MapMsg16To32W
1194 * Map a message from 16- to 32-bit Unicode.
1195 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1197 static INT WINPROC_MapMsg16To32W( HWND hwnd, UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
1198 WPARAM *pwparam32, LPARAM *plparam )
1200 *pmsg32=(UINT)msg16;
1201 *pwparam32 = (WPARAM)wParam16;
1202 switch(msg16)
1204 case WM_NCCREATE:
1205 case WM_CREATE:
1207 CREATESTRUCT16 *cs16 = MapSL(*plparam);
1208 CREATESTRUCTW *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1209 if (!cs) return -1;
1210 CREATESTRUCT16to32A( cs16, (CREATESTRUCTA *)cs );
1211 cs->lpszName = map_str_16_to_32W(cs16->lpszName);
1212 cs->lpszClass = map_str_16_to_32W(cs16->lpszClass);
1214 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1216 MDICREATESTRUCT16 *mdi_cs16;
1217 MDICREATESTRUCTW *mdi_cs = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs));
1218 if (!mdi_cs)
1220 HeapFree(GetProcessHeap(), 0, cs);
1221 return -1;
1223 mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs16->lpCreateParams);
1224 MDICREATESTRUCT16to32A(mdi_cs16, (MDICREATESTRUCTA *)mdi_cs);
1225 mdi_cs->szTitle = map_str_16_to_32W(mdi_cs16->szTitle);
1226 mdi_cs->szClass = map_str_16_to_32W(mdi_cs16->szClass);
1228 cs->lpCreateParams = mdi_cs;
1230 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1231 *plparam = (LPARAM)cs;
1233 return 1;
1234 case WM_MDICREATE:
1236 MDICREATESTRUCT16 *cs16 = MapSL(*plparam);
1237 MDICREATESTRUCTW *cs = HeapAlloc( GetProcessHeap(), 0, sizeof(*cs) + sizeof(LPARAM) );
1238 if (!cs) return -1;
1239 MDICREATESTRUCT16to32A( cs16, (MDICREATESTRUCTA *)cs );
1240 cs->szTitle = map_str_16_to_32W(cs16->szTitle);
1241 cs->szClass = map_str_16_to_32W(cs16->szClass);
1242 *(LPARAM *)(cs + 1) = *plparam; /* Store the previous lParam */
1243 *plparam = (LPARAM)cs;
1245 return 1;
1246 case WM_GETDLGCODE:
1247 if (*plparam)
1249 LPMSG16 msg16 = MapSL(*plparam);
1250 LPMSG msg32 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) );
1252 if (!msg32) return -1;
1253 msg32->hwnd = WIN_Handle32( msg16->hwnd );
1254 msg32->message = msg16->message;
1255 msg32->wParam = msg16->wParam;
1256 msg32->lParam = msg16->lParam;
1257 msg32->time = msg16->time;
1258 msg32->pt.x = msg16->pt.x;
1259 msg32->pt.y = msg16->pt.y;
1260 switch(msg32->message)
1262 case WM_CHAR:
1263 case WM_DEADCHAR:
1264 case WM_SYSCHAR:
1265 case WM_SYSDEADCHAR:
1266 msg32->wParam = map_wparam_char_AtoW( msg16->wParam, 1 );
1267 break;
1269 *plparam = (LPARAM)msg32;
1270 return 1;
1272 else return 0;
1274 case WM_CHARTOITEM:
1275 *pwparam32 = MAKEWPARAM( map_wparam_char_AtoW( wParam16, 1 ), HIWORD(*plparam) );
1276 *plparam = (LPARAM)WIN_Handle32( LOWORD(*plparam) );
1277 return 0;
1278 case WM_MENUCHAR:
1279 *pwparam32 = MAKEWPARAM( map_wparam_char_AtoW( wParam16, 1 ), LOWORD(*plparam) );
1280 *plparam = (LPARAM)HMENU_32(HIWORD(*plparam));
1281 return 0;
1282 case WM_CHAR:
1283 case WM_DEADCHAR:
1284 case WM_SYSCHAR:
1285 case WM_SYSDEADCHAR:
1286 *pwparam32 = map_wparam_char_AtoW( wParam16, 1 );
1287 return 0;
1288 case WM_IME_CHAR:
1289 *pwparam32 = map_wparam_char_AtoW( wParam16, 2 );
1290 return 0;
1292 default: /* No Unicode translation needed */
1293 return WINPROC_MapMsg16To32A( hwnd, msg16, wParam16, pmsg32,
1294 pwparam32, plparam );
1299 /**********************************************************************
1300 * WINPROC_UnmapMsg16To32W
1302 * Unmap a message that was mapped from 16- to 32-bit Unicode.
1304 static LRESULT WINPROC_UnmapMsg16To32W( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1305 LRESULT result )
1307 switch(msg)
1309 case WM_NCCREATE:
1310 case WM_CREATE:
1312 CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
1313 lParam = *(LPARAM *)(cs + 1);
1314 CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs, MapSL(lParam) );
1315 unmap_str_16_to_32W( cs->lpszName );
1316 unmap_str_16_to_32W( cs->lpszClass );
1318 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1320 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)cs->lpCreateParams;
1321 unmap_str_16_to_32W( mdi_cs->szTitle );
1322 unmap_str_16_to_32W( mdi_cs->szClass );
1323 HeapFree(GetProcessHeap(), 0, cs->lpCreateParams);
1325 HeapFree( GetProcessHeap(), 0, cs );
1327 break;
1328 case WM_MDICREATE:
1330 MDICREATESTRUCTW *cs = (MDICREATESTRUCTW *)lParam;
1331 lParam = *(LPARAM *)(cs + 1);
1332 MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs, MapSL(lParam) );
1333 unmap_str_16_to_32W( cs->szTitle );
1334 unmap_str_16_to_32W( cs->szClass );
1335 HeapFree( GetProcessHeap(), 0, cs );
1337 break;
1338 case WM_GETDLGCODE:
1339 if (lParam)
1341 LPMSG msg32 = (LPMSG)lParam;
1342 HeapFree( GetProcessHeap(), 0, msg32 );
1344 break;
1345 default:
1346 return WINPROC_UnmapMsg16To32A( hwnd, msg, wParam, lParam, result );
1348 return result;
1351 static HANDLE16 convert_handle_32_to_16(UINT src, unsigned int flags)
1353 HANDLE16 dst;
1354 UINT sz = GlobalSize((HANDLE)src);
1355 LPSTR ptr16, ptr32;
1357 if (!(dst = GlobalAlloc16(flags, sz)))
1358 return 0;
1359 ptr32 = GlobalLock((HANDLE)src);
1360 ptr16 = GlobalLock16(dst);
1361 if (ptr16 != NULL && ptr32 != NULL) memcpy(ptr16, ptr32, sz);
1362 GlobalUnlock((HANDLE)src);
1363 GlobalUnlock16(dst);
1365 return dst;
1369 /**********************************************************************
1370 * WINPROC_MapMsg32ATo16
1372 * Map a message from 32-bit Ansi to 16-bit.
1373 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
1375 static INT WINPROC_MapMsg32ATo16( HWND hwnd, UINT msg32, WPARAM wParam32,
1376 UINT16 *pmsg16, WPARAM16 *pwparam16, LPARAM *plparam )
1378 *pmsg16 = (UINT16)msg32;
1379 *pwparam16 = (WPARAM16)LOWORD(wParam32);
1380 switch(msg32)
1382 case SBM_SETRANGE:
1383 *pmsg16 = SBM_SETRANGE16;
1384 *plparam = MAKELPARAM(wParam32, *plparam);
1385 *pwparam16 = 0;
1386 return 0;
1388 case SBM_GETRANGE:
1389 *pmsg16 = SBM_GETRANGE16;
1390 return 1;
1392 case BM_GETCHECK:
1393 case BM_SETCHECK:
1394 case BM_GETSTATE:
1395 case BM_SETSTATE:
1396 case BM_SETSTYLE:
1397 *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK);
1398 return 0;
1400 case EM_GETSEL:
1401 case EM_GETRECT:
1402 case EM_SETRECT:
1403 case EM_SETRECTNP:
1404 case EM_SCROLL:
1405 case EM_LINESCROLL:
1406 case EM_SCROLLCARET:
1407 case EM_GETMODIFY:
1408 case EM_SETMODIFY:
1409 case EM_GETLINECOUNT:
1410 case EM_LINEINDEX:
1411 case EM_SETHANDLE:
1412 case EM_GETHANDLE:
1413 case EM_GETTHUMB:
1414 case EM_LINELENGTH:
1415 case EM_REPLACESEL:
1416 case EM_GETLINE:
1417 case EM_LIMITTEXT:
1418 case EM_CANUNDO:
1419 case EM_UNDO:
1420 case EM_FMTLINES:
1421 case EM_LINEFROMCHAR:
1422 case EM_SETTABSTOPS:
1423 case EM_SETPASSWORDCHAR:
1424 case EM_EMPTYUNDOBUFFER:
1425 case EM_GETFIRSTVISIBLELINE:
1426 case EM_SETREADONLY:
1427 case EM_SETWORDBREAKPROC:
1428 case EM_GETWORDBREAKPROC:
1429 case EM_GETPASSWORDCHAR:
1430 *pmsg16 = (UINT16)msg32 + (EM_GETSEL16 - EM_GETSEL);
1431 return 0;
1433 case LB_CARETOFF:
1434 case LB_CARETON:
1435 case LB_DELETESTRING:
1436 case LB_GETANCHORINDEX:
1437 case LB_GETCARETINDEX:
1438 case LB_GETCOUNT:
1439 case LB_GETCURSEL:
1440 case LB_GETHORIZONTALEXTENT:
1441 case LB_GETITEMDATA:
1442 case LB_GETITEMHEIGHT:
1443 case LB_GETSEL:
1444 case LB_GETSELCOUNT:
1445 case LB_GETTEXTLEN:
1446 case LB_GETTOPINDEX:
1447 case LB_RESETCONTENT:
1448 case LB_SELITEMRANGE:
1449 case LB_SELITEMRANGEEX:
1450 case LB_SETANCHORINDEX:
1451 case LB_SETCARETINDEX:
1452 case LB_SETCOLUMNWIDTH:
1453 case LB_SETCURSEL:
1454 case LB_SETHORIZONTALEXTENT:
1455 case LB_SETITEMDATA:
1456 case LB_SETITEMHEIGHT:
1457 case LB_SETSEL:
1458 case LB_SETTOPINDEX:
1459 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1460 return 0;
1461 case CB_DELETESTRING:
1462 case CB_GETCOUNT:
1463 case CB_GETLBTEXTLEN:
1464 case CB_LIMITTEXT:
1465 case CB_RESETCONTENT:
1466 case CB_SETEDITSEL:
1467 case CB_GETCURSEL:
1468 case CB_SETCURSEL:
1469 case CB_SHOWDROPDOWN:
1470 case CB_SETITEMDATA:
1471 case CB_SETITEMHEIGHT:
1472 case CB_GETITEMHEIGHT:
1473 case CB_SETEXTENDEDUI:
1474 case CB_GETEXTENDEDUI:
1475 case CB_GETDROPPEDSTATE:
1476 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1477 return 0;
1478 case CB_GETEDITSEL:
1479 *pmsg16 = CB_GETEDITSEL16;
1480 return 1;
1482 case LB_ADDSTRING:
1483 case LB_FINDSTRING:
1484 case LB_FINDSTRINGEXACT:
1485 case LB_INSERTSTRING:
1486 case LB_SELECTSTRING:
1487 case LB_DIR:
1488 case LB_ADDFILE:
1489 *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1490 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
1491 return 1;
1493 case CB_ADDSTRING:
1494 case CB_FINDSTRING:
1495 case CB_FINDSTRINGEXACT:
1496 case CB_INSERTSTRING:
1497 case CB_SELECTSTRING:
1498 case CB_DIR:
1499 *plparam = (LPARAM)MapLS( (LPSTR)*plparam );
1500 *pmsg16 = (UINT16)msg32 + (CB_GETEDITSEL16 - CB_GETEDITSEL);
1501 return 1;
1503 case LB_GETITEMRECT:
1505 RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
1506 if (!rect) return -1;
1507 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1508 *plparam = MapLS( rect );
1510 *pmsg16 = LB_GETITEMRECT16;
1511 return 1;
1512 case LB_GETSELITEMS:
1514 LPARAM *items; /* old LPARAM first, then *pwparam16 x INT16 entries */
1516 *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1517 if (!(items = HeapAlloc( GetProcessHeap(), 0,
1518 *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
1519 *items++ = *plparam; /* Store the previous lParam */
1520 *plparam = MapLS( items );
1522 *pmsg16 = LB_GETSELITEMS16;
1523 return 1;
1524 case LB_SETTABSTOPS:
1525 if (wParam32)
1527 INT i;
1528 LPINT16 stops;
1529 *pwparam16 = (WPARAM16)min( wParam32, 0x7f80 ); /* Must be < 64K */
1530 if (!(stops = HeapAlloc( GetProcessHeap(), 0,
1531 *pwparam16 * sizeof(INT16) + sizeof(LPARAM)))) return -1;
1532 for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT)*plparam+i);
1533 *plparam = MapLS( stops );
1534 return 1;
1536 *pmsg16 = LB_SETTABSTOPS16;
1537 return 0;
1539 case CB_GETDROPPEDCONTROLRECT:
1541 RECT16 *rect = HeapAlloc( GetProcessHeap(), 0, sizeof(RECT16) + sizeof(LPARAM) );
1542 if (!rect) return -1;
1543 *(LPARAM *)(rect + 1) = *plparam; /* Store the previous lParam */
1544 *plparam = (LPARAM)MapLS(rect);
1546 *pmsg16 = CB_GETDROPPEDCONTROLRECT16;
1547 return 1;
1549 case LB_GETTEXT:
1550 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1551 *pmsg16 = LB_GETTEXT16;
1552 return 1;
1554 case CB_GETLBTEXT:
1555 *plparam = (LPARAM)MapLS( (LPVOID)(*plparam) );
1556 *pmsg16 = CB_GETLBTEXT16;
1557 return 1;
1559 case EM_SETSEL:
1560 *pwparam16 = 0;
1561 *plparam = MAKELONG( (INT16)(INT)wParam32, (INT16)*plparam );
1562 *pmsg16 = EM_SETSEL16;
1563 return 0;
1565 case WM_ACTIVATE:
1566 case WM_CHARTOITEM:
1567 case WM_COMMAND:
1568 case WM_VKEYTOITEM:
1569 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
1570 return 0;
1571 case WM_HSCROLL:
1572 case WM_VSCROLL:
1573 *plparam = MAKELPARAM( HIWORD(wParam32), (HWND16)*plparam );
1574 return 0;
1575 case WM_COPYDATA:
1577 PCOPYDATASTRUCT pcds32 = (PCOPYDATASTRUCT) *plparam;
1578 PCOPYDATASTRUCT16 pcds = HeapAlloc( GetProcessHeap(), 0, sizeof( *pcds));
1579 pcds->dwData = pcds32->dwData;
1580 pcds->cbData = pcds32->cbData;
1581 pcds->lpData = MapLS( pcds32->lpData);
1582 *plparam = MapLS( pcds );
1584 return 1;
1585 case WM_CTLCOLORMSGBOX:
1586 case WM_CTLCOLOREDIT:
1587 case WM_CTLCOLORLISTBOX:
1588 case WM_CTLCOLORBTN:
1589 case WM_CTLCOLORDLG:
1590 case WM_CTLCOLORSCROLLBAR:
1591 case WM_CTLCOLORSTATIC:
1592 *pmsg16 = WM_CTLCOLOR;
1593 *plparam = MAKELPARAM( (HWND16)*plparam,
1594 (WORD)msg32 - WM_CTLCOLORMSGBOX );
1595 return 0;
1596 case WM_COMPAREITEM:
1598 COMPAREITEMSTRUCT *cis32 = (COMPAREITEMSTRUCT *)*plparam;
1599 COMPAREITEMSTRUCT16 *cis = HeapAlloc( GetProcessHeap(), 0, sizeof(COMPAREITEMSTRUCT16));
1600 if (!cis) return -1;
1601 cis->CtlType = (UINT16)cis32->CtlType;
1602 cis->CtlID = (UINT16)cis32->CtlID;
1603 cis->hwndItem = HWND_16( cis32->hwndItem );
1604 cis->itemID1 = (UINT16)cis32->itemID1;
1605 cis->itemData1 = cis32->itemData1;
1606 cis->itemID2 = (UINT16)cis32->itemID2;
1607 cis->itemData2 = cis32->itemData2;
1608 *plparam = MapLS( cis );
1610 return 1;
1611 case WM_DELETEITEM:
1613 DELETEITEMSTRUCT *dis32 = (DELETEITEMSTRUCT *)*plparam;
1614 DELETEITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DELETEITEMSTRUCT16) );
1615 if (!dis) return -1;
1616 dis->CtlType = (UINT16)dis32->CtlType;
1617 dis->CtlID = (UINT16)dis32->CtlID;
1618 dis->itemID = (UINT16)dis32->itemID;
1619 dis->hwndItem = (dis->CtlType == ODT_MENU) ? (HWND16)LOWORD(dis32->hwndItem)
1620 : HWND_16( dis32->hwndItem );
1621 dis->itemData = dis32->itemData;
1622 *plparam = MapLS( dis );
1624 return 1;
1625 case WM_DRAWITEM:
1627 DRAWITEMSTRUCT *dis32 = (DRAWITEMSTRUCT *)*plparam;
1628 DRAWITEMSTRUCT16 *dis = HeapAlloc( GetProcessHeap(), 0, sizeof(DRAWITEMSTRUCT16) );
1629 if (!dis) return -1;
1630 dis->CtlType = (UINT16)dis32->CtlType;
1631 dis->CtlID = (UINT16)dis32->CtlID;
1632 dis->itemID = (UINT16)dis32->itemID;
1633 dis->itemAction = (UINT16)dis32->itemAction;
1634 dis->itemState = (UINT16)dis32->itemState;
1635 dis->hwndItem = HWND_16( dis32->hwndItem );
1636 dis->hDC = HDC_16(dis32->hDC);
1637 dis->itemData = dis32->itemData;
1638 dis->rcItem.left = dis32->rcItem.left;
1639 dis->rcItem.top = dis32->rcItem.top;
1640 dis->rcItem.right = dis32->rcItem.right;
1641 dis->rcItem.bottom = dis32->rcItem.bottom;
1642 *plparam = MapLS( dis );
1644 return 1;
1645 case WM_MEASUREITEM:
1647 MEASUREITEMSTRUCT *mis32 = (MEASUREITEMSTRUCT *)*plparam;
1648 MEASUREITEMSTRUCT16 *mis = HeapAlloc( GetProcessHeap(), 0, sizeof(*mis)+sizeof(LPARAM));
1649 if (!mis) return -1;
1650 mis->CtlType = (UINT16)mis32->CtlType;
1651 mis->CtlID = (UINT16)mis32->CtlID;
1652 mis->itemID = (UINT16)mis32->itemID;
1653 mis->itemWidth = (UINT16)mis32->itemWidth;
1654 mis->itemHeight = (UINT16)mis32->itemHeight;
1655 mis->itemData = mis32->itemData;
1656 *(LPARAM *)(mis + 1) = *plparam; /* Store the previous lParam */
1657 *plparam = MapLS( mis );
1659 return 1;
1660 case WM_GETMINMAXINFO:
1662 MINMAXINFO16 *mmi = HeapAlloc( GetProcessHeap(), 0, sizeof(*mmi) + sizeof(LPARAM) );
1663 if (!mmi) return -1;
1664 MINMAXINFO32to16( (MINMAXINFO *)*plparam, mmi );
1665 *(LPARAM *)(mmi + 1) = *plparam; /* Store the previous lParam */
1666 *plparam = MapLS( mmi );
1668 return 1;
1669 case WM_GETTEXT:
1670 case WM_ASKCBFORMATNAME:
1672 LPARAM *str; /* store LPARAM, then *pwparam16 char space */
1673 *pwparam16 = (WPARAM16)min( wParam32, 0xff80 ); /* Must be < 64K */
1674 if (!(str = HeapAlloc( GetProcessHeap(), 0, *pwparam16 + sizeof(LPARAM)))) return -1;
1675 *str++ = *plparam; /* Store the previous lParam */
1676 *plparam = MapLS( str );
1678 return 1;
1679 case WM_MDICREATE:
1681 MDICREATESTRUCT16 *cs;
1682 MDICREATESTRUCTA *cs32 = (MDICREATESTRUCTA *)*plparam;
1684 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
1685 MDICREATESTRUCT32Ato16( cs32, cs );
1686 cs->szTitle = MapLS( cs32->szTitle );
1687 cs->szClass = MapLS( cs32->szClass );
1688 *plparam = MapLS( cs );
1690 return 1;
1691 case WM_MDIGETACTIVE:
1692 return 1;
1693 case WM_MDISETMENU:
1694 *plparam = MAKELPARAM( (HMENU16)LOWORD(wParam32),
1695 (HMENU16)LOWORD(*plparam) );
1696 *pwparam16 = (*plparam == 0);
1697 return 0;
1698 case WM_MENUSELECT:
1699 if(HIWORD(wParam32) & MF_POPUP)
1701 HMENU hmenu;
1702 if (((UINT)HIWORD(wParam32) != 0xFFFF) || (*plparam))
1704 if((hmenu = GetSubMenu((HMENU)*plparam, *pwparam16)))
1705 *pwparam16=HMENU_16(hmenu);
1708 /* fall through */
1709 case WM_MENUCHAR:
1710 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
1711 return 0;
1712 case WM_MDIACTIVATE:
1713 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_MDICHILD)
1715 *pwparam16 = ((HWND)*plparam == hwnd);
1716 *plparam = MAKELPARAM( (HWND16)LOWORD(*plparam),
1717 (HWND16)LOWORD(wParam32) );
1719 else
1721 *pwparam16 = HWND_16( (HWND)wParam32 );
1722 *plparam = 0;
1724 return 0;
1725 case WM_NCCALCSIZE:
1727 NCCALCSIZE_PARAMS *nc32 = (NCCALCSIZE_PARAMS *)*plparam;
1728 NCCALCSIZE_PARAMS16 *nc = HeapAlloc( GetProcessHeap(), 0, sizeof(*nc) + sizeof(LPARAM));
1729 if (!nc) return -1;
1731 nc->rgrc[0].left = nc32->rgrc[0].left;
1732 nc->rgrc[0].top = nc32->rgrc[0].top;
1733 nc->rgrc[0].right = nc32->rgrc[0].right;
1734 nc->rgrc[0].bottom = nc32->rgrc[0].bottom;
1735 if (wParam32)
1737 WINDOWPOS16 *wp;
1738 nc->rgrc[1].left = nc32->rgrc[1].left;
1739 nc->rgrc[1].top = nc32->rgrc[1].top;
1740 nc->rgrc[1].right = nc32->rgrc[1].right;
1741 nc->rgrc[1].bottom = nc32->rgrc[1].bottom;
1742 nc->rgrc[2].left = nc32->rgrc[2].left;
1743 nc->rgrc[2].top = nc32->rgrc[2].top;
1744 nc->rgrc[2].right = nc32->rgrc[2].right;
1745 nc->rgrc[2].bottom = nc32->rgrc[2].bottom;
1746 if (!(wp = HeapAlloc( GetProcessHeap(), 0, sizeof(WINDOWPOS16) )))
1748 HeapFree( GetProcessHeap(), 0, nc );
1749 return -1;
1751 WINDOWPOS32to16( nc32->lppos, wp );
1752 nc->lppos = MapLS( wp );
1754 *(LPARAM *)(nc + 1) = *plparam; /* Store the previous lParam */
1755 *plparam = MapLS( nc );
1757 return 1;
1758 case WM_NCCREATE:
1759 case WM_CREATE:
1761 CREATESTRUCT16 *cs;
1762 CREATESTRUCTA *cs32 = (CREATESTRUCTA *)*plparam;
1764 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
1765 CREATESTRUCT32Ato16( cs32, cs );
1766 cs->lpszName = MapLS( cs32->lpszName );
1767 cs->lpszClass = MapLS( cs32->lpszClass );
1769 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1771 MDICREATESTRUCT16 *mdi_cs16;
1772 MDICREATESTRUCTA *mdi_cs = (MDICREATESTRUCTA *)cs32->lpCreateParams;
1773 mdi_cs16 = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs16));
1774 if (!mdi_cs16)
1776 HeapFree(GetProcessHeap(), 0, cs);
1777 return -1;
1779 MDICREATESTRUCT32Ato16(mdi_cs, mdi_cs16);
1780 mdi_cs16->szTitle = MapLS( mdi_cs->szTitle );
1781 mdi_cs16->szClass = MapLS( mdi_cs->szClass );
1782 cs->lpCreateParams = MapLS( mdi_cs16 );
1784 *plparam = MapLS( cs );
1786 return 1;
1787 case WM_PARENTNOTIFY:
1788 if ((LOWORD(wParam32)==WM_CREATE) || (LOWORD(wParam32)==WM_DESTROY))
1789 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32));
1790 /* else nothing to do */
1791 return 0;
1792 case WM_NOTIFY:
1793 *plparam = MapLS( (NMHDR *)*plparam ); /* NMHDR is already 32-bit */
1794 return 1;
1795 case WM_SETTEXT:
1796 case WM_WININICHANGE:
1797 case WM_DEVMODECHANGE:
1798 *plparam = MapLS( (LPSTR)*plparam );
1799 return 1;
1800 case WM_WINDOWPOSCHANGING:
1801 case WM_WINDOWPOSCHANGED:
1803 WINDOWPOS16 *wp = HeapAlloc( GetProcessHeap(), 0, sizeof(*wp) + sizeof(LPARAM) );
1804 if (!wp) return -1;
1805 WINDOWPOS32to16( (WINDOWPOS *)*plparam, wp );
1806 *(LPARAM *)(wp + 1) = *plparam; /* Store the previous lParam */
1807 *plparam = MapLS( wp );
1809 return 1;
1810 case WM_GETDLGCODE:
1811 if (*plparam) {
1812 LPMSG msg32 = (LPMSG) *plparam;
1813 LPMSG16 msg16 = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG16) );
1815 if (!msg16) return -1;
1816 msg16->hwnd = HWND_16( msg32->hwnd );
1817 msg16->message = msg32->message;
1818 msg16->wParam = msg32->wParam;
1819 msg16->lParam = msg32->lParam;
1820 msg16->time = msg32->time;
1821 msg16->pt.x = msg32->pt.x;
1822 msg16->pt.y = msg32->pt.y;
1823 *plparam = MapLS( msg16 );
1824 return 1;
1826 return 0;
1828 case WM_ACTIVATEAPP:
1829 if (*plparam) *plparam = HTASK_16( (HANDLE)*plparam );
1830 return 0;
1831 case WM_NEXTMENU:
1833 MDINEXTMENU *next = (MDINEXTMENU *)*plparam;
1834 *plparam = (LPARAM)next->hmenuIn;
1835 return 1;
1837 case WM_PAINT:
1838 if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON ))
1840 *pmsg16 = WM_PAINTICON;
1841 *pwparam16 = 1;
1843 return 0;
1844 case WM_ERASEBKGND:
1845 if (IsIconic( hwnd ) && GetClassLongPtrW( hwnd, GCLP_HICON ))
1846 *pmsg16 = WM_ICONERASEBKGND;
1847 return 0;
1848 case WM_PAINTCLIPBOARD:
1849 case WM_SIZECLIPBOARD:
1850 FIXME_(msg)("message %04x needs translation\n", msg32 );
1851 return -1;
1852 /* following messages should not be sent to 16-bit apps */
1853 case WM_SIZING:
1854 case WM_MOVING:
1855 case WM_CAPTURECHANGED:
1856 case WM_STYLECHANGING:
1857 case WM_STYLECHANGED:
1858 return -1;
1859 case WM_DDE_INITIATE:
1860 case WM_DDE_TERMINATE:
1861 case WM_DDE_UNADVISE:
1862 case WM_DDE_REQUEST:
1863 *pwparam16 = HWND_16((HWND)wParam32);
1864 return 0;
1865 case WM_DDE_ADVISE:
1866 case WM_DDE_DATA:
1867 case WM_DDE_POKE:
1869 UINT_PTR lo32, hi;
1870 HANDLE16 lo16 = 0;
1872 *pwparam16 = HWND_16((HWND)wParam32);
1873 UnpackDDElParam(msg32, *plparam, &lo32, &hi);
1874 if (lo32 && !(lo16 = convert_handle_32_to_16(lo32, GMEM_DDESHARE)))
1875 return -1;
1876 *plparam = MAKELPARAM(lo16, hi);
1878 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1879 case WM_DDE_ACK:
1881 UINT_PTR lo, hi;
1882 int flag = 0;
1883 char buf[2];
1885 *pwparam16 = HWND_16((HWND)wParam32);
1887 UnpackDDElParam(msg32, *plparam, &lo, &hi);
1889 if (GlobalGetAtomNameA((ATOM)hi, buf, sizeof(buf)) > 0) flag |= 1;
1890 if (GlobalSize((HANDLE)hi) != 0) flag |= 2;
1891 switch (flag)
1893 case 0:
1894 if (hi)
1896 MESSAGE("DDE_ACK: neither atom nor handle!!!\n");
1897 hi = 0;
1899 break;
1900 case 1:
1901 break; /* atom, nothing to do */
1902 case 3:
1903 MESSAGE("DDE_ACK: %x both atom and handle... choosing handle\n", hi);
1904 /* fall thru */
1905 case 2:
1906 hi = convert_handle_32_to_16(hi, GMEM_DDESHARE);
1907 break;
1909 *plparam = MAKELPARAM(lo, hi);
1911 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1912 case WM_DDE_EXECUTE:
1913 *plparam = convert_handle_32_to_16(*plparam, GMEM_DDESHARE);
1914 return 0; /* FIXME don't know how to free allocated memory (handle) !! */
1915 default: /* No translation needed */
1916 return 0;
1921 /**********************************************************************
1922 * WINPROC_UnmapMsg32ATo16
1924 * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
1926 static void WINPROC_UnmapMsg32ATo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
1927 WPARAM16 wParam16, LPARAM lParam16, LRESULT *result )
1929 switch(msg)
1931 case SBM_GETRANGE:
1932 *(LPINT)wParam = LOWORD(*result);
1933 *(LPINT)lParam = HIWORD(*result);
1934 break;
1936 case LB_ADDFILE:
1937 case LB_ADDSTRING:
1938 case LB_DIR:
1939 case LB_FINDSTRING:
1940 case LB_FINDSTRINGEXACT:
1941 case LB_INSERTSTRING:
1942 case LB_SELECTSTRING:
1943 case LB_GETTEXT:
1944 case CB_ADDSTRING:
1945 case CB_FINDSTRING:
1946 case CB_FINDSTRINGEXACT:
1947 case CB_INSERTSTRING:
1948 case CB_SELECTSTRING:
1949 case CB_DIR:
1950 case CB_GETLBTEXT:
1951 case WM_SETTEXT:
1952 case WM_WININICHANGE:
1953 case WM_DEVMODECHANGE:
1954 UnMapLS( (SEGPTR)lParam16 );
1955 break;
1956 case LB_SETTABSTOPS:
1957 case WM_COMPAREITEM:
1958 case WM_DELETEITEM:
1959 case WM_DRAWITEM:
1961 void *ptr = MapSL( lParam16 );
1962 UnMapLS( lParam16 );
1963 HeapFree( GetProcessHeap(), 0, ptr );
1965 break;
1966 case WM_COPYDATA:
1968 PCOPYDATASTRUCT16 pcds = MapSL( lParam16 );
1969 UnMapLS( lParam16 );
1970 UnMapLS( pcds->lpData );
1971 HeapFree( GetProcessHeap(), 0, pcds );
1973 break;
1974 case CB_GETDROPPEDCONTROLRECT:
1975 case LB_GETITEMRECT:
1977 RECT *r32;
1978 RECT16 *rect = MapSL(lParam16);
1979 UnMapLS( lParam16 );
1980 lParam16 = *(LPARAM *)(rect + 1);
1981 r32 = (RECT *)lParam16;
1982 r32->left = rect->left;
1983 r32->top = rect->top;
1984 r32->right = rect->right;
1985 r32->bottom = rect->bottom;
1986 HeapFree( GetProcessHeap(), 0, rect );
1988 break;
1989 case LB_GETSELITEMS:
1991 INT i;
1992 LPINT16 items = MapSL(lParam16);
1993 UnMapLS( lParam16 );
1994 lParam16 = *((LPARAM *)items - 1);
1995 for (i = 0; i < wParam16; i++) *((LPINT)lParam16 + i) = items[i];
1996 HeapFree( GetProcessHeap(), 0, (LPARAM *)items - 1 );
1998 break;
2000 case CB_GETEDITSEL:
2001 if( wParam )
2002 *((PUINT)(wParam)) = LOWORD(*result);
2003 if( lParam )
2004 *((PUINT)(lParam)) = HIWORD(*result); /* FIXME: substract 1? */
2005 break;
2007 case WM_MEASUREITEM:
2009 MEASUREITEMSTRUCT16 *mis = MapSL(lParam16);
2010 MEASUREITEMSTRUCT *mis32 = *(MEASUREITEMSTRUCT **)(mis + 1);
2011 mis32->itemWidth = mis->itemWidth;
2012 mis32->itemHeight = mis->itemHeight;
2013 UnMapLS( lParam16 );
2014 HeapFree( GetProcessHeap(), 0, mis );
2016 break;
2017 case WM_GETMINMAXINFO:
2019 MINMAXINFO16 *mmi = MapSL(lParam16);
2020 UnMapLS( lParam16 );
2021 lParam16 = *(LPARAM *)(mmi + 1);
2022 MINMAXINFO16to32( mmi, (MINMAXINFO *)lParam16 );
2023 HeapFree( GetProcessHeap(), 0, mmi );
2025 break;
2026 case WM_GETTEXT:
2027 case WM_ASKCBFORMATNAME:
2029 LPSTR str = MapSL(lParam16);
2030 UnMapLS( lParam16 );
2031 lParam16 = *((LPARAM *)str - 1);
2032 lstrcpynA( (LPSTR)lParam16, str, wParam16 );
2033 HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2035 break;
2036 case WM_MDICREATE:
2038 MDICREATESTRUCT16 *cs = MapSL(lParam16);
2039 UnMapLS( cs->szTitle );
2040 UnMapLS( cs->szClass );
2041 UnMapLS( lParam16 );
2042 HeapFree( GetProcessHeap(), 0, cs );
2044 break;
2045 case WM_MDIGETACTIVE:
2046 if (lParam) *(BOOL *)lParam = (BOOL16)HIWORD(*result);
2047 *result = (LRESULT)WIN_Handle32( LOWORD(*result) );
2048 break;
2049 case WM_NCCALCSIZE:
2051 NCCALCSIZE_PARAMS *nc32;
2052 NCCALCSIZE_PARAMS16 *nc = MapSL(lParam16);
2053 UnMapLS( lParam16 );
2054 lParam16 = *(LPARAM *)(nc + 1);
2055 nc32 = (NCCALCSIZE_PARAMS *)lParam16;
2056 nc32->rgrc[0].left = nc->rgrc[0].left;
2057 nc32->rgrc[0].top = nc->rgrc[0].top;
2058 nc32->rgrc[0].right = nc->rgrc[0].right;
2059 nc32->rgrc[0].bottom = nc->rgrc[0].bottom;
2060 if (wParam16)
2062 WINDOWPOS16 *pos = MapSL(nc->lppos);
2063 UnMapLS( nc->lppos );
2064 nc32->rgrc[1].left = nc->rgrc[1].left;
2065 nc32->rgrc[1].top = nc->rgrc[1].top;
2066 nc32->rgrc[1].right = nc->rgrc[1].right;
2067 nc32->rgrc[1].bottom = nc->rgrc[1].bottom;
2068 nc32->rgrc[2].left = nc->rgrc[2].left;
2069 nc32->rgrc[2].top = nc->rgrc[2].top;
2070 nc32->rgrc[2].right = nc->rgrc[2].right;
2071 nc32->rgrc[2].bottom = nc->rgrc[2].bottom;
2072 WINDOWPOS16to32( pos, nc32->lppos );
2073 HeapFree( GetProcessHeap(), 0, pos );
2075 HeapFree( GetProcessHeap(), 0, nc );
2077 break;
2078 case WM_NCCREATE:
2079 case WM_CREATE:
2081 CREATESTRUCT16 *cs = MapSL(lParam16);
2082 UnMapLS( lParam16 );
2083 UnMapLS( cs->lpszName );
2084 UnMapLS( cs->lpszClass );
2085 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2087 MDICREATESTRUCT16 *mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs->lpCreateParams);
2088 UnMapLS( cs->lpCreateParams );
2089 UnMapLS( mdi_cs16->szTitle );
2090 UnMapLS( mdi_cs16->szClass );
2091 HeapFree(GetProcessHeap(), 0, mdi_cs16);
2093 HeapFree( GetProcessHeap(), 0, cs );
2095 break;
2096 case WM_WINDOWPOSCHANGING:
2097 case WM_WINDOWPOSCHANGED:
2099 WINDOWPOS16 *wp = MapSL(lParam16);
2100 UnMapLS( lParam16 );
2101 lParam16 = *(LPARAM *)(wp + 1);
2102 WINDOWPOS16to32( wp, (WINDOWPOS *)lParam16 );
2103 HeapFree( GetProcessHeap(), 0, wp );
2105 break;
2106 case WM_NOTIFY:
2107 UnMapLS(lParam16);
2108 break;
2109 case WM_GETDLGCODE:
2110 if (lParam16)
2112 LPMSG16 msg16 = MapSL(lParam16);
2113 UnMapLS( lParam16 );
2114 HeapFree( GetProcessHeap(), 0, msg16 );
2116 break;
2117 case WM_NEXTMENU:
2119 MDINEXTMENU *next = (MDINEXTMENU *)lParam;
2120 next->hmenuNext = HMENU_32( LOWORD(*result) );
2121 next->hwndNext = WIN_Handle32( HIWORD(*result) );
2122 *result = 0;
2124 break;
2129 /**********************************************************************
2130 * WINPROC_MapMsg32WTo16
2132 * Map a message from 32-bit Unicode to 16-bit.
2133 * Return value is -1 on error, 0 if OK, 1 if an UnmapMsg call is needed.
2135 static INT WINPROC_MapMsg32WTo16( HWND hwnd, UINT msg32, WPARAM wParam32,
2136 UINT16 *pmsg16, WPARAM16 *pwparam16, LPARAM *plparam )
2138 *pmsg16 = LOWORD(msg32);
2139 *pwparam16 = LOWORD(wParam32);
2140 switch(msg32)
2142 case LB_ADDSTRING:
2143 case LB_FINDSTRING:
2144 case LB_FINDSTRINGEXACT:
2145 case LB_INSERTSTRING:
2146 case LB_SELECTSTRING:
2147 case LB_DIR:
2148 case LB_ADDFILE:
2149 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2150 *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING);
2151 return 1;
2153 case CB_ADDSTRING:
2154 case CB_FINDSTRING:
2155 case CB_FINDSTRINGEXACT:
2156 case CB_INSERTSTRING:
2157 case CB_SELECTSTRING:
2158 case CB_DIR:
2159 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2160 *pmsg16 = (UINT16)msg32 + (CB_ADDSTRING16 - CB_ADDSTRING);
2161 return 1;
2163 case WM_NCCREATE:
2164 case WM_CREATE:
2166 CREATESTRUCT16 *cs;
2167 CREATESTRUCTW *cs32 = (CREATESTRUCTW *)*plparam;
2169 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(CREATESTRUCT16) ))) return -1;
2170 CREATESTRUCT32Ato16( (CREATESTRUCTA *)cs32, cs );
2171 cs->lpszName = map_str_32W_to_16( cs32->lpszName );
2172 cs->lpszClass = map_str_32W_to_16( cs32->lpszClass );
2174 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2176 MDICREATESTRUCT16 *mdi_cs16;
2177 MDICREATESTRUCTW *mdi_cs = (MDICREATESTRUCTW *)cs32->lpCreateParams;
2178 mdi_cs16 = HeapAlloc(GetProcessHeap(), 0, sizeof(*mdi_cs16));
2179 if (!mdi_cs16)
2181 HeapFree(GetProcessHeap(), 0, cs);
2182 return -1;
2184 MDICREATESTRUCT32Ato16((MDICREATESTRUCTA *)mdi_cs, mdi_cs16);
2185 mdi_cs16->szTitle = map_str_32W_to_16(mdi_cs->szTitle);
2186 mdi_cs16->szClass = map_str_32W_to_16(mdi_cs->szClass);
2187 cs->lpCreateParams = MapLS(mdi_cs16);
2189 *plparam = MapLS(cs);
2191 return 1;
2192 case WM_MDICREATE:
2194 MDICREATESTRUCT16 *cs;
2195 MDICREATESTRUCTW *cs32 = (MDICREATESTRUCTW *)*plparam;
2197 if (!(cs = HeapAlloc( GetProcessHeap(), 0, sizeof(MDICREATESTRUCT16) ))) return -1;
2198 MDICREATESTRUCT32Ato16( (MDICREATESTRUCTA *)cs32, cs );
2199 cs->szTitle = map_str_32W_to_16( cs32->szTitle );
2200 cs->szClass = map_str_32W_to_16( cs32->szClass );
2201 *plparam = MapLS(cs);
2203 return 1;
2204 case WM_SETTEXT:
2205 case WM_WININICHANGE:
2206 case WM_DEVMODECHANGE:
2207 *plparam = map_str_32W_to_16( (LPWSTR)*plparam );
2208 return 1;
2209 case LB_GETTEXT:
2210 case CB_GETLBTEXT:
2211 if ( WINPROC_TestLBForStr( hwnd, msg32 ))
2213 LPSTR str = HeapAlloc( GetProcessHeap(), 0, 512 ); /* FIXME: fixed sized buffer */
2214 if (!str) return -1;
2215 *pmsg16 = (msg32 == LB_GETTEXT) ? LB_GETTEXT16 : CB_GETLBTEXT16;
2216 *plparam = (LPARAM)MapLS(str);
2218 return 1;
2220 case WM_CHARTOITEM:
2221 *pwparam16 = map_wparam_char_WtoA( wParam32, 1 );
2222 *plparam = MAKELPARAM( (HWND16)*plparam, HIWORD(wParam32) );
2223 return 0;
2224 case WM_MENUCHAR:
2225 *pwparam16 = map_wparam_char_WtoA( wParam32, 1 );
2226 *plparam = MAKELPARAM( HIWORD(wParam32), (HMENU16)*plparam );
2227 return 0;
2228 case WM_CHAR:
2229 case WM_DEADCHAR:
2230 case WM_SYSCHAR:
2231 case WM_SYSDEADCHAR:
2232 *pwparam16 = map_wparam_char_WtoA( wParam32, 1 );
2233 return 0;
2234 case WM_IME_CHAR:
2235 *pwparam16 = map_wparam_char_WtoA( wParam32, 2 );
2236 return 0;
2238 default: /* No Unicode translation needed (?) */
2239 return WINPROC_MapMsg32ATo16( hwnd, msg32, wParam32, pmsg16,
2240 pwparam16, plparam );
2245 /**********************************************************************
2246 * WINPROC_UnmapMsg32WTo16
2248 * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
2250 static void WINPROC_UnmapMsg32WTo16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
2251 WPARAM16 wParam16, LPARAM lParam16, LRESULT *result )
2253 switch(msg)
2255 case LB_ADDSTRING:
2256 case LB_FINDSTRING:
2257 case LB_FINDSTRINGEXACT:
2258 case LB_INSERTSTRING:
2259 case LB_SELECTSTRING:
2260 case LB_DIR:
2261 case LB_ADDFILE:
2262 case CB_ADDSTRING:
2263 case CB_FINDSTRING:
2264 case CB_FINDSTRINGEXACT:
2265 case CB_INSERTSTRING:
2266 case CB_SELECTSTRING:
2267 case CB_DIR:
2268 case WM_SETTEXT:
2269 case WM_WININICHANGE:
2270 case WM_DEVMODECHANGE:
2271 unmap_str_32W_to_16( lParam16 );
2272 break;
2273 case WM_NCCREATE:
2274 case WM_CREATE:
2276 CREATESTRUCT16 *cs = MapSL(lParam16);
2277 UnMapLS( lParam16 );
2278 unmap_str_32W_to_16( cs->lpszName );
2279 unmap_str_32W_to_16( cs->lpszClass );
2281 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2283 MDICREATESTRUCT16 *mdi_cs16 = (MDICREATESTRUCT16 *)MapSL(cs->lpCreateParams);
2284 UnMapLS( cs->lpCreateParams );
2285 unmap_str_32W_to_16(mdi_cs16->szTitle);
2286 unmap_str_32W_to_16(mdi_cs16->szClass);
2287 HeapFree(GetProcessHeap(), 0, mdi_cs16);
2289 HeapFree( GetProcessHeap(), 0, cs );
2291 break;
2292 case WM_MDICREATE:
2294 MDICREATESTRUCT16 *cs = MapSL(lParam16);
2295 UnMapLS( lParam16 );
2296 unmap_str_32W_to_16( cs->szTitle );
2297 unmap_str_32W_to_16( cs->szClass );
2298 HeapFree( GetProcessHeap(), 0, cs );
2300 break;
2301 case WM_GETTEXT:
2302 case WM_ASKCBFORMATNAME:
2304 LPSTR str = MapSL(lParam16);
2305 UnMapLS( lParam16 );
2306 lParam16 = *((LPARAM *)str - 1);
2307 MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam16, 0x7fffffff );
2308 *result = strlenW( (LPWSTR)lParam16 );
2309 HeapFree( GetProcessHeap(), 0, (LPARAM *)str - 1 );
2311 break;
2312 case LB_GETTEXT:
2313 case CB_GETLBTEXT:
2314 if ( WINPROC_TestLBForStr( hwnd, msg ))
2316 LPSTR str = MapSL(lParam16);
2317 UnMapLS( lParam16 );
2318 *result = MultiByteToWideChar( CP_ACP, 0, str, -1, (LPWSTR)lParam, 0x7fffffff ) - 1;
2319 HeapFree( GetProcessHeap(), 0, (LPARAM *)str );
2321 break;
2322 default:
2323 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, wParam16, lParam16, result );
2324 break;
2329 /**********************************************************************
2330 * WINPROC_CallProcAtoW
2332 * Call a window procedure, translating args from Ansi to Unicode.
2334 LRESULT WINPROC_CallProcAtoW( winproc_callback_t callback, HWND hwnd, UINT msg, WPARAM wParam,
2335 LPARAM lParam, LRESULT *result, void *arg )
2337 LRESULT ret = 0;
2339 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2340 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2342 switch(msg)
2344 case WM_NCCREATE:
2345 case WM_CREATE:
2347 WCHAR *ptr, buffer[512];
2348 CREATESTRUCTA *csA = (CREATESTRUCTA *)lParam;
2349 CREATESTRUCTW csW = *(CREATESTRUCTW *)csA;
2350 MDICREATESTRUCTW mdi_cs;
2351 DWORD name_lenA = 0, name_lenW = 0, class_lenA = 0, class_lenW = 0;
2353 if (HIWORD(csA->lpszClass))
2355 class_lenA = strlen(csA->lpszClass) + 1;
2356 RtlMultiByteToUnicodeSize( &class_lenW, csA->lpszClass, class_lenA );
2358 if (HIWORD(csA->lpszName))
2360 name_lenA = strlen(csA->lpszName) + 1;
2361 RtlMultiByteToUnicodeSize( &name_lenW, csA->lpszName, name_lenA );
2364 if (!(ptr = get_buffer( buffer, sizeof(buffer), class_lenW + name_lenW ))) break;
2366 if (class_lenW)
2368 csW.lpszClass = ptr;
2369 RtlMultiByteToUnicodeN( ptr, class_lenW, NULL, csA->lpszClass, class_lenA );
2371 if (name_lenW)
2373 csW.lpszName = ptr + class_lenW/sizeof(WCHAR);
2374 RtlMultiByteToUnicodeN( ptr + class_lenW/sizeof(WCHAR), name_lenW, NULL,
2375 csA->lpszName, name_lenA );
2378 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2380 mdi_cs = *(MDICREATESTRUCTW *)csA->lpCreateParams;
2381 mdi_cs.szTitle = csW.lpszName;
2382 mdi_cs.szClass = csW.lpszClass;
2383 csW.lpCreateParams = &mdi_cs;
2386 ret = callback( hwnd, msg, wParam, (LPARAM)&csW, result, arg );
2387 free_buffer( buffer, ptr );
2389 break;
2391 case WM_MDICREATE:
2393 WCHAR *ptr, buffer[512];
2394 DWORD title_lenA = 0, title_lenW = 0, class_lenA = 0, class_lenW = 0;
2395 MDICREATESTRUCTA *csA = (MDICREATESTRUCTA *)lParam;
2396 MDICREATESTRUCTW csW;
2398 memcpy( &csW, csA, sizeof(csW) );
2400 if (HIWORD(csA->szTitle))
2402 title_lenA = strlen(csA->szTitle) + 1;
2403 RtlMultiByteToUnicodeSize( &title_lenW, csA->szTitle, title_lenA );
2405 if (HIWORD(csA->szClass))
2407 class_lenA = strlen(csA->szClass) + 1;
2408 RtlMultiByteToUnicodeSize( &class_lenW, csA->szClass, class_lenA );
2411 if (!(ptr = get_buffer( buffer, sizeof(buffer), title_lenW + class_lenW ))) break;
2413 if (title_lenW)
2415 csW.szTitle = ptr;
2416 RtlMultiByteToUnicodeN( ptr, title_lenW, NULL, csA->szTitle, title_lenA );
2418 if (class_lenW)
2420 csW.szClass = ptr + title_lenW/sizeof(WCHAR);
2421 RtlMultiByteToUnicodeN( ptr + title_lenW/sizeof(WCHAR), class_lenW, NULL,
2422 csA->szClass, class_lenA );
2424 ret = callback( hwnd, msg, wParam, (LPARAM)&csW, result, arg );
2425 free_buffer( buffer, ptr );
2427 break;
2429 case WM_GETTEXT:
2430 case WM_ASKCBFORMATNAME:
2432 WCHAR *ptr, buffer[512];
2433 LPSTR str = (LPSTR)lParam;
2434 DWORD len = wParam * sizeof(WCHAR);
2436 if (!(ptr = get_buffer( buffer, sizeof(buffer), len ))) break;
2437 ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2438 if (*result && wParam)
2440 RtlUnicodeToMultiByteN( str, wParam - 1, &len, ptr, strlenW(ptr) * sizeof(WCHAR) );
2441 str[len] = 0;
2442 *result = len;
2444 free_buffer( buffer, ptr );
2446 break;
2448 case LB_ADDSTRING:
2449 case LB_INSERTSTRING:
2450 case LB_FINDSTRING:
2451 case LB_FINDSTRINGEXACT:
2452 case LB_SELECTSTRING:
2453 case CB_ADDSTRING:
2454 case CB_INSERTSTRING:
2455 case CB_FINDSTRING:
2456 case CB_FINDSTRINGEXACT:
2457 case CB_SELECTSTRING:
2458 if (!lParam || !WINPROC_TestLBForStr( hwnd, msg ))
2460 ret = callback( hwnd, msg, wParam, lParam, result, arg );
2461 break;
2463 /* fall through */
2464 case WM_SETTEXT:
2465 case WM_WININICHANGE:
2466 case WM_DEVMODECHANGE:
2467 case CB_DIR:
2468 case LB_DIR:
2469 case LB_ADDFILE:
2470 case EM_REPLACESEL:
2471 if (!lParam) ret = callback( hwnd, msg, wParam, lParam, result, arg );
2472 else
2474 WCHAR *ptr, buffer[512];
2475 LPCSTR strA = (LPCSTR)lParam;
2476 DWORD lenW, lenA = strlen(strA) + 1;
2478 RtlMultiByteToUnicodeSize( &lenW, strA, lenA );
2479 if ((ptr = get_buffer( buffer, sizeof(buffer), lenW )))
2481 RtlMultiByteToUnicodeN( ptr, lenW, NULL, strA, lenA );
2482 ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2483 free_buffer( buffer, ptr );
2486 break;
2488 case LB_GETTEXT:
2489 case CB_GETLBTEXT:
2490 if (lParam && WINPROC_TestLBForStr( hwnd, msg ))
2492 WCHAR buffer[512]; /* FIXME: fixed sized buffer */
2494 ret = callback( hwnd, msg, wParam, (LPARAM)buffer, result, arg );
2495 if (*result >= 0)
2497 DWORD len;
2498 RtlUnicodeToMultiByteN( (LPSTR)lParam, ~0u, &len,
2499 buffer, (strlenW(buffer) + 1) * sizeof(WCHAR) );
2500 *result = len - 1;
2503 else ret = callback( hwnd, msg, wParam, lParam, result, arg );
2504 break;
2506 case EM_GETLINE:
2508 WCHAR *ptr, buffer[512];
2509 WORD len = *(WORD *)lParam;
2511 if (!(ptr = get_buffer( buffer, sizeof(buffer), len * sizeof(WCHAR) ))) break;
2512 *((WORD *)ptr) = len; /* store the length */
2513 ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2514 if (*result)
2516 DWORD reslen;
2517 RtlUnicodeToMultiByteN( (LPSTR)lParam, len, &reslen, ptr, *result * sizeof(WCHAR) );
2518 if (reslen < len) ((LPSTR)lParam)[reslen] = 0;
2519 *result = reslen;
2521 free_buffer( buffer, ptr );
2523 break;
2525 case WM_GETDLGCODE:
2526 if (lParam)
2528 MSG newmsg = *(MSG *)lParam;
2529 switch(newmsg.message)
2531 case WM_CHAR:
2532 case WM_DEADCHAR:
2533 case WM_SYSCHAR:
2534 case WM_SYSDEADCHAR:
2535 newmsg.wParam = map_wparam_char_AtoW( newmsg.wParam, 1 );
2536 break;
2537 case WM_IME_CHAR:
2538 newmsg.wParam = map_wparam_char_AtoW( newmsg.wParam, 2 );
2539 break;
2541 ret = callback( hwnd, msg, wParam, (LPARAM)&newmsg, result, arg );
2543 else ret = callback( hwnd, msg, wParam, lParam, result, arg );
2544 break;
2546 case WM_CHARTOITEM:
2547 case WM_MENUCHAR:
2548 case WM_CHAR:
2549 case WM_DEADCHAR:
2550 case WM_SYSCHAR:
2551 case WM_SYSDEADCHAR:
2552 case EM_SETPASSWORDCHAR:
2553 ret = callback( hwnd, msg, map_wparam_char_AtoW(wParam,1), lParam, result, arg );
2554 break;
2556 case WM_IME_CHAR:
2557 ret = callback( hwnd, msg, map_wparam_char_AtoW(wParam,2), lParam, result, arg );
2558 break;
2560 case WM_GETTEXTLENGTH:
2561 case CB_GETLBTEXTLEN:
2562 case LB_GETTEXTLEN:
2563 ret = callback( hwnd, msg, wParam, lParam, result, arg );
2564 if (*result >= 0)
2566 WCHAR *ptr, buffer[512];
2567 LRESULT tmp;
2568 DWORD len = *result + 1;
2569 /* Determine respective GETTEXT message */
2570 UINT msgGetText = (msg == WM_GETTEXTLENGTH) ? WM_GETTEXT :
2571 ((msg == CB_GETLBTEXTLEN) ? CB_GETLBTEXT : LB_GETTEXT);
2572 /* wParam differs between the messages */
2573 WPARAM wp = (msg == WM_GETTEXTLENGTH) ? len : wParam;
2575 if (!(ptr = get_buffer( buffer, sizeof(buffer), len * sizeof(WCHAR) ))) break;
2577 if (callback == call_window_proc) /* FIXME: hack */
2578 callback( hwnd, msgGetText, wp, (LPARAM)ptr, &tmp, arg );
2579 else
2580 tmp = SendMessageW( hwnd, msgGetText, wp, (LPARAM)ptr );
2581 RtlUnicodeToMultiByteSize( &len, ptr, tmp * sizeof(WCHAR) );
2582 *result = len;
2583 free_buffer( buffer, ptr );
2585 break;
2587 case WM_PAINTCLIPBOARD:
2588 case WM_SIZECLIPBOARD:
2589 FIXME_(msg)( "message %s (0x%x) needs translation, please report\n",
2590 SPY_GetMsgName(msg, hwnd), msg );
2591 break;
2593 default:
2594 ret = callback( hwnd, msg, wParam, lParam, result, arg );
2595 break;
2597 return ret;
2601 /**********************************************************************
2602 * WINPROC_CallProcWtoA
2604 * Call a window procedure, translating args from Unicode to Ansi.
2606 static LRESULT WINPROC_CallProcWtoA( winproc_callback_t callback, HWND hwnd, UINT msg, WPARAM wParam,
2607 LPARAM lParam, LRESULT *result, void *arg )
2609 LRESULT ret = 0;
2611 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2612 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2614 switch(msg)
2616 case WM_NCCREATE:
2617 case WM_CREATE:
2618 { /* csW->lpszName and csW->lpszClass are NOT supposed to be atoms
2619 * at this point.
2621 char buffer[1024], *cls, *name;
2622 CREATESTRUCTW *csW = (CREATESTRUCTW *)lParam;
2623 CREATESTRUCTA csA = *(CREATESTRUCTA *)csW;
2624 MDICREATESTRUCTA mdi_cs;
2625 DWORD name_lenA, name_lenW, class_lenA, class_lenW;
2627 class_lenW = strlenW(csW->lpszClass) * sizeof(WCHAR);
2628 RtlUnicodeToMultiByteSize(&class_lenA, csW->lpszClass, class_lenW);
2630 if (csW->lpszName)
2632 name_lenW = strlenW(csW->lpszName) * sizeof(WCHAR);
2633 RtlUnicodeToMultiByteSize(&name_lenA, csW->lpszName, name_lenW);
2635 else
2636 name_lenW = name_lenA = 0;
2638 if (!(cls = get_buffer( buffer, sizeof(buffer), class_lenA + name_lenA + 2 ))) break;
2640 RtlUnicodeToMultiByteN(cls, class_lenA, NULL, csW->lpszClass, class_lenW);
2641 cls[class_lenA] = 0;
2642 csA.lpszClass = cls;
2644 if (csW->lpszName)
2646 name = cls + class_lenA + 1;
2647 RtlUnicodeToMultiByteN(name, name_lenA, NULL, csW->lpszName, name_lenW);
2648 name[name_lenA] = 0;
2649 csA.lpszName = name;
2652 if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
2654 mdi_cs = *(MDICREATESTRUCTA *)csW->lpCreateParams;
2655 mdi_cs.szTitle = csA.lpszName;
2656 mdi_cs.szClass = csA.lpszClass;
2657 csA.lpCreateParams = &mdi_cs;
2660 ret = callback( hwnd, msg, wParam, (LPARAM)&csA, result, arg );
2661 free_buffer( buffer, cls );
2663 break;
2665 case WM_GETTEXT:
2666 case WM_ASKCBFORMATNAME:
2668 char *ptr, buffer[512];
2669 DWORD len = wParam * 2;
2671 if (!(ptr = get_buffer( buffer, sizeof(buffer), len ))) break;
2672 ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2673 if (*result && len)
2675 RtlMultiByteToUnicodeN( (LPWSTR)lParam, wParam*sizeof(WCHAR), &len, ptr, strlen(ptr)+1 );
2676 *result = len/sizeof(WCHAR) - 1; /* do not count terminating null */
2677 ((LPWSTR)lParam)[*result] = 0;
2679 free_buffer( buffer, ptr );
2681 break;
2683 case LB_ADDSTRING:
2684 case LB_INSERTSTRING:
2685 case LB_FINDSTRING:
2686 case LB_FINDSTRINGEXACT:
2687 case LB_SELECTSTRING:
2688 case CB_ADDSTRING:
2689 case CB_INSERTSTRING:
2690 case CB_FINDSTRING:
2691 case CB_FINDSTRINGEXACT:
2692 case CB_SELECTSTRING:
2693 if (!lParam || !WINPROC_TestLBForStr( hwnd, msg ))
2695 ret = callback( hwnd, msg, wParam, lParam, result, arg );
2696 break;
2698 /* fall through */
2699 case WM_SETTEXT:
2700 case WM_WININICHANGE:
2701 case WM_DEVMODECHANGE:
2702 case CB_DIR:
2703 case LB_DIR:
2704 case LB_ADDFILE:
2705 case EM_REPLACESEL:
2706 if (!lParam) ret = callback( hwnd, msg, wParam, lParam, result, arg );
2707 else
2709 char *ptr, buffer[512];
2710 LPCWSTR strW = (LPCWSTR)lParam;
2711 DWORD lenA, lenW = (strlenW(strW) + 1) * sizeof(WCHAR);
2713 RtlUnicodeToMultiByteSize( &lenA, strW, lenW );
2714 if ((ptr = get_buffer( buffer, sizeof(buffer), lenA )))
2716 RtlUnicodeToMultiByteN( ptr, lenA, NULL, strW, lenW );
2717 ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2718 free_buffer( buffer, ptr );
2721 break;
2723 case WM_MDICREATE:
2725 char *ptr, buffer[1024];
2726 DWORD title_lenA = 0, title_lenW = 0, class_lenA = 0, class_lenW = 0;
2727 MDICREATESTRUCTW *csW = (MDICREATESTRUCTW *)lParam;
2728 MDICREATESTRUCTA csA;
2730 memcpy( &csA, csW, sizeof(csA) );
2732 if (HIWORD(csW->szTitle))
2734 title_lenW = (strlenW(csW->szTitle) + 1) * sizeof(WCHAR);
2735 RtlUnicodeToMultiByteSize( &title_lenA, csW->szTitle, title_lenW );
2737 if (HIWORD(csW->szClass))
2739 class_lenW = (strlenW(csW->szClass) + 1) * sizeof(WCHAR);
2740 RtlUnicodeToMultiByteSize( &class_lenA, csW->szClass, class_lenW );
2743 if (!(ptr = get_buffer( buffer, sizeof(buffer), title_lenA + class_lenA ))) break;
2745 if (title_lenA)
2747 RtlUnicodeToMultiByteN( ptr, title_lenA, NULL, csW->szTitle, title_lenW );
2748 csA.szTitle = ptr;
2750 if (class_lenA)
2752 RtlUnicodeToMultiByteN( ptr + title_lenA, class_lenA, NULL, csW->szClass, class_lenW );
2753 csA.szClass = ptr + title_lenA;
2755 ret = callback( hwnd, msg, wParam, (LPARAM)&csA, result, arg );
2756 free_buffer( buffer, ptr );
2758 break;
2760 case LB_GETTEXT:
2761 case CB_GETLBTEXT:
2762 if (lParam && WINPROC_TestLBForStr( hwnd, msg ))
2764 char buffer[512]; /* FIXME: fixed sized buffer */
2766 ret = callback( hwnd, msg, wParam, (LPARAM)buffer, result, arg );
2767 if (*result >= 0)
2769 DWORD len;
2770 RtlMultiByteToUnicodeN( (LPWSTR)lParam, ~0u, &len, buffer, strlen(buffer) + 1 );
2771 *result = len / sizeof(WCHAR) - 1;
2774 else ret = callback( hwnd, msg, wParam, lParam, result, arg );
2775 break;
2777 case EM_GETLINE:
2779 char *ptr, buffer[512];
2780 WORD len = *(WORD *)lParam;
2782 if (!(ptr = get_buffer( buffer, sizeof(buffer), len * 2 ))) break;
2783 *((WORD *)ptr) = len * 2; /* store the length */
2784 ret = callback( hwnd, msg, wParam, (LPARAM)ptr, result, arg );
2785 if (*result)
2787 DWORD reslen;
2788 RtlMultiByteToUnicodeN( (LPWSTR)lParam, len*sizeof(WCHAR), &reslen, ptr, *result );
2789 *result = reslen / sizeof(WCHAR);
2790 if (*result < len) ((LPWSTR)lParam)[*result] = 0;
2792 free_buffer( buffer, ptr );
2794 break;
2796 case WM_GETDLGCODE:
2797 if (lParam)
2799 MSG newmsg = *(MSG *)lParam;
2800 switch(newmsg.message)
2802 case WM_CHAR:
2803 case WM_DEADCHAR:
2804 case WM_SYSCHAR:
2805 case WM_SYSDEADCHAR:
2806 newmsg.wParam = map_wparam_char_WtoA( newmsg.wParam, 1 );
2807 break;
2808 case WM_IME_CHAR:
2809 newmsg.wParam = map_wparam_char_WtoA( newmsg.wParam, 2 );
2810 break;
2812 ret = callback( hwnd, msg, wParam, (LPARAM)&newmsg, result, arg );
2814 else ret = callback( hwnd, msg, wParam, lParam, result, arg );
2815 break;
2817 case WM_CHARTOITEM:
2818 case WM_MENUCHAR:
2819 case WM_CHAR:
2820 case WM_DEADCHAR:
2821 case WM_SYSCHAR:
2822 case WM_SYSDEADCHAR:
2823 case EM_SETPASSWORDCHAR:
2824 ret = callback( hwnd, msg, map_wparam_char_WtoA(wParam,1), lParam, result, arg );
2825 break;
2827 case WM_IME_CHAR:
2828 ret = callback( hwnd, msg, map_wparam_char_WtoA(wParam,2), lParam, result, arg );
2829 break;
2831 case WM_PAINTCLIPBOARD:
2832 case WM_SIZECLIPBOARD:
2833 FIXME_(msg)( "message %s (%04x) needs translation, please report\n",
2834 SPY_GetMsgName(msg, hwnd), msg );
2835 break;
2837 default:
2838 ret = callback( hwnd, msg, wParam, lParam, result, arg );
2839 break;
2842 return ret;
2846 /**********************************************************************
2847 * WINPROC_CallProc16To32A
2849 LRESULT WINPROC_CallProc16To32A( winproc_callback_t callback, HWND16 hwnd, UINT16 msg,
2850 WPARAM16 wParam, LPARAM lParam, LRESULT *result, void *arg )
2852 LRESULT ret;
2853 UINT msg32;
2854 WPARAM wParam32;
2855 HWND hwnd32 = WIN_Handle32( hwnd );
2857 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2858 hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
2860 if (WINPROC_MapMsg16To32A( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2861 return 0;
2863 ret = callback( hwnd32, msg32, wParam32, lParam, result, arg );
2864 *result = WINPROC_UnmapMsg16To32A( hwnd32, msg32, wParam32, lParam, *result );
2865 return ret;
2869 /**********************************************************************
2870 * WINPROC_CallProc16To32W
2872 static LRESULT WINPROC_CallProc16To32W( winproc_callback_t callback, HWND16 hwnd, UINT16 msg,
2873 WPARAM16 wParam, LPARAM lParam, LRESULT *result, void *arg )
2875 LRESULT ret;
2876 UINT msg32;
2877 WPARAM wParam32;
2878 HWND hwnd32 = WIN_Handle32( hwnd );
2880 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2881 hwnd32, SPY_GetMsgName(msg, hwnd32), wParam, lParam);
2883 switch(msg)
2885 case WM_GETTEXT:
2886 case WM_ASKCBFORMATNAME:
2887 case WM_SETTEXT:
2888 case WM_WININICHANGE:
2889 case WM_DEVMODECHANGE:
2890 case CB_DIR:
2891 case LB_DIR:
2892 case LB_ADDFILE:
2893 case EM_REPLACESEL:
2894 ret = WINPROC_CallProcAtoW( callback, hwnd32, msg, wParam, (LPARAM)MapSL(lParam), result, arg );
2895 break;
2897 case WM_GETTEXTLENGTH:
2898 case CB_GETLBTEXTLEN:
2899 case LB_GETTEXTLEN:
2900 ret = WINPROC_CallProcAtoW( callback, hwnd32, msg, wParam, lParam, result, arg );
2901 break;
2903 default:
2904 if (WINPROC_MapMsg16To32W( hwnd32, msg, wParam, &msg32, &wParam32, &lParam ) == -1)
2905 return 0;
2906 ret = callback( hwnd32, msg32, wParam32, lParam, result, arg );
2907 *result = WINPROC_UnmapMsg16To32W( hwnd32, msg32, wParam32, lParam, *result );
2909 return ret;
2913 /**********************************************************************
2914 * __wine_call_wndproc (USER.1010)
2916 LRESULT WINAPI __wine_call_wndproc( HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam,
2917 WINDOWPROC *proc )
2919 LRESULT result;
2921 if (proc->procA)
2922 WINPROC_CallProc16To32A( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
2923 else
2924 WINPROC_CallProc16To32W( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
2925 return result;
2929 /**********************************************************************
2930 * WINPROC_CallProc32ATo16
2932 * Call a 16-bit window procedure, translating the 32-bit args.
2934 LRESULT WINPROC_CallProc32ATo16( winproc_callback16_t callback, HWND hwnd, UINT msg,
2935 WPARAM wParam, LPARAM lParam, LRESULT *result, void *arg )
2937 LRESULT ret;
2938 UINT16 msg16;
2939 WPARAM16 wParam16;
2940 LPARAM lParam16;
2942 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2943 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2945 lParam16 = lParam;
2946 if (WINPROC_MapMsg32ATo16( hwnd, msg, wParam, &msg16, &wParam16, &lParam16 ) == -1)
2947 return 0;
2948 ret = callback( HWND_16(hwnd), msg16, wParam16, lParam16, result, arg );
2949 WINPROC_UnmapMsg32ATo16( hwnd, msg, wParam, lParam, wParam16, lParam16, result );
2950 return ret;
2954 /**********************************************************************
2955 * WINPROC_CallProc32WTo16
2957 * Call a 16-bit window procedure, translating the 32-bit args.
2959 static LRESULT WINPROC_CallProc32WTo16( winproc_callback16_t callback, HWND hwnd, UINT msg,
2960 WPARAM wParam, LPARAM lParam, LRESULT *result, void *arg )
2962 LRESULT ret;
2963 UINT16 msg16;
2964 WPARAM16 wParam16;
2965 LPARAM lParam16;
2967 TRACE_(msg)("(hwnd=%p,msg=%s,wp=%08x,lp=%08lx)\n",
2968 hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam);
2970 lParam16 = lParam;
2971 if (WINPROC_MapMsg32WTo16( hwnd, msg, wParam, &msg16, &wParam16, &lParam16 ) == -1)
2972 return 0;
2973 ret = callback( HWND_16(hwnd), msg16, wParam16, lParam16, result, arg );
2974 WINPROC_UnmapMsg32WTo16( hwnd, msg, wParam, lParam, wParam16, lParam16, result );
2975 return ret;
2979 /**********************************************************************
2980 * CallWindowProc (USER.122)
2982 LRESULT WINAPI CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg,
2983 WPARAM16 wParam, LPARAM lParam )
2985 WINDOWPROC *proc;
2986 LRESULT result;
2988 if (!func) return 0;
2990 if (!(proc = handle16_to_proc( func )))
2991 call_window_proc16( hwnd, msg, wParam, lParam, &result, func );
2992 else if (proc->procA)
2993 WINPROC_CallProc16To32A( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
2994 else if (proc->procW)
2995 WINPROC_CallProc16To32W( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
2996 else
2997 call_window_proc16( hwnd, msg, wParam, lParam, &result, proc->proc16 );
2999 return result;
3003 /**********************************************************************
3004 * CallWindowProcA (USER32.@)
3006 * The CallWindowProc() function invokes the windows procedure _func_,
3007 * with _hwnd_ as the target window, the message specified by _msg_, and
3008 * the message parameters _wParam_ and _lParam_.
3010 * Some kinds of argument conversion may be done, I'm not sure what.
3012 * CallWindowProc() may be used for windows subclassing. Use
3013 * SetWindowLong() to set a new windows procedure for windows of the
3014 * subclass, and handle subclassed messages in the new windows
3015 * procedure. The new windows procedure may then use CallWindowProc()
3016 * with _func_ set to the parent class's windows procedure to dispatch
3017 * the message to the superclass.
3019 * RETURNS
3021 * The return value is message dependent.
3023 * CONFORMANCE
3025 * ECMA-234, Win32
3027 LRESULT WINAPI CallWindowProcA(
3028 WNDPROC func, /* [in] window procedure */
3029 HWND hwnd, /* [in] target window */
3030 UINT msg, /* [in] message */
3031 WPARAM wParam, /* [in] message dependent parameter */
3032 LPARAM lParam /* [in] message dependent parameter */
3034 WINDOWPROC *proc;
3035 LRESULT result;
3037 if (!func) return 0;
3039 if (!(proc = handle_to_proc( func )))
3040 call_window_proc( hwnd, msg, wParam, lParam, &result, func );
3041 else if (proc->procA)
3042 call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procA );
3043 else if (proc->procW)
3044 WINPROC_CallProcAtoW( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
3045 else
3046 WINPROC_CallProc32ATo16( call_window_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3047 return result;
3051 /**********************************************************************
3052 * CallWindowProcW (USER32.@)
3054 * See CallWindowProcA.
3056 LRESULT WINAPI CallWindowProcW( WNDPROC func, HWND hwnd, UINT msg,
3057 WPARAM wParam, LPARAM lParam )
3059 WINDOWPROC *proc;
3060 LRESULT result;
3062 if (!func) return 0;
3064 if (!(proc = handle_to_proc( func )))
3065 call_window_proc( hwnd, msg, wParam, lParam, &result, func );
3066 else if (proc->procW)
3067 call_window_proc( hwnd, msg, wParam, lParam, &result, proc->procW );
3068 else if (proc->procA)
3069 WINPROC_CallProcWtoA( call_window_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
3070 else
3071 WINPROC_CallProc32WTo16( call_window_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3072 return result;
3076 /**********************************************************************
3077 * WINPROC_CallDlgProc16
3079 INT_PTR WINPROC_CallDlgProc16( DLGPROC16 func, HWND16 hwnd, UINT16 msg, WPARAM16 wParam, LPARAM lParam )
3081 WINDOWPROC *proc;
3082 LRESULT result;
3083 INT_PTR ret;
3085 if (!func) return 0;
3087 if (!(proc = handle16_to_proc( (WNDPROC16)func )))
3089 ret = call_dialog_proc16( hwnd, msg, wParam, lParam, &result, func );
3091 else if (proc->procA)
3093 ret = WINPROC_CallProc16To32A( call_dialog_proc, hwnd, msg, wParam, lParam,
3094 &result, proc->procA );
3095 SetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT, result );
3097 else if (proc->procW)
3099 ret = WINPROC_CallProc16To32W( call_dialog_proc, hwnd, msg, wParam, lParam,
3100 &result, proc->procW );
3101 SetWindowLongPtrW( WIN_Handle32(hwnd), DWLP_MSGRESULT, result );
3103 else
3105 ret = call_dialog_proc16( hwnd, msg, wParam, lParam, &result, proc->proc16 );
3107 return ret;
3111 /**********************************************************************
3112 * WINPROC_CallDlgProcA
3114 INT_PTR WINPROC_CallDlgProcA( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
3116 WINDOWPROC *proc;
3117 LRESULT result;
3118 INT_PTR ret;
3120 if (!func) return 0;
3122 if (!(proc = handle_to_proc( (WNDPROC)func )))
3123 ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, func );
3124 else if (proc->procA)
3125 ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procA );
3126 else if (proc->procW)
3128 ret = WINPROC_CallProcAtoW( call_dialog_proc, hwnd, msg, wParam, lParam, &result, proc->procW );
3129 SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3131 else
3133 ret = WINPROC_CallProc32ATo16( call_dialog_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3134 SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3136 return ret;
3140 /**********************************************************************
3141 * WINPROC_CallDlgProcW
3143 INT_PTR WINPROC_CallDlgProcW( DLGPROC func, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
3145 WINDOWPROC *proc;
3146 LRESULT result;
3147 INT_PTR ret;
3149 if (!func) return 0;
3151 if (!(proc = handle_to_proc( (WNDPROC)func )))
3152 ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, func );
3153 else if (proc->procW)
3154 ret = call_dialog_proc( hwnd, msg, wParam, lParam, &result, proc->procW );
3155 else if (proc->procA)
3157 ret = WINPROC_CallProcWtoA( call_dialog_proc, hwnd, msg, wParam, lParam, &result, proc->procA );
3158 SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3160 else
3162 ret = WINPROC_CallProc32WTo16( call_dialog_proc16, hwnd, msg, wParam, lParam, &result, proc->proc16 );
3163 SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, result );
3165 return ret;